Add test for state updates in YouTrackRepository. Also it correctly releases connecti...
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Tue, 13 Jan 2015 13:27:57 +0000 (16:27 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Tue, 13 Jan 2015 13:27:57 +0000 (16:27 +0300)
plugins/tasks/tasks-api/src/com/intellij/tasks/CustomTaskState.java
plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java [new file with mode: 0644]

index dbae96362d7959545b45a6e869ce4b9fef667ecb..cd479e90aee7a29c3b992f9fbdbe18877c4e7e55 100644 (file)
@@ -83,4 +83,9 @@ public class CustomTaskState {
   public void setPredefined(boolean predefined) {
     myPredefined = predefined;
   }
+
+  @Override
+  public String toString() {
+    return "CustomTaskState(id='" + myId + '\'' + ", name='" + myPresentableName + '\'' + ", myPredefined=" + myPredefined + ')';
+  }
 }
index bb1f0c320bcb997b1eedd9e69cfd5172d52be27c..c67fa68343683404883817530c0989d4e80097bf 100644 (file)
@@ -42,6 +42,7 @@ import org.jdom.JDOMException;
 import org.jdom.input.SAXBuilder;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 
 import javax.swing.*;
 import java.io.InputStream;
@@ -88,39 +89,44 @@ public class YouTrackRepository extends BaseRepositoryImpl {
     }
     String requestUrl = "/rest/project/issues/?filter=" + encodeUrl(query) + "&max=" + max + "&updatedAfter" + since;
     HttpMethod method = doREST(requestUrl, false);
-    InputStream stream = method.getResponseBodyAsStream();
+    try {
+      InputStream stream = method.getResponseBodyAsStream();
 
-    // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984
-    String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET);
-    for (int i = 0; i < s.length(); i++) {
-      if (!XMLChar.isValid(s.charAt(i))) {
-        s = s.replace(s.charAt(i), ' ');
+      // todo workaround for http://youtrack.jetbrains.net/issue/JT-7984
+      String s = StreamUtil.readText(stream, CharsetToolkit.UTF8_CHARSET);
+      for (int i = 0; i < s.length(); i++) {
+        if (!XMLChar.isValid(s.charAt(i))) {
+          s = s.replace(s.charAt(i), ' ');
+        }
       }
-    }
 
-    Element element;
-    try {
-      //InputSource source = new InputSource(stream);
-      //source.setEncoding("UTF-8");
-      //element = new SAXBuilder(false).build(source).getRootElement();
-      element = new SAXBuilder(false).build(new StringReader(s)).getRootElement();
-    }
-    catch (JDOMException e) {
-      LOG.error("Can't parse YouTrack response for " + requestUrl, e);
-      throw e;
-    }
-    if ("error".equals(element.getName())) {
-      throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'");
-    }
+      Element element;
+      try {
+        //InputSource source = new InputSource(stream);
+        //source.setEncoding("UTF-8");
+        //element = new SAXBuilder(false).build(source).getRootElement();
+        element = new SAXBuilder(false).build(new StringReader(s)).getRootElement();
+      }
+      catch (JDOMException e) {
+        LOG.error("Can't parse YouTrack response for " + requestUrl, e);
+        throw e;
+      }
+      if ("error".equals(element.getName())) {
+        throw new Exception("Error from YouTrack for " + requestUrl + ": '" + element.getText() + "'");
+      }
 
-    List<Element> children = element.getChildren("issue");
+      List<Element> children = element.getChildren("issue");
 
-    final List<Task> tasks = ContainerUtil.mapNotNull(children, new NullableFunction<Element, Task>() {
-      public Task fun(Element o) {
-        return createIssue(o);
-      }
-    });
-    return tasks.toArray(new Task[tasks.size()]);
+      final List<Task> tasks = ContainerUtil.mapNotNull(children, new NullableFunction<Element, Task>() {
+        public Task fun(Element o) {
+          return createIssue(o);
+        }
+      });
+      return tasks.toArray(new Task[tasks.size()]);
+    }
+    finally {
+      method.releaseConnection();
+    }
   }
 
   @Nullable
@@ -143,10 +149,16 @@ public class YouTrackRepository extends BaseRepositoryImpl {
     method.addParameter("password", getPassword());
     client.getParams().setContentCharset("UTF-8");
     client.executeMethod(method);
-    if (method.getStatusCode() != 200) {
-      throw new Exception("Cannot login: HTTP status code " + method.getStatusCode());
+    String response;
+    try {
+      if (method.getStatusCode() != 200) {
+        throw new Exception("Cannot login: HTTP status code " + method.getStatusCode());
+      }
+      response = method.getResponseBodyAsString(1000);
+    }
+    finally {
+      method.releaseConnection();
     }
-    String response = method.getResponseBodyAsString(1000);
     if (response == null) {
       throw new NullPointerException();
     }
@@ -163,12 +175,23 @@ public class YouTrackRepository extends BaseRepositoryImpl {
 
   @Nullable
   public Task findTask(@NotNull String id) throws Exception {
-    HttpMethod method = doREST("/rest/issue/byid/" + id, false);
-    InputStream stream = method.getResponseBodyAsStream();
-    Element element = new SAXBuilder(false).build(stream).getRootElement();
+    final Element element = fetchRequestAsElement(id);
     return element.getName().equals("issue") ? createIssue(element) : null;
   }
 
+  @TestOnly
+  @NotNull
+  public Element fetchRequestAsElement(@NotNull String id) throws Exception {
+    final HttpMethod method = doREST("/rest/issue/byid/" + id, false);
+    try {
+      final InputStream stream = method.getResponseBodyAsStream();
+      return new SAXBuilder(false).build(stream).getRootElement();
+    }
+    finally {
+      method.releaseConnection();
+    }
+  }
+
 
   HttpMethod doREST(String request, boolean post) throws Exception {
     HttpClient client = login(new PostMethod(getUrl() + "/rest/user/login"));
@@ -189,22 +212,27 @@ public class YouTrackRepository extends BaseRepositoryImpl {
 
   @Override
   public void setTaskState(@NotNull Task task, @NotNull CustomTaskState state) throws Exception {
-    doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true);
+    doREST("/rest/issue/execute/" + task.getId() + "?command=" + encodeUrl("state " + state.getId()), true).releaseConnection();
   }
 
   @NotNull
   @Override
   public Set<CustomTaskState> getAvailableTaskStates(@NotNull Task task) throws Exception {
     final HttpMethod method = doREST("/rest/issue/" + task.getId() + "/execute/intellisense?command=" + encodeUrl("state "), false);
-    final InputStream stream = method.getResponseBodyAsStream();
-    final Element element = new SAXBuilder(false).build(stream).getRootElement();
-    return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function<Element, CustomTaskState>() {
-      @Override
-      public CustomTaskState fun(Element element) {
-        final String stateName = element.getChildText("option");
-        return new CustomTaskState(stateName, stateName);
-      }
-    });
+    try {
+      final InputStream stream = method.getResponseBodyAsStream();
+      final Element element = new SAXBuilder(false).build(stream).getRootElement();
+      return ContainerUtil.map2Set(element.getChild("suggest").getChildren("item"), new Function<Element, CustomTaskState>() {
+        @Override
+        public CustomTaskState fun(Element element) {
+          final String stateName = element.getChildText("option");
+          return new CustomTaskState(stateName, stateName);
+        }
+      });
+    }
+    finally {
+      method.releaseConnection();
+    }
   }
 
   @Nullable
@@ -325,20 +353,30 @@ public class YouTrackRepository extends BaseRepositoryImpl {
   public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception {
     checkVersion();
     final HttpMethod method = doREST("/rest/issue/execute/" + task.getId() + "?command=work+Today+" + timeSpent.replaceAll(" ", "+") + "+" + comment, true);
-    if (method.getStatusCode() != 200) {
-      InputStream stream = method.getResponseBodyAsStream();
-      String message = new SAXBuilder(false).build(stream).getRootElement().getText();
-      throw new Exception(message);
+    try {
+      if (method.getStatusCode() != 200) {
+        InputStream stream = method.getResponseBodyAsStream();
+        String message = new SAXBuilder(false).build(stream).getRootElement().getText();
+        throw new Exception(message);
+      }
+    }
+    finally {
+      method.releaseConnection();
     }
   }
 
   private void checkVersion() throws Exception {
     HttpMethod method = doREST("/rest/workflow/version", false);
-    InputStream stream = method.getResponseBodyAsStream();
-    Element element = new SAXBuilder(false).build(stream).getRootElement();
-    final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0;
-    if (!timeTrackingAvailable) {
-      throw new Exception("This version of Youtrack the time tracking is not supported");
+    try {
+      InputStream stream = method.getResponseBodyAsStream();
+      Element element = new SAXBuilder(false).build(stream).getRootElement();
+      final boolean timeTrackingAvailable = element.getName().equals("version") && VersionComparatorUtil.compare(element.getChildText("version"), "4.1") >= 0;
+      if (!timeTrackingAvailable) {
+        throw new Exception("This version of Youtrack the time tracking is not supported");
+      }
+    }
+    finally {
+      method.releaseConnection();
     }
   }
 
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/YouTrackIntegrationTest.java
new file mode 100644 (file)
index 0000000..f4577b8
--- /dev/null
@@ -0,0 +1,59 @@
+package com.intellij.tasks.integration;
+
+import com.intellij.tasks.CustomTaskState;
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskManagerTestCase;
+import com.intellij.tasks.youtrack.YouTrackRepository;
+import com.intellij.tasks.youtrack.YouTrackRepositoryType;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jdom.Element;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class YouTrackIntegrationTest extends TaskManagerTestCase {
+  private static final String YOUTRACK_4_TEST_SERVER_URL = "http://trackers-tests.labs.intellij.net:8067";
+
+  private static final String REQUEST_WITH_CUSTOM_STATES_ID = "YT4CS-1";
+  private static final CustomTaskState NORTH_STATE = new CustomTaskState("North", "North");
+  private static final CustomTaskState SUBMITTED_STATE = new CustomTaskState("Submitted", "Submitted");
+
+  private YouTrackRepository myRepository;
+
+  public void testCustomTaskStates() throws Exception {
+    final Task task = myRepository.findTask(REQUEST_WITH_CUSTOM_STATES_ID);
+    assertNotNull(task);
+
+    final Set<CustomTaskState> states = myRepository.getAvailableTaskStates(task);
+    final List<String> stateNames = ContainerUtil.map(states, new Function<CustomTaskState, String>() {
+      @Override
+      public String fun(CustomTaskState state) {
+        return state.getPresentableName();
+      }
+    });
+    assertContainsElements(stateNames, "North", "South");
+
+    // ? -> North
+    myRepository.setTaskState(task, NORTH_STATE);
+    Element element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID);
+    assertEquals("North", element.getAttributeValue("state"));
+
+    // North -> Submitted
+    myRepository.setTaskState(task, SUBMITTED_STATE);
+    element = myRepository.fetchRequestAsElement(REQUEST_WITH_CUSTOM_STATES_ID);
+    assertEquals("Submitted", element.getAttributeValue("state"));
+  }
+
+  @Override
+  protected void setUp() throws Exception {
+    super.setUp();
+    myRepository = new YouTrackRepository(new YouTrackRepositoryType());
+    myRepository.setUrl(YOUTRACK_4_TEST_SERVER_URL);
+    myRepository.setUsername("buildtest");
+    myRepository.setPassword("buildtest");
+  }
+}