Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wolf2019-12-28 22:01:22 +0000
committerMichael Keppler2019-12-29 17:42:43 +0000
commitc53b9b34fb56f3e80a0e0bfb17625fb09fa0e49d (patch)
tree5da2f260125cbab9a466cc5ddc98baf34b36a12f
parent56560c75b1658df51a09f6f9c442741743d6ff63 (diff)
downloadegit-github-c53b9b34fb56f3e80a0e0bfb17625fb09fa0e49d.tar.gz
egit-github-c53b9b34fb56f3e80a0e0bfb17625fb09fa0e49d.tar.xz
egit-github-c53b9b34fb56f3e80a0e0bfb17625fb09fa0e49d.zip
Milestone creation needs a special DTO
Milestone creation accepts only a stripped-down creation DTO, not a full Milestone object.[1] This is similar to issue creation. Editing a milestone had the same problem; the update endpoint also accepts only the same DTO.[2] Create a DTO parameter map containing only the needed fields. [1] https://developer.github.com/v3/issues/milestones/#create-a-milestone [2] https://developer.github.com/v3/issues/milestones/#update-a-milestone Bug: 558649 Change-Id: I3b244b93822bc9596556fa7f712d61bcf5fe4586 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/MilestoneServiceTest.java189
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/MilestoneService.java110
2 files changed, 255 insertions, 44 deletions
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/MilestoneServiceTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/MilestoneServiceTest.java
index d5cf5b83..ab804ca3 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/MilestoneServiceTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/MilestoneServiceTest.java
@@ -1,5 +1,6 @@
/*******************************************************************************
- * Copyright (c) 2011 Christian Trutz
+ * Copyright (c) 2011, 2019 Christian Trutz and others.
+ *
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -12,22 +13,29 @@
*******************************************************************************/
package org.eclipse.egit.github.core.tests;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
import org.eclipse.egit.github.core.Milestone;
import org.eclipse.egit.github.core.RepositoryId;
import org.eclipse.egit.github.core.client.GitHubClient;
import org.eclipse.egit.github.core.client.GitHubRequest;
import org.eclipse.egit.github.core.client.GitHubResponse;
+import org.eclipse.egit.github.core.client.GsonUtils;
import org.eclipse.egit.github.core.service.MilestoneService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@@ -43,6 +51,9 @@ public class MilestoneServiceTest {
@Mock
private GitHubResponse response;
+ @Captor
+ private ArgumentCaptor<Object> dtoCaptor;
+
private MilestoneService milestoneService;
/**
@@ -203,6 +214,16 @@ public class MilestoneServiceTest {
}
/**
+ * Create milestone with an empty milestone
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void createMilestoneEmptyMilestone() throws IOException {
+ milestoneService.createMilestone("user", "repo", new Milestone());
+ }
+
+ /**
* Create valid milestone
*
* @throws IOException
@@ -210,9 +231,24 @@ public class MilestoneServiceTest {
@Test
public void createMilestone() throws IOException {
Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestoneService.createMilestone("user", "repo", milestone);
+ verify(gitHubClient).post(eq("/repos/user/repo/milestones"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"A title\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Create invalid milestone without title.
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void createMilestoneNoTitle() throws IOException {
+ Milestone milestone = new Milestone();
+ milestone.setDescription("A description");
milestoneService.createMilestone("user", "repo", milestone);
- verify(gitHubClient).post("/repos/user/repo/milestones", milestone,
- Milestone.class);
}
/**
@@ -224,9 +260,89 @@ public class MilestoneServiceTest {
public void createMilestoneWithRepositoryId() throws IOException {
RepositoryId id = new RepositoryId("user", "repo");
Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestone.setDescription("A description");
+ milestoneService.createMilestone(id, milestone);
+ verify(gitHubClient).post(eq("/repos/user/repo/milestones"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"A title\",\"description\":\"A description\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Create an invalid milestone with a wrong state.
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void createMilestoneInvalidState() throws IOException {
+ RepositoryId id = new RepositoryId("user", "repo");
+ Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestone.setState("bogus");
+ milestoneService.createMilestone(id, milestone);
+ }
+
+ /**
+ * Create valid closed milestone.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void createMilestoneClosed() throws IOException {
+ RepositoryId id = new RepositoryId("user", "repo");
+ Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestone.setState("closed");
+ milestoneService.createMilestone(id, milestone);
+ verify(gitHubClient).post(eq("/repos/user/repo/milestones"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"A title\",\"state\":\"closed\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Create valid open milestone.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void createMilestoneOpen() throws IOException {
+ RepositoryId id = new RepositoryId("user", "repo");
+ Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestone.setState("open");
+ milestoneService.createMilestone(id, milestone);
+ verify(gitHubClient).post(eq("/repos/user/repo/milestones"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"A title\",\"state\":\"open\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Create valid open milestone.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void createMilestoneFull() throws IOException {
+ RepositoryId id = new RepositoryId("user", "repo");
+ Milestone milestone = new Milestone();
+ milestone.setTitle("A title");
+ milestone.setDescription("A description");
+ milestone.setState("open");
+ Calendar cal = Calendar.getInstance();
+ cal.set(2019, 1, 1, 12, 0, 0);
+ Date date = Date.from(cal.toInstant());
+ milestone.setDueOn(date);
+ milestone.setCreatedAt(date);
+ String serializedDate = GsonUtils.getGson().toJson(date);
milestoneService.createMilestone(id, milestone);
- verify(gitHubClient).post("/repos/user/repo/milestones", milestone,
- Milestone.class);
+ verify(gitHubClient).post(eq("/repos/user/repo/milestones"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"A title\",\"state\":\"open\",\"description\":\"A description\",\"due_on\":"
+ + serializedDate + "}", GsonUtils.getGson().toJson(dto));
}
/**
@@ -405,11 +521,21 @@ public class MilestoneServiceTest {
* @throws IOException
*/
@Test(expected = IllegalArgumentException.class)
- public void editMilestoneNullUser() throws IOException {
+ public void editMilestoneNullMilestone() throws IOException {
milestoneService.editMilestone(RepositoryId.create("a", "b"), null);
}
/**
+ * Edit milestone with empty milestone
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void editMilestoneEmptyMilestone() throws IOException {
+ milestoneService.editMilestone(RepositoryId.create("a", "b"), new Milestone());
+ }
+
+ /**
* Edit milestone
*
* @throws IOException
@@ -421,7 +547,54 @@ public class MilestoneServiceTest {
milestone.setTitle("a milestone");
milestoneService
.editMilestone(RepositoryId.create("a", "b"), milestone);
- verify(gitHubClient).post("/repos/a/b/milestones/1234", milestone,
- Milestone.class);
+ verify(gitHubClient).post(eq("/repos/a/b/milestones/1234"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"a milestone\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Edit milestone description
+ *
+ * @throws IOException
+ */
+ @Test
+ public void editMilestoneDescription() throws IOException {
+ Milestone milestone = new Milestone();
+ milestone.setNumber(1234);
+ milestone.setDescription("A description");
+ milestoneService
+ .editMilestone(RepositoryId.create("a", "b"), milestone);
+ verify(gitHubClient).post(eq("/repos/a/b/milestones/1234"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"description\":\"A description\"}", GsonUtils.getGson().toJson(dto));
+ }
+
+ /**
+ * Edit milestone with all fields
+ *
+ * @throws IOException
+ */
+ @Test
+ public void editMilestoneFull() throws IOException {
+ Milestone milestone = new Milestone();
+ milestone.setNumber(1234);
+ milestone.setTitle("a milestone");
+ milestone.setDescription("a description");
+ milestone.setState("closed");
+ Calendar cal = Calendar.getInstance();
+ cal.set(2019, 1, 1, 12, 0, 0);
+ Date date = Date.from(cal.toInstant());
+ milestone.setDueOn(date);
+ milestone.setCreatedAt(date);
+ String serializedDate = GsonUtils.getGson().toJson(date);
+ milestoneService
+ .editMilestone(RepositoryId.create("a", "b"), milestone);
+ verify(gitHubClient).post(eq("/repos/a/b/milestones/1234"), dtoCaptor.capture(),
+ eq(Milestone.class));
+ Object dto = dtoCaptor.getValue();
+ assertEquals("{\"title\":\"a milestone\",\"state\":\"closed\",\"description\":\"a description\",\"due_on\":"
+ + serializedDate + "}", GsonUtils.getGson().toJson(dto));
}
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/MilestoneService.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/MilestoneService.java
index a6546f48..fe557d33 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/MilestoneService.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/MilestoneService.java
@@ -1,5 +1,6 @@
/*******************************************************************************
- * Copyright (c) 2011 GitHub Inc.
+ * Copyright (c) 2011, 2019 GitHub Inc. and others.
+ *
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
@@ -19,7 +20,10 @@ import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import org.eclipse.egit.github.core.IRepositoryIdProvider;
import org.eclipse.egit.github.core.Milestone;
@@ -36,6 +40,14 @@ import org.eclipse.egit.github.core.client.PagedRequest;
*/
public class MilestoneService extends GitHubService {
+ private static final String TITLE = "title"; //$NON-NLS-1$
+
+ private static final String DESCRIPTION = "description"; //$NON-NLS-1$
+
+ private static final String DUE_ON = "due_on"; //$NON-NLS-1$
+
+ private static final String STATE = "state"; //$NON-NLS-1$
+
/**
* Create milestone service
*/
@@ -87,13 +99,12 @@ public class MilestoneService extends GitHubService {
private List<Milestone> getMilestones(String id, String state)
throws IOException {
- StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
- uri.append('/').append(id);
- uri.append(SEGMENT_MILESTONES);
+ String uri = SEGMENT_REPOS + '/' + id + SEGMENT_MILESTONES;
PagedRequest<Milestone> request = createPagedRequest();
- if (state != null)
+ if (state != null) {
request.setParams(Collections.singletonMap(
IssueService.FILTER_STATE, state));
+ }
request.setUri(uri).setType(new TypeToken<List<Milestone>>() {
// make protected type visible
}.getType());
@@ -136,15 +147,49 @@ public class MilestoneService extends GitHubService {
return createMilestone(repoId, milestone);
}
+ private Map<String, Object> createParams(Milestone milestone,
+ boolean titleRequired) {
+ Map<String, Object> params = new LinkedHashMap<>();
+ String value = milestone.getTitle();
+ if (titleRequired && value == null) {
+ throw new IllegalArgumentException(
+ "Milestone title must not be null"); //$NON-NLS-1$
+ }
+ if (value != null) {
+ params.put(TITLE, value);
+ }
+ value = milestone.getState();
+ if (value != null) {
+ if (!"open".equals(value) && !"closed".equals(value)) { //$NON-NLS-1$ //$NON-NLS-2$
+ throw new IllegalArgumentException(
+ "Milestone state must be 'open' or 'closed', or null for default ('open')"); //$NON-NLS-1$
+ }
+ params.put(STATE, value);
+ }
+ value = milestone.getDescription();
+ if (value != null) {
+ params.put(DESCRIPTION, value);
+ }
+ Date date = milestone.getDueOn();
+ if (date != null) {
+ params.put(DUE_ON, date);
+ }
+ if (params.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Milestone operation requires at least one of title, description, state, or due date"); //$NON-NLS-1$
+ }
+ return params;
+ }
+
private Milestone createMilestone(String id, Milestone milestone)
throws IOException {
- if (milestone == null)
+ if (milestone == null) {
throw new IllegalArgumentException("Milestone cannot be null"); //$NON-NLS-1$
+ }
+ String uri = SEGMENT_REPOS + '/' + id + SEGMENT_MILESTONES;
- StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
- uri.append('/').append(id);
- uri.append(SEGMENT_MILESTONES);
- return client.post(uri.toString(), milestone, Milestone.class);
+ Map<String, Object> dto = createParams(milestone, true);
+ return client.post(uri, dto, Milestone.class);
}
/**
@@ -214,15 +259,12 @@ public class MilestoneService extends GitHubService {
}
private Milestone getMilestone(String id, String number) throws IOException {
- if (number == null)
- throw new IllegalArgumentException("Milestone cannot be null"); //$NON-NLS-1$
- if (number.length() == 0)
- throw new IllegalArgumentException("Milestone cannot be empty"); //$NON-NLS-1$
-
- StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
- uri.append('/').append(id);
- uri.append(SEGMENT_MILESTONES);
- uri.append('/').append(number);
+ if (number == null || number.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Milestone cannot be null or empty"); //$NON-NLS-1$
+ }
+ String uri = SEGMENT_REPOS + '/' + id + SEGMENT_MILESTONES + '/'
+ + number;
GitHubRequest request = createRequest();
request.setUri(uri);
request.setType(Milestone.class);
@@ -285,16 +327,13 @@ public class MilestoneService extends GitHubService {
private void deleteMilestone(String id, String milestone)
throws IOException {
- if (milestone == null)
- throw new IllegalArgumentException("Milestone cannot be null"); //$NON-NLS-1$
- if (milestone.length() == 0)
- throw new IllegalArgumentException("Milestone cannot be empty"); //$NON-NLS-1$
-
- StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
- uri.append('/').append(id);
- uri.append(SEGMENT_MILESTONES);
- uri.append('/').append(milestone);
- client.delete(uri.toString());
+ if (milestone == null || milestone.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Milestone cannot be null or empty"); //$NON-NLS-1$
+ }
+ String uri = SEGMENT_REPOS + '/' + id + SEGMENT_MILESTONES + '/'
+ + milestone;
+ client.delete(uri);
}
/**
@@ -308,14 +347,13 @@ public class MilestoneService extends GitHubService {
public Milestone editMilestone(IRepositoryIdProvider repository,
Milestone milestone) throws IOException {
String repoId = getId(repository);
- if (milestone == null)
+ if (milestone == null) {
throw new IllegalArgumentException("Milestone cannot be null"); //$NON-NLS-1$
+ }
+ String uri = SEGMENT_REPOS + '/' + repoId + SEGMENT_MILESTONES + '/'
+ + milestone.getNumber();
- StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
- uri.append('/').append(repoId);
- uri.append(SEGMENT_MILESTONES);
- uri.append('/').append(milestone.getNumber());
-
- return client.post(uri.toString(), milestone, Milestone.class);
+ Map<String, Object> dto = createParams(milestone, false);
+ return client.post(uri, dto, Milestone.class);
}
}

Back to the top