From 0c79cf40f107097d32563785cf35d723b59a7f26 Mon Sep 17 00:00:00 2001 From: Franc Margallo Date: Fri, 23 Apr 2021 09:25:07 +0800 Subject: [PATCH] Added support for actual start and due dates. Updated Issue bean, and JSON parser and reader methods for serializing and deserializing to and from Issue bean. Added new test cases for parser and builder changes. Added json file containing the test data for parser's new UT item. --- .../taskadapter/redmineapi/bean/Issue.java | 20 ++++++++ .../internal/RedmineJSONBuilder.java | 4 ++ .../internal/RedmineJSONParser.java | 2 + .../internal/RedmineJSONBuilderTest.java | 12 +++++ .../internal/RedmineJSONParserTest.java | 33 +++++++++++-- ...ssues_with_actual_start_and_due_dates.json | 49 +++++++++++++++++++ 6 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/test/resources/issue/redmine_issues_with_actual_start_and_due_dates.json diff --git a/src/main/java/com/taskadapter/redmineapi/bean/Issue.java b/src/main/java/com/taskadapter/redmineapi/bean/Issue.java index 693fea68..62a69f0c 100644 --- a/src/main/java/com/taskadapter/redmineapi/bean/Issue.java +++ b/src/main/java/com/taskadapter/redmineapi/bean/Issue.java @@ -29,6 +29,8 @@ public class Issue implements Identifiable, FluentStyle { public final static Property SUBJECT = new Property<>(String.class, "subject"); public final static Property START_DATE = new Property<>(Date.class, "startDate"); public final static Property DUE_DATE = new Property<>(Date.class, "dueDate"); + public final static Property ACTUAL_START_DATE = new Property<>(Date.class, "actualStartDate"); + public final static Property ACTUAL_DUE_DATE = new Property<>(Date.class, "actualDueDate"); public final static Property CREATED_ON = new Property<>(Date.class, "createdOn"); public final static Property UPDATED_ON = new Property<>(Date.class, "updatedOn"); public final static Property DONE_RATIO = new Property<>(Integer.class, "doneRatio"); @@ -249,6 +251,24 @@ public Issue setDueDate(Date dueDate) { return this; } + public Date getActualStartDate() { + return storage.get(ACTUAL_START_DATE); + } + + public Issue setActualStartDate(Date actualStartDate) { + storage.set(ACTUAL_START_DATE, actualStartDate); + return this; + } + + public Date getActualDueDate() { + return storage.get(ACTUAL_DUE_DATE); + } + + public Issue setActualDueDate(Date actualStartDate) { + storage.set(ACTUAL_DUE_DATE, actualStartDate); + return this; + } + public Integer getAuthorId() { return storage.get(AUTHOR_ID); } diff --git a/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilder.java b/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilder.java index 26435c90..f9168e87 100644 --- a/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilder.java +++ b/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilder.java @@ -229,6 +229,10 @@ public static void writeIssue(final JSONWriter writer, Issue issue) throws JSONE addIfSet(writer, "author_id", storage, Issue.AUTHOR_ID); addIfSet(writer, "start_date", storage, Issue.START_DATE, RedmineDateParser.SHORT_DATE_FORMAT_V2.get()); addIfSet(writer, "due_date", storage, Issue.DUE_DATE, RedmineDateParser.SHORT_DATE_FORMAT_V2.get()); + addIfSet(writer, "actual_start_date", storage, Issue.ACTUAL_START_DATE, + RedmineDateParser.SHORT_DATE_FORMAT_V2.get()); + addIfSet(writer, "actual_due_date", storage, Issue.ACTUAL_DUE_DATE, + RedmineDateParser.SHORT_DATE_FORMAT_V2.get()); addIfSetIdentifiable(writer, "tracker_id", storage, Issue.TRACKER); addIfSet(writer, "description", storage, Issue.DESCRIPTION); diff --git a/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONParser.java b/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONParser.java index 5f1f563e..441c906a 100644 --- a/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONParser.java +++ b/src/main/java/com/taskadapter/redmineapi/internal/RedmineJSONParser.java @@ -209,6 +209,8 @@ public static Issue parseIssue(JSONObject content) throws JSONException { } result.setStartDate(getDateOrNull(content, "start_date")); result.setDueDate(getDateOrNull(content, "due_date")); + result.setActualStartDate(getDateOrNull(content, "actual_start_date")); + result.setActualDueDate(getDateOrNull(content, "actual_due_date")); result.setTracker(JsonInput.getObjectOrNull(content, "tracker", RedmineJSONParser::parseTracker)); result.setDescription(JsonInput.getStringOrNull(content, "description")); result.setCreatedOn(getDateOrNull(content, "created_on")); diff --git a/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilderTest.java b/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilderTest.java index 5805bab5..c11ed462 100644 --- a/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilderTest.java +++ b/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONBuilderTest.java @@ -8,7 +8,9 @@ import com.taskadapter.redmineapi.bean.Version; import org.junit.Test; +import java.util.Calendar; import java.util.Collections; +import java.util.GregorianCalendar; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.Assert.assertTrue; @@ -60,6 +62,16 @@ public void fieldsExplicitlySetToNullAreAddedToIssueJSonAsNull() { assertThat(generatedJSON).contains("\"notes\":null"); } + @Test + public void actualStartAndDueDatesAreSetAndAreAddedToIssueJson() { + Issue issue = new Issue() + .setActualStartDate(new GregorianCalendar(2021, Calendar.APRIL, 23).getTime()) + .setActualDueDate(new GregorianCalendar(2021, Calendar.APRIL, 25).getTime()); + final String generatedJson = RedmineJSONBuilder.toSimpleJSON("some_project_key", issue, RedmineJSONBuilder::writeIssue); + assertThat(generatedJson).contains("\"actual_start_date\":\"2021-04-23\""); + assertThat(generatedJson).contains("\"actual_due_date\":\"2021-04-25\""); + } + @Test public void onlyExplicitlySetFieldsAreAddedToUserJSon() { User user = new User(null) diff --git a/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONParserTest.java b/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONParserTest.java index aadefe2b..2fabde66 100644 --- a/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONParserTest.java +++ b/src/test/java/com/taskadapter/redmineapi/internal/RedmineJSONParserTest.java @@ -22,10 +22,7 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.List; +import java.util.*; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; @@ -39,6 +36,8 @@ public class RedmineJSONParserTest { private static final String FILE_EMPTY_ISSUES = "issue/issues_empty_list.json"; private static final String REDMINE_ISSUES = "issue/redmine_issues.json"; + private static final String REDMINE_ISSUES_WITH_ACTUAL_START_AND_DUE_DATES = + "issue/redmine_issues_with_actual_start_and_due_dates.json"; @Test public void testParseProject1() throws ParseException, JSONException { @@ -93,12 +92,38 @@ public void testCountIssues() { } + @Test + public void testParseIssuesWithActualStartAndDates() { + try { + List issues = loadRedmineIssuesWithActualStartAndDueDates(); + + Assert.assertEquals(3, issues.size()); + Assert.assertEquals(new GregorianCalendar(2020, Calendar.DECEMBER, 15).getTime(), + issues.get(0).getActualStartDate()); + Assert.assertNull(issues.get(0).getActualDueDate()); + Assert.assertEquals(new GregorianCalendar(2020, Calendar.DECEMBER, 15).getTime(), + issues.get(1).getActualStartDate()); + Assert.assertEquals(new GregorianCalendar(2021, Calendar.FEBRUARY, 4).getTime(), + issues.get(1).getActualDueDate()); + Assert.assertNull(issues.get(2).getActualStartDate()); + Assert.assertNull(issues.get(2).getActualDueDate()); + } catch (Exception e) { + fail(e.getMessage()); + } + } + private List loadRedmine11Issues() throws IOException, JSONException { String json = MyIOUtils.getResourceAsString(REDMINE_ISSUES); return JsonInput.getListOrEmpty(RedmineJSONParser.getResponse(json), "issues", RedmineJSONParser::parseIssue); } + private List loadRedmineIssuesWithActualStartAndDueDates() throws IOException { + String json = MyIOUtils.getResourceAsString(REDMINE_ISSUES_WITH_ACTUAL_START_AND_DUE_DATES); + return JsonInput.getListOrEmpty(RedmineJSONParser.getResponse(json), + "issues", RedmineJSONParser::parseIssue); + } + /* Gson parser is bad at detecting errors :( */ @Ignore @Test diff --git a/src/test/resources/issue/redmine_issues_with_actual_start_and_due_dates.json b/src/test/resources/issue/redmine_issues_with_actual_start_and_due_dates.json new file mode 100644 index 00000000..4ce0e682 --- /dev/null +++ b/src/test/resources/issue/redmine_issues_with_actual_start_and_due_dates.json @@ -0,0 +1,49 @@ +{"total_count":3, "limit":25, "offset":0, "issues":[ + { + "id":72, + "project":{"name":"test project","id":27}, + "tracker":{"name":"Bug","id":1}, + "status":{"name":"New","id":1}, + "priority":{"name":"Normal","id":4}, + "author":{"name":"Redmine Admin","id":1}, + "subject":"testGetIssues: Thu Dec 10 13:59:26 PST 2020", + "description":"", + "start_date":"2020-12-14", + "due_date":"2020-12-15", + "actual_start_date": "2020-12-15", + "done_ratio":0, + "created_on":"2020-12-10T13:59:25Z", + "updated_on":"2020-12-10T13:59:25Z" + }, + { + "id":71, + "project":{"name":"test project","id":26}, + "tracker":{"name":"Bug","id":1}, + "status":{"name":"New","id":1}, + "priority":{"name":"Normal","id":4}, + "author":{"name":"Redmine Admin","id":1}, + "subject":"testGetIssues: Fri Dec 11 13:57:58 PST 2011", + "description":"", + "start_date": "2020-12-16", + "due_date": "2021-01-12", + "actual_start_date": "2020-12-15", + "actual_due_date": "2021-02-04", + "done_ratio":0, + "created_on":"2020-12-11T14:58:59Z", + "updated_on":"2020-12-11T16:57:59Z" + }, + { + "id":70, + "project":{"name":"test project","id":25}, + "tracker":{"name":"Bug","id":1}, + "status":{"name":"New","id":1}, + "priority":{"name":"Normal","id":4}, + "author":{"name":"Redmine Admin","id":1}, + "subject":"Issue Fri Dec 11 13:57:22 PST 2020", + "description":"", + "start_date":"2020-12-12", + "done_ratio":0, + "created_on":"2020-12-11T13:57:20Z", + "updated_on":"2020-12-11T13:57:20Z" + }] +}