Merge branch 'mikhail.golubev/configurable-issues-states'
[idea/community.git] / plugins / tasks / tasks-tests / test / com / intellij / tasks / integration / JiraIntegrationTest.java
index 24a3be38c265eecb60cd460e8aca9424acd9daee..67bbb0138f36d0f1396cf0784adc2485fa98f809 100644 (file)
@@ -25,10 +25,20 @@ import com.intellij.tasks.impl.TaskUtil;
 import com.intellij.tasks.jira.JiraRepository;
 import com.intellij.tasks.jira.JiraRepositoryType;
 import com.intellij.tasks.jira.JiraVersion;
+import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.xmlrpc.CommonsXmlRpcTransport;
+import org.apache.xmlrpc.XmlRpcClient;
+import org.apache.xmlrpc.XmlRpcRequest;
+import org.intellij.lang.annotations.Language;
 import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
 
-import java.util.Date;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
 
 import static com.intellij.tasks.jira.JiraRemoteApi.ApiType.REST_2_0;
 import static com.intellij.tasks.jira.JiraRemoteApi.ApiType.REST_2_0_ALPHA;
@@ -43,12 +53,16 @@ public class JiraIntegrationTest extends TaskManagerTestCase {
    * JIRA 4.4.5, REST API 2.0.alpha1
    */
   @NonNls private static final String JIRA_4_TEST_SERVER_URL = "http://idea-qa-task-2.labs.intellij.net:8014";
+
   /**
    * JIRA 5.0.6, REST API 2.0
    */
   @NonNls private static final String JIRA_5_TEST_SERVER_URL = "http://trackers-tests.labs.intellij.net:8015";
-  public static final CustomTaskState REOPENED_CUSTOM_STATE = new CustomTaskState("3", "Reopened");
-  public static final CustomTaskState RESOLVED_CUSTOM_STATE = new CustomTaskState("5:Fixed", "Fixed");
+
+  private static final SimpleDateFormat SHORT_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+  static {
+    SHORT_TIMESTAMP_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
 
   private JiraRepository myRepository;
 
@@ -116,19 +130,74 @@ public class JiraIntegrationTest extends TaskManagerTestCase {
     }
   }
 
-  // TODO move to on-Demand-specific tests
-  //public void testBasicAuthenticationDisabling() throws Exception {
-  //  assertTrue("Basic authentication should be enabled at first", myRepository.isUseHttpAuthentication());
-  //  myRepository.findTask("PRJONE-1");
-  //  assertFalse("Basic authentication should be disabled once JSESSIONID cookie was received", myRepository.isUseHttpAuthentication());
-  //  HttpClient client = myRepository.getHttpClient();
-  //  assertFalse(client.getParams().isAuthenticationPreemptive());
-  //  assertNull(client.getState().getCredentials(AuthScope.ANY));
-  //}
+  // Our test servers poorly handles frequent state updates of single dedicated issue. As a workaround
+  // we create new issue for every test run (via XML-RPC API in JIRA 4.x and REST API in JIRA 5+)
 
-  public void testSetTaskState() throws Exception {
-    changeStateAndCheck(JIRA_4_TEST_SERVER_URL, "PRJONE-8");
-    changeStateAndCheck(JIRA_5_TEST_SERVER_URL, "UT-8");
+  public void testSetTaskStateInJira5() throws Exception {
+    myRepository.setUrl(JIRA_5_TEST_SERVER_URL);
+    final String id = createIssueViaRestApi("BTSU", "Test issue for state updates (" + SHORT_TIMESTAMP_FORMAT.format(new Date()) + ")");
+    changeTaskStateAndCheck(id);
+  }
+
+  // We can use XML-RPC in JIRA 5+ too, but nonetheless it's useful to have REST-based implementation as well
+  private String createIssueViaRestApi(@NotNull String project, @NotNull String summary) throws Exception {
+    final HttpClient client = myRepository.getHttpClient();
+    final PostMethod method = new PostMethod(myRepository.getUrl() + "/rest/api/latest/issue");
+    try {
+      // For simplicity assume that project, summary and username don't contain illegal characters
+      @Language("JSON")
+      final String json = "{\"fields\": {\n" +
+                          "  \"project\": {\n" +
+                          "    \"key\": \"" + project + "\"\n" +
+                          "  },\n" +
+                          "  \"issuetype\": {\n" +
+                          "    \"name\": \"Bug\"\n" +
+                          "  },\n" +
+                          "  \"assignee\": {\n" +
+                          "    \"name\": \"" + myRepository.getUsername() + "\"\n" +
+                          "  },\n" +
+                          "  \"summary\": \"" + summary + "\"\n" +
+                          "}}";
+      method.setRequestEntity(new StringRequestEntity(json, "application/json", "utf-8"));
+      client.executeMethod(method);
+      return new Gson().fromJson(method.getResponseBodyAsString(), JsonObject.class).get("id").getAsString();
+    }
+    finally {
+      method.releaseConnection();
+    }
+  }
+
+  public void testSetTaskStateInJira4() throws Exception {
+    myRepository.setUrl(JIRA_4_TEST_SERVER_URL);
+    final String id = createIssueViaXmlRpc("BTSU", "Test issue for state updates (" + SHORT_TIMESTAMP_FORMAT.format(new Date()) + ")");
+    changeTaskStateAndCheck(id);
+  }
+
+  @SuppressWarnings("UseOfObsoleteCollectionType")
+  @NotNull
+  private String createIssueViaXmlRpc(@NotNull String project, @NotNull String summary) throws Exception {
+    final URL url = new URL(myRepository.getUrl() + "/rpc/xmlrpc");
+    final XmlRpcClient xmlRpcClient = new XmlRpcClient(url);
+    final Map<String, Object> issue = new Hashtable<String, Object>();
+    issue.put("summary", summary);
+    issue.put("project", project);
+    issue.put("assignee", myRepository.getUsername());
+    issue.put("type", 1); // Bug
+    issue.put("state", 1); // Open
+
+    final Vector<Object> params = new Vector<Object>(Arrays.asList("", issue)); // empty token because of HTTP basic auth
+    final Hashtable result = (Hashtable)xmlRpcClient.execute(new XmlRpcRequest("jira1.createIssue", params),
+                                                             new CommonsXmlRpcTransport(url, myRepository.getHttpClient()));
+    return (String)result.get("key");
+  }
+
+  private void changeTaskStateAndCheck(@NotNull String issueKey) throws Exception {
+    final Task original = myRepository.findTask(issueKey);
+    assertNotNull(original);
+    myRepository.setTaskState(original, new CustomTaskState("4", "In Progress"));
+    final Task updated = myRepository.findTask(issueKey);
+    assertNotNull(updated);
+    assertEquals(TaskState.IN_PROGRESS, updated.getState());
   }
 
   public void testSetTimeSpend() throws Exception {
@@ -158,31 +227,6 @@ public class JiraIntegrationTest extends TaskManagerTestCase {
     assertEquals(minutes * 60, last.get("timeSpentSeconds").getAsInt());
   }
 
-  private void changeStateAndCheck(String url, String key) throws Exception {
-    myRepository.setUrl(url);
-    Task task = myRepository.findTask(key);
-    assertNotNull("Test task not found", task);
-    // set required initial state, if was left wrong
-    if (task.getState() != TaskState.REOPENED) {
-      myRepository.setTaskState(task, REOPENED_CUSTOM_STATE);
-    }
-    try {
-      //assertEquals("Wrong initial state of test issue: " + key, TaskState.REOPENED, task.getState());
-      myRepository.setTaskState(task, RESOLVED_CUSTOM_STATE);
-      task = myRepository.findTask(key);
-      assertEquals(task.getState(), TaskState.RESOLVED);
-    }
-    finally {
-      try {
-        // always attempt to restore original state of the issue
-        myRepository.setTaskState(task, REOPENED_CUSTOM_STATE);
-      }
-      catch (Exception ignored) {
-        // empty
-      }
-    }
-  }
-
   public void testParseVersionNumbers() throws Exception {
     assertEquals(new JiraVersion("6.1-OD-09-WN").toString(), "6.1.9");
     assertEquals(new JiraVersion("5.0.6").toString(), "5.0.6");