diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java index 757baaec9ae1..af300e0f792e 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java @@ -15,8 +15,11 @@ */ package com.intellij.tasks.jira; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import com.google.gson.*; +import com.intellij.tasks.impl.TaskUtil; + +import java.lang.reflect.Type; +import java.util.Date; /** * @author Mikhail Golubev @@ -26,8 +29,14 @@ public class JiraUtil { private static Gson buildGson() { GsonBuilder gson = new GsonBuilder(); - // ISO-8601 with timezone info - gson.setDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZ"); + gson.registerTypeAdapter(Date.class, new DateDeserializer()); return gson.create(); } + + private static class DateDeserializer implements JsonDeserializer { + @Override + public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return TaskUtil.parseDate(json.getAsString()); + } + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java index 697e71be7a02..4678b46389ad 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java @@ -188,7 +188,6 @@ public class RedmineRepository extends BaseRepositoryImpl { parsed = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US).parse(date); } catch (ParseException e) { - LOG.warn("Unparseable date: '" + date + "'. Trying ISO-8601 format instead."); parsed = TaskUtil.parseDate(date); } return parsed; diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/DateParsingTest.java similarity index 98% rename from plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java rename to plugins/tasks/tasks-tests/test/com/intellij/tasks/DateParsingTest.java index d9d0a320924d..6b18d96e0f8c 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskUtilTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/DateParsingTest.java @@ -14,7 +14,7 @@ import static org.junit.Assert.assertNull; /** * @author Mikhail Golubev */ -public class TaskUtilTest { +public class DateParsingTest { private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); static { FORMATTER.setTimeZone(TimeZone.getTimeZone("GMT")); diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskTestUtil.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskTestUtil.java new file mode 100644 index 000000000000..a2fd54ff898d --- /dev/null +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskTestUtil.java @@ -0,0 +1,195 @@ +package com.intellij.tasks; + +import com.intellij.tasks.impl.TaskUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Date; +import java.util.List; + +import static junit.framework.Assert.assertTrue; + +/** + * @author Mikhail Golubev + */ +public class TaskTestUtil { + public static void assertTasksEqual(@NotNull Task t1, @NotNull Task t2) { + assertTrue(TaskUtil.tasksEqual(t1, t2)); + } + + public static void assertTasksEqual(@NotNull List t1, @NotNull List t2) { + assertTrue(TaskUtil.tasksEqual(t1, t2)); + } + + public static void assertTasksEqual(@NotNull Task[] t1, @NotNull Task[] t2) { + assertTrue(TaskUtil.tasksEqual(t1, t2)); + } + + /** + * Auxiliary builder class to simplify comparison of server responses parsing results. + * + * @see #assertTasksEqual(Task, Task) + */ + public static class TaskBuilder extends Task { + private String myId; + private String mySummary; + private TaskRepository myRepository; + private String myDescription; + private String myIssueUrl; + private Comment[] myComments = Comment.EMPTY_ARRAY; + private Icon myIcon; + private TaskType myType = TaskType.OTHER; + private TaskState myState; + private Date myCreated; + private Date myUpdated; + private boolean myClosed = false; + private boolean myIssue = true; + + public TaskBuilder(@NotNull String id, @NotNull String summary) { + myId = id; + mySummary = summary; + } + + public TaskBuilder withRepository(@Nullable TaskRepository repository) { + myRepository = repository; + return this; + } + + public TaskBuilder withDescription(@Nullable String description) { + myDescription = description; + return this; + } + + public TaskBuilder withIssueUrl(@Nullable String issueUrl) { + myIssueUrl = issueUrl; + return this; + } + + public TaskBuilder withComments(@NotNull Comment... comments) { + myComments = comments; + return this; + } + + public TaskBuilder withClosed(boolean isClosed) { + myClosed = isClosed; + return this; + } + + public TaskBuilder withIssue(boolean isIssue) { + myIssue = isIssue; + return this; + } + + public TaskBuilder withUpdated(@Nullable Date updated) { + myUpdated = updated; + return this; + } + + public TaskBuilder withUpdated(@NotNull String updated) { + return withUpdated(TaskUtil.parseDate(updated)); + } + + public TaskBuilder withCreated(@Nullable Date created) { + myCreated = created; + return this; + } + + public TaskBuilder withCreated(@NotNull String created) { + return withCreated(TaskUtil.parseDate(created)); + } + + public TaskBuilder withType(@NotNull TaskType type) { + myType = type; + return this; + } + + public TaskBuilder withState(@Nullable TaskState state) { + myState = state; + return this; + } + + public TaskBuilder withIcon(@Nullable Icon icon) { + myIcon = icon; + return this; + } + + @NotNull + @Override + public String getId() { + return myId; + } + + @NotNull + @Override + public String getSummary() { + return mySummary; + } + + @Nullable + @Override + public String getDescription() { + return myDescription; + } + + @NotNull + @Override + public Comment[] getComments() { + return myComments; + } + + @NotNull + @Override + public Icon getIcon() { + return myIcon == null? myRepository.getIcon() : myIcon; + } + + @NotNull + @Override + public TaskType getType() { + return myType; + } + + @Nullable + @Override + public TaskState getState() { + return myState; + } + + @Nullable + @Override + public Date getUpdated() { + return myUpdated; + } + + @Nullable + @Override + public Date getCreated() { + return myCreated; + } + + @Override + public boolean isClosed() { + return myClosed; + } + + @Override + public boolean isIssue() { + return myIssue; + } + + @Nullable + @Override + public String getIssueUrl() { + return myIssueUrl; + } + + @Nullable + @Override + public TaskRepository getRepository() { + return myRepository; + } + } + + +} diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaIntegrationTest.java index 57847117965f..dce734801199 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaIntegrationTest.java @@ -16,6 +16,7 @@ package com.intellij.tasks.integration; import com.intellij.tasks.Task; +import com.intellij.tasks.TaskTestUtil; import com.intellij.tasks.generic.GenericRepository; import com.intellij.tasks.generic.GenericRepositoryType; import com.intellij.tasks.generic.GenericTask; @@ -26,6 +27,9 @@ import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.List; +import static com.intellij.tasks.TaskTestUtil.TaskBuilder; +import static com.intellij.tasks.TaskTestUtil.assertTasksEqual; + /** * @author Mikhail Golubev */ @@ -97,11 +101,13 @@ public class AsanaIntegrationTest extends GenericSubtypeTestCase { public void testParsingSingleTask() throws Exception { Task task = myRepository.getActiveResponseHandler().parseIssue(SINGLE_TASK_RESPONSE); assertNotNull(task); - GenericTask expected = new GenericTask("7119324862208", "Task #2", myRepository); - expected.setDescription("This is task #2 description"); - expected.setCreated(TaskUtil.parseDate("2013-08-02T12:13:20.372Z")); - expected.setUpdated(TaskUtil.parseDate("2013-08-21T16:36:36.290Z")); - expected.setClosed(true); - assertTasksEqual(expected, task); + assertTasksEqual( + new TaskBuilder("7119324862208", "Task #2") + .withRepository(myRepository) + .withDescription("This is task #2 description") + .withClosed(true) + .withCreated("2013-08-02T12:13:20.372Z") + .withUpdated("2013-08-21T16:36:36.290Z"), + task); } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java index 42b3e78d2339..59e365e7bd55 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java @@ -16,12 +16,16 @@ package com.intellij.tasks.integration; import com.intellij.tasks.Task; +import com.intellij.tasks.TaskTestUtil; import com.intellij.tasks.generic.GenericRepository; import com.intellij.tasks.generic.GenericRepositoryType; import com.intellij.tasks.generic.GenericTask; import com.intellij.tasks.impl.TaskUtil; import org.jetbrains.annotations.NotNull; +import static com.intellij.tasks.TaskTestUtil.TaskBuilder; +import static com.intellij.tasks.TaskTestUtil.assertTasksEqual; + /** * @author Dmitry Avdeev * Date: 4/1/13 @@ -71,10 +75,14 @@ public class AssemblaIntegrationTest extends GenericSubtypeTestCase { public void testParsingTaskList() throws Exception { Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(TASK_LIST_RESPONSE, 50); - GenericTask expected = new GenericTask("50351983", "\u041F\u0440\u0438\u0432\u0435\u0442", myRepository); - expected.setDescription(""); - expected.setUpdated(TaskUtil.parseDate("2013-04-01T10:48:19+03:00")); - expected.setCreated(TaskUtil.parseDate("2013-04-01T10:45:06+03:00")); - assertTasksEqual(new Task[] {expected}, tasks); + assertTasksEqual( + new Task[]{ + new TaskBuilder("50351983", "\u041F\u0440\u0438\u0432\u0435\u0442") + .withRepository(myRepository) + .withDescription("") + .withUpdated("2013-04-01T10:48:19+03:00") + .withCreated("2013-04-01T10:45:06+03:00") + }, + tasks); } } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GenericSubtypeTestCase.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GenericSubtypeTestCase.java index 459e67ccfa85..92ac54bb65df 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GenericSubtypeTestCase.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GenericSubtypeTestCase.java @@ -24,18 +24,4 @@ public abstract class GenericSubtypeTestCase extends TaskManagerTestCase { @NotNull protected abstract GenericRepository createRepository(GenericRepositoryType genericType); - - protected static void assertTasksEqual(@NotNull Task t1, @NotNull Task t2) { - assertTrue(TaskUtil.tasksEqual(t1, t2)); - } - - protected static void assertTasksEqual(@NotNull List t1, @NotNull List t2) { - assertTrue(TaskUtil.tasksEqual(t1, t2)); - } - - protected static void assertTasksEqual(@NotNull Task[] t1, @NotNull Task[] t2) { - assertTrue(TaskUtil.tasksEqual(t1, t2)); - } - - } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java index 1b4a3d68b2ba..75a792d7e493 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java @@ -90,12 +90,29 @@ public class JiraIntegrationTest extends TaskManagerTestCase { private void changeStateAndCheck(String url, String key) throws Exception { myRepository.setUrl(url); Task task = myRepository.findTask(key); - myRepository.setTaskState(task, TaskState.IN_PROGRESS); - assertEquals(myRepository.findTask(key).getState(), TaskState.IN_PROGRESS); - myRepository.setTaskState(task, TaskState.RESOLVED); - assertEquals(myRepository.findTask(key).getState(), TaskState.RESOLVED); - myRepository.setTaskState(task, TaskState.REOPENED); - assertEquals(myRepository.findTask(key).getState(), TaskState.REOPENED); + try { + myRepository.setTaskState(task, TaskState.IN_PROGRESS); + assertEquals(myRepository.findTask(key).getState(), TaskState.IN_PROGRESS); + myRepository.setTaskState(task, TaskState.RESOLVED); + assertEquals(myRepository.findTask(key).getState(), TaskState.RESOLVED); + myRepository.setTaskState(task, TaskState.REOPENED); + assertEquals(myRepository.findTask(key).getState(), TaskState.REOPENED); + } + catch (Exception e) { + // always attempt to restore original state of the issue + try { + // transition to Resolved state usually is possible from any other + myRepository.setTaskState(task, TaskState.RESOLVED); + } + catch (Exception ignored) { + } + try { + myRepository.setTaskState(task, TaskState.REOPENED); + } + catch (Exception ignored) { + } + throw e; + } } @Override