1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package it;
18
19 import com.atlassian.jira.rest.client.IntegrationTestUtil;
20 import com.atlassian.jira.rest.client.IssueRestClient;
21 import com.atlassian.jira.rest.client.IterableMatcher;
22 import com.atlassian.jira.rest.client.NullProgressMonitor;
23 import com.atlassian.jira.rest.client.domain.Attachment;
24 import com.atlassian.jira.rest.client.domain.Comment;
25 import com.atlassian.jira.rest.client.domain.input.FieldInput;
26 import com.atlassian.jira.rest.client.domain.Issue;
27 import com.atlassian.jira.rest.client.domain.Transition;
28 import com.atlassian.jira.rest.client.domain.input.TransitionInput;
29 import com.atlassian.jira.rest.client.domain.Votes;
30 import com.atlassian.jira.rest.client.domain.Watchers;
31 import com.google.common.collect.Iterables;
32 import org.hamcrest.Matchers;
33 import org.joda.time.DateTime;
34 import org.joda.time.format.ISODateTimeFormat;
35 import org.junit.Assert;
36 import org.junit.Test;
37
38 import javax.ws.rs.core.Response;
39 import java.text.NumberFormat;
40 import java.util.Arrays;
41 import java.util.Collections;
42 import java.util.Locale;
43
44 import static com.atlassian.jira.rest.client.IntegrationTestUtil.*;
45 import static com.atlassian.jira.rest.client.TestUtil.assertErrorCode;
46 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER1_USERNAME;
47 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER2_USERNAME;
48 import static org.junit.Assert.assertThat;
49
50
51 public class JerseyIssueRestClientTest extends AbstractRestoringJiraStateJerseyRestClientTest {
52
53
54 private final DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime("2010-08-04T17:46:45.454");
55
56 @Test
57 public void testGetWatchers() throws Exception {
58 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
59 final Watchers watchers = client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), new NullProgressMonitor());
60 assertEquals(1, watchers.getNumWatchers());
61 assertFalse(watchers.isWatching());
62 assertThat(watchers.getUsers(), IterableMatcher.hasOnlyElements(USER1));
63 }
64
65 public void testGetWatcherForAnonymouslyAccessibleIssue() {
66 setAnonymousMode();
67 final Issue issue = client.getIssueClient().getIssue("ANNON-1", new NullProgressMonitor());
68 final Watchers watchers = client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm);
69 assertEquals(1, watchers.getNumWatchers());
70 assertFalse(watchers.isWatching());
71 assertTrue("JRADEV-3594 bug!!!", Iterables.isEmpty(watchers.getUsers()));
72 }
73
74
75 @Test
76 public void testGetIssue() throws Exception {
77 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
78 assertEquals("TST-1", issue.getKey());
79 assertTrue(issue.getSelf().toString().startsWith(jiraUri.toString()));
80 assertEquals(IntegrationTestUtil.USER_ADMIN, issue.getReporter());
81 assertEquals(IntegrationTestUtil.USER_ADMIN, issue.getAssignee());
82
83 assertEquals(3, Iterables.size(issue.getComments()));
84 assertThat(issue.getExpandos(), IterableMatcher.hasOnlyElements("html"));
85 assertTrue(Iterables.size(issue.getFields()) > 0);
86
87 assertEquals(IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Iterables.size(issue.getAttachments()));
88 final Iterable<Attachment> items = issue.getAttachments();
89 assertNotNull(items);
90 Attachment attachment1 = new Attachment(IntegrationTestUtil.concat(jiraRestRootUri, "/attachment/10040"),
91 "dla Paw\u0142a.txt", IntegrationTestUtil.USER_ADMIN, dateTime, 643, "text/plain",
92 IntegrationTestUtil.concat(jiraUri, "/secure/attachment/10040/dla+Paw%C5%82a.txt"), null);
93
94 assertEquals(attachment1, items.iterator().next());
95
96 }
97
98
99 public void testGetIssueWithNonTrivialComments() {
100 final Issue issue = client.getIssueClient().getIssue("TST-2", pm);
101 final Iterable<Comment> comments = issue.getComments();
102 assertEquals(3, Iterables.size(comments));
103 final Comment c1 = Iterables.get(comments, 0);
104 assertEquals("Administrators", c1.getRoleLevel());
105 assertNull(c1.getGroupLevel());
106
107 final Comment c3 = Iterables.get(comments, 2);
108 assertEquals("jira-users", c3.getGroupLevel());
109 assertNull(c3.getRoleLevel());
110
111 }
112
113 public void testGetIssueWithNoViewWatchersPermission() {
114 setUser1();
115 assertTrue(client.getIssueClient().getIssue("TST-1", pm).getWatchers().isWatching());
116
117 setUser2();
118 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
119 assertFalse(issue.getWatchers().isWatching());
120 client.getIssueClient().watch(issue.getWatchers().getSelf(), pm);
121 final Issue watchedIssue = client.getIssueClient().getIssue("TST-1", pm);
122 assertTrue(watchedIssue.getWatchers().isWatching());
123 assertEquals(2, watchedIssue.getWatchers().getNumWatchers());
124
125
126
127 assertThat(client.getIssueClient().getWatchers(watchedIssue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.hasOnlyElements(USER2));
128 }
129
130 @Test
131 public void testGetVoter() {
132 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
133 final Votes votes = client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
134 assertFalse(votes.hasVoted());
135 assertThat(votes.getUsers(), IterableMatcher.hasOnlyElements(USER1));
136 }
137
138 @Test
139 public void testGetVotersWithoutViewIssuePermission() {
140 final Issue issue = client.getIssueClient().getIssue("RST-1", pm);
141 setUser2();
142 assertErrorCode(Response.Status.FORBIDDEN, "You do not have the permission to see the specified issue", new Runnable() {
143 @Override
144 public void run() {
145 client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
146 }
147 });
148 }
149
150 @Test
151 public void testGetVotersWithoutViewVotersPermission() {
152 setUser2();
153 assertNumVotesAndNoVotersDetails("TST-1", 1);
154 }
155
156 @Test
157 public void testGetVotersAnonymously() {
158 setAnonymousMode();
159 assertNumVotesAndNoVotersDetails("ANNON-1", 0);
160 }
161
162
163 private void assertNumVotesAndNoVotersDetails(final String issueKey, final int numVotes) {
164 final Issue issue = client.getIssueClient().getIssue(issueKey, pm);
165 assertEquals(numVotes, issue.getVotes().getVotes());
166 assertFalse(issue.getVotes().hasVoted());
167 final Votes votes = client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
168 assertFalse(votes.hasVoted());
169 assertEquals(numVotes, votes.getVotes());
170 assertTrue(Iterables.isEmpty(votes.getUsers()));
171 }
172
173
174 @Test
175 public void testGetTransitions() throws Exception {
176 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
177 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
178 assertEquals(4, Iterables.size(transitions));
179 assertTrue(Iterables.contains(transitions, new Transition("Start Progress", IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList())));
180 }
181
182 @Test
183 public void testTransition() throws Exception {
184 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
185 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
186 assertEquals(4, Iterables.size(transitions));
187 final Transition startProgressTransition = new Transition("Start Progress", IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList());
188 assertTrue(Iterables.contains(transitions, startProgressTransition));
189
190 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(IntegrationTestUtil.START_PROGRESS_TRANSITION_ID,
191 Collections.<FieldInput>emptyList(), Comment.valueOf("My test comment")), new NullProgressMonitor()) ;
192 final Issue transitionedIssue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
193 assertEquals("In Progress", transitionedIssue.getStatus().getName());
194 final Iterable<Transition> transitionsAfterTransition = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
195 assertFalse(Iterables.contains(transitionsAfterTransition, startProgressTransition));
196 final Transition stopProgressTransition = new Transition("Stop Progress", IntegrationTestUtil.STOP_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList());
197 assertTrue(Iterables.contains(transitionsAfterTransition, stopProgressTransition));
198 }
199
200
201 @Test
202 public void testTransitionWithNumericCustomFieldPolishLocale() throws Exception {
203 final double newValue = 123.45;
204 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID,
205 NumberFormat.getNumberInstance(new Locale("pl")).format(newValue));
206 assertTransitionWithNumericCustomField(fieldInput, newValue);
207 }
208
209 @Test
210 public void testTransitionWithNumericCustomFieldEnglishLocale() throws Exception {
211 setUser1();
212 final double newValue = 123.45;
213 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID,
214 NumberFormat.getNumberInstance(new Locale("pl")).format(newValue));
215
216 assertErrorCode(Response.Status.BAD_REQUEST, "'" + fieldInput.getValue() + "' is an invalid number", new Runnable() {
217 @Override
218 public void run() {
219 assertTransitionWithNumericCustomField(fieldInput, newValue);
220 }
221 });
222
223 final FieldInput fieldInput2 = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
224 assertTransitionWithNumericCustomField(fieldInput2, newValue);
225
226 }
227
228
229 private void assertTransitionWithNumericCustomField(FieldInput fieldInput, Double expectedValue) {
230 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
231 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
232 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
233
234 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
235 assertNotNull(transitionFound);
236 assertTrue(Iterables.contains(transitionFound.getFields(),
237 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
238 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
239 Comment.valueOf("My test comment")), new NullProgressMonitor());
240 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
241 assertTrue(changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue().equals(expectedValue));
242 }
243
244 @Test
245 public void testTransitionWithNumericCustomFieldAndInteger() throws Exception {
246 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
247 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
248 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
249 Transition transitionFound = getTransitionByName(transitions, "Estimate");
250
251 assertNotNull(transitionFound);
252 assertTrue(Iterables.contains(transitionFound.getFields(),
253 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
254 final double newValue = 123;
255 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
256 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
257 Comment.valueOf("My test comment")), pm);
258 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
259 assertEquals(newValue, changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
260 }
261
262 @Test
263 public void testTransitionWithInvalidNumericField() throws Exception {
264 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
265 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
266 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
267 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
268
269 assertNotNull(transitionFound);
270 assertTrue(Iterables.contains(transitionFound.getFields(),
271 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
272 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, "]432jl");
273
274 assertErrorCode(Response.Status.BAD_REQUEST, "']432jl' nie jest prawid\u0142ow\u0105 liczb\u0105", new Runnable() {
275 @Override
276 public void run() {
277 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
278 Comment.valueOf("My test comment")), pm);
279 }
280 });
281 }
282
283
284 public void testTransitionWithNoRoleOrGroup() {
285 Comment comment = Comment.valueOf("My text which I am just adding " + new DateTime());
286 testTransitionImpl(comment);
287 }
288
289 @Test
290 public void testTransitionWithRoleLevel() {
291 Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "Users");
292 testTransitionImpl(comment);
293 }
294
295 @Test
296 public void testTransitionWithGroupLevel() {
297 Comment comment = Comment.createWithGroupLevel("My text which I am just adding " + new DateTime(), "jira-users");
298 testTransitionImpl(comment);
299 }
300
301 @Test
302 public void testTransitionWithInvalidRole() {
303 final Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "some-fake-role");
304 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
305 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
306 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
307
308 assertErrorCode(Response.Status.BAD_REQUEST,
309 @Override
310 public void run() {
311 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), comment), pm);
312 }
313 });
314 }
315
316 private void testTransitionImpl(Comment comment) {
317 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
318 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
319 Transition transitionFound = getTransitionByName(transitions, "Estimate");
320 DateTime now = new DateTime();
321 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), comment), pm);
322
323 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
324 final Comment lastComment = Iterables.getLast(changedIssue.getComments());
325 assertEquals(comment.getBody(), lastComment.getBody());
326 assertEquals(USER_ADMIN, lastComment.getAuthor());
327 assertEquals(USER_ADMIN, lastComment.getUpdateAuthor());
328 assertEquals(lastComment.getCreationDate(), lastComment.getUpdateDate());
329 assertTrue(lastComment.getCreationDate().isAfter(now) || lastComment.getCreationDate().isEqual(now));
330 assertEquals(comment.getGroupLevel(), lastComment.getGroupLevel());
331 assertEquals(comment.getRoleLevel(), lastComment.getRoleLevel());
332 }
333
334 @Test
335 public void testVoteUnvote() {
336 final Issue issue1 = client.getIssueClient().getIssue("TST-1", pm);
337 assertFalse(issue1.getVotes().hasVoted());
338 assertEquals(1, issue1.getVotes().getVotes());
339
340
341 assertErrorCode(Response.Status.NOT_FOUND, "Nie mo\u017cesz g\u0142osowa\u0107 na zadanie kt\u00f3re utworzy\u0142e\u015b.", new Runnable() {
342 @Override
343 public void run() {
344 client.getIssueClient().vote(issue1.getVotesUri(), pm);
345 }
346 });
347
348
349 final String issueKey = "TST-7";
350 Issue issue = client.getIssueClient().getIssue(issueKey, pm);
351 assertFalse(issue.getVotes().hasVoted());
352 assertEquals(0, issue.getVotes().getVotes());
353
354 client.getIssueClient().vote(issue.getVotesUri(), pm);
355 issue = client.getIssueClient().getIssue(issueKey, pm);
356 assertTrue(issue.getVotes().hasVoted());
357 assertEquals(1, issue.getVotes().getVotes());
358
359 client.getIssueClient().unvote(issue.getVotesUri(), pm);
360 issue = client.getIssueClient().getIssue(issueKey, pm);
361 assertFalse(issue.getVotes().hasVoted());
362 assertEquals(0, issue.getVotes().getVotes());
363
364 setUser2();
365 issue = client.getIssueClient().getIssue(issueKey, pm);
366 assertFalse(issue.getVotes().hasVoted());
367 assertEquals(0, issue.getVotes().getVotes());
368 final Issue finalIssue = issue;
369 assertErrorCode(Response.Status.NOT_FOUND, "Cannot remove a vote for an issue that the user has not already voted for.", new Runnable() {
370 @Override
371 public void run() {
372 client.getIssueClient().unvote(finalIssue.getVotesUri(), pm);
373 }
374 });
375
376
377 issue = client.getIssueClient().getIssue(issueKey, pm);
378 assertFalse(issue.getVotes().hasVoted());
379 assertEquals(0, issue.getVotes().getVotes());
380 client.getIssueClient().vote(issue.getVotesUri(), pm);
381 issue = client.getIssueClient().getIssue(issueKey, pm);
382 assertTrue(issue.getVotes().hasVoted());
383 assertEquals(1, issue.getVotes().getVotes());
384
385 setClient(ADMIN_USERNAME, ADMIN_PASSWORD);
386 client.getIssueClient().vote(issue.getVotesUri(), pm);
387 issue = client.getIssueClient().getIssue(issueKey, pm);
388 assertTrue(issue.getVotes().hasVoted());
389 assertEquals(2, issue.getVotes().getVotes());
390 }
391
392 @Test
393 public void testWatchUnwatch() {
394 final IssueRestClient issueClient = client.getIssueClient();
395 final Issue issue1 = issueClient.getIssue("TST-1", pm);
396
397 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(),
398 Matchers.not(IterableMatcher.contains(USER_ADMIN)));
399
400 issueClient.watch(issue1.getWatchers().getSelf(), pm);
401 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER_ADMIN));
402
403 issueClient.unwatch(issue1.getWatchers().getSelf(), pm);
404 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), Matchers.not(IterableMatcher.contains(USER_ADMIN)));
405
406 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
407 issueClient.removeWatcher(issue1.getWatchers().getSelf(), USER1.getName(), pm);
408 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), Matchers.not(IterableMatcher.contains(USER1)));
409 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER1.getName(), pm);
410 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
411 }
412
413 @Test
414 public void testRemoveWatcherUnauthorized() {
415 final IssueRestClient issueClient = client.getIssueClient();
416 final Issue issue1 = issueClient.getIssue("TST-1", pm);
417 issueClient.watch(issue1.getWatchers().getSelf(), pm);
418
419 setUser1();
420 final IssueRestClient issueClient2 = client.getIssueClient();
421 assertErrorCode(Response.Status.UNAUTHORIZED,
422 "User 'wseliga' is not allowed to remove watchers from issue 'TST-1'", new Runnable() {
423 @Override
424 public void run() {
425 issueClient2.removeWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME, pm);
426 }
427 });
428 }
429
430
431 @Test
432 public void testWatchAlreadyWatched() {
433 setUser1();
434 final IssueRestClient issueClient = client.getIssueClient();
435 final Issue issue = issueClient.getIssue("TST-1", pm);
436 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
437
438 issueClient.watch(issue.getWatchers().getSelf(), pm);
439 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
440 }
441
442 @Test
443 public void testAddWatcherUnauthorized() {
444 final IssueRestClient issueClient = client.getIssueClient();
445 final Issue issue1 = issueClient.getIssue("TST-1", pm);
446 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER1_USERNAME, pm);
447 assertThat(client.getIssueClient().getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
448
449 setUser1();
450 assertTrue(client.getIssueClient().getIssue("TST-1", pm).getWatchers().isWatching());
451
452
453 assertErrorCode(Response.Status.UNAUTHORIZED
454 , new Runnable() {
455 @Override
456 public void run() {
457 client.getIssueClient().addWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME, pm);
458 }
459 });
460 }
461
462
463 public void xtestAddWatcherWhoDoesNotHaveViewIssuePermissions() {
464 final IssueRestClient issueClient = client.getIssueClient();
465 final Issue issue1 = issueClient.getIssue("RST-1", pm);
466 assertErrorCode(Response.Status.BAD_REQUEST, "The user \"" + USER2_USERNAME
467 + "\" does not have permission to view this issue. This user will not be added to the watch list.",
468 new Runnable() {
469 @Override
470 public void run() {
471 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER2_USERNAME, pm);
472 }
473 });
474
475 }
476 }