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.Issue;
26 import com.atlassian.jira.rest.client.domain.IssueLink;
27 import com.atlassian.jira.rest.client.domain.IssueLinkType;
28 import com.atlassian.jira.rest.client.domain.Transition;
29 import com.atlassian.jira.rest.client.domain.Visibility;
30 import com.atlassian.jira.rest.client.domain.Votes;
31 import com.atlassian.jira.rest.client.domain.Watchers;
32 import com.atlassian.jira.rest.client.domain.input.AttachmentInput;
33 import com.atlassian.jira.rest.client.domain.input.FieldInput;
34 import com.atlassian.jira.rest.client.domain.input.LinkIssuesInput;
35 import com.atlassian.jira.rest.client.domain.input.TransitionInput;
36 import com.atlassian.jira.rest.client.internal.ServerVersionConstants;
37 import com.google.common.base.Function;
38 import com.google.common.base.Predicate;
39 import com.google.common.collect.Iterables;
40 import org.apache.commons.io.IOUtils;
41 import org.hamcrest.Matchers;
42 import org.joda.time.DateTime;
43 import org.joda.time.format.ISODateTimeFormat;
44 import org.junit.Assert;
45 import org.junit.Test;
46
47 import javax.annotation.Nullable;
48 import javax.ws.rs.core.Response;
49 import java.io.ByteArrayInputStream;
50 import java.io.File;
51 import java.io.FileInputStream;
52 import java.io.FileWriter;
53 import java.io.IOException;
54 import java.text.NumberFormat;
55 import java.util.Arrays;
56 import java.util.Collections;
57 import java.util.Locale;
58 import java.util.regex.Matcher;
59 import java.util.regex.Pattern;
60
61 import static com.atlassian.jira.rest.client.IntegrationTestUtil.*;
62 import static com.atlassian.jira.rest.client.TestUtil.assertErrorCode;
63 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER1_USERNAME;
64 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER2_USERNAME;
65 import static org.junit.Assert.assertThat;
66
67
68 public class JerseyIssueRestClientTest extends AbstractRestoringJiraStateJerseyRestClientTest {
69
70
71 private final DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime("2010-08-04T17:46:45.454");
72
73 @Test
74 public void testGetWatchers() throws Exception {
75 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
76 final Watchers watchers = client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), new NullProgressMonitor());
77 assertEquals(1, watchers.getNumWatchers());
78 assertFalse(watchers.isWatching());
79 assertThat(watchers.getUsers(), IterableMatcher.hasOnlyElements(USER1));
80 }
81
82 public void testGetWatcherForAnonymouslyAccessibleIssue() {
83 setAnonymousMode();
84 final Issue issue = client.getIssueClient().getIssue("ANNON-1", new NullProgressMonitor());
85 final Watchers watchers = client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm);
86 assertEquals(1, watchers.getNumWatchers());
87 assertFalse(watchers.isWatching());
88 assertTrue("JRADEV-3594 bug!!!", Iterables.isEmpty(watchers.getUsers()));
89 }
90
91
92 @Test
93 public void testGetIssue() throws Exception {
94 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
95 assertEquals("TST-1", issue.getKey());
96 assertTrue(issue.getSelf().toString().startsWith(jiraUri.toString()));
97 assertEquals(IntegrationTestUtil.USER_ADMIN, issue.getReporter());
98 assertEquals(IntegrationTestUtil.USER_ADMIN, issue.getAssignee());
99
100 assertEquals(3, Iterables.size(issue.getComments()));
101 assertThat(issue.getExpandos(), IterableMatcher.hasOnlyElements("html"));
102 assertTrue(Iterables.size(issue.getFields()) > 0);
103
104 assertEquals(IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Iterables.size(issue.getAttachments()));
105 final Iterable<Attachment> items = issue.getAttachments();
106 assertNotNull(items);
107 Attachment attachment1 = new Attachment(IntegrationTestUtil.concat(jiraRestRootUri, "/attachment/10040"),
108 "dla Paw\u0142a.txt", IntegrationTestUtil.USER_ADMIN, dateTime, 643, "text/plain",
109 IntegrationTestUtil.concat(jiraUri, "/secure/attachment/10040/dla+Paw%C5%82a.txt"), null);
110
111 assertEquals(attachment1, items.iterator().next());
112
113 }
114
115
116 public void testGetIssueWithNonTrivialComments() {
117 final Issue issue = client.getIssueClient().getIssue("TST-2", pm);
118 final Iterable<Comment> comments = issue.getComments();
119 assertEquals(3, Iterables.size(comments));
120 final Comment c1 = Iterables.get(comments, 0);
121 assertEquals(Visibility.role("Administrators"), c1.getVisibility());
122
123 final Comment c3 = Iterables.get(comments, 2);
124 assertEquals(Visibility.group("jira-users"), c3.getVisibility());
125
126 }
127
128 public void testGetIssueWithNoViewWatchersPermission() {
129 setUser1();
130 assertTrue(client.getIssueClient().getIssue("TST-1", pm).getWatchers().isWatching());
131
132 setUser2();
133 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
134 assertFalse(issue.getWatchers().isWatching());
135 client.getIssueClient().watch(issue.getWatchers().getSelf(), pm);
136 final Issue watchedIssue = client.getIssueClient().getIssue("TST-1", pm);
137 assertTrue(watchedIssue.getWatchers().isWatching());
138 assertEquals(2, watchedIssue.getWatchers().getNumWatchers());
139
140
141
142 assertThat(client.getIssueClient().getWatchers(watchedIssue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.hasOnlyElements(USER2));
143 }
144
145 @Test
146 public void testGetVoter() {
147 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
148 final Votes votes = client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
149 assertFalse(votes.hasVoted());
150 assertThat(votes.getUsers(), IterableMatcher.hasOnlyElements(USER1));
151 }
152
153 @Test
154 public void testGetVotersWithoutViewIssuePermission() {
155 final Issue issue = client.getIssueClient().getIssue("RST-1", pm);
156 setUser2();
157 assertErrorCode(Response.Status.FORBIDDEN, "You do not have the permission to see the specified issue", new Runnable() {
158 @Override
159 public void run() {
160 client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
161 }
162 });
163 }
164
165 @Test
166 public void testGetVotersWithoutViewVotersPermission() {
167 setUser2();
168 assertNumVotesAndNoVotersDetails("TST-1", 1);
169 }
170
171 @Test
172 public void testGetVotersAnonymously() {
173 setAnonymousMode();
174 assertNumVotesAndNoVotersDetails("ANNON-1", 0);
175 }
176
177
178 private void assertNumVotesAndNoVotersDetails(final String issueKey, final int numVotes) {
179 final Issue issue = client.getIssueClient().getIssue(issueKey, pm);
180 assertEquals(numVotes, issue.getVotes().getVotes());
181 assertFalse(issue.getVotes().hasVoted());
182 final Votes votes = client.getIssueClient().getVotes(issue.getVotes().getSelf(), pm);
183 assertFalse(votes.hasVoted());
184 assertEquals(numVotes, votes.getVotes());
185 assertTrue(Iterables.isEmpty(votes.getUsers()));
186 }
187
188
189 @Test
190 public void testGetTransitions() throws Exception {
191 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
192 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
193 assertEquals(4, Iterables.size(transitions));
194 assertTrue(Iterables.contains(transitions, new Transition("Start Progress", IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList())));
195 }
196
197 @Test
198 public void testTransition() throws Exception {
199 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
200 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
201 assertEquals(4, Iterables.size(transitions));
202 final Transition startProgressTransition = new Transition("Start Progress", IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList());
203 assertTrue(Iterables.contains(transitions, startProgressTransition));
204
205 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(IntegrationTestUtil.START_PROGRESS_TRANSITION_ID,
206 Collections.<FieldInput>emptyList(), Comment.valueOf("My test comment")), new NullProgressMonitor()) ;
207 final Issue transitionedIssue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
208 assertEquals("In Progress", transitionedIssue.getStatus().getName());
209 final Iterable<Transition> transitionsAfterTransition = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
210 assertFalse(Iterables.contains(transitionsAfterTransition, startProgressTransition));
211 final Transition stopProgressTransition = new Transition("Stop Progress", IntegrationTestUtil.STOP_PROGRESS_TRANSITION_ID, Collections.<Transition.Field>emptyList());
212 assertTrue(Iterables.contains(transitionsAfterTransition, stopProgressTransition));
213 }
214
215
216 @Test
217 public void testTransitionWithNumericCustomFieldPolishLocale() throws Exception {
218 final double newValue = 123.45;
219 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID,
220 NumberFormat.getNumberInstance(new Locale("pl")).format(newValue));
221 assertTransitionWithNumericCustomField(fieldInput, newValue);
222 }
223
224 @Test
225 public void testTransitionWithNumericCustomFieldEnglishLocale() throws Exception {
226 setUser1();
227 final double newValue = 123.45;
228 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID,
229 NumberFormat.getNumberInstance(new Locale("pl")).format(newValue));
230
231 assertErrorCode(Response.Status.BAD_REQUEST, "'" + fieldInput.getValue() + "' is an invalid number", new Runnable() {
232 @Override
233 public void run() {
234 assertTransitionWithNumericCustomField(fieldInput, newValue);
235 }
236 });
237
238 final FieldInput fieldInput2 = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
239 assertTransitionWithNumericCustomField(fieldInput2, newValue);
240
241 }
242
243
244 private void assertTransitionWithNumericCustomField(FieldInput fieldInput, Double expectedValue) {
245 final Issue issue = client.getIssueClient().getIssue("TST-1", new NullProgressMonitor());
246 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
247 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
248
249 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
250 assertNotNull(transitionFound);
251 assertTrue(Iterables.contains(transitionFound.getFields(),
252 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
253 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
254 Comment.valueOf("My test comment")), new NullProgressMonitor());
255 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
256 assertTrue(changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue().equals(expectedValue));
257 }
258
259 @Test
260 public void testTransitionWithNumericCustomFieldAndInteger() throws Exception {
261 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
262 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
263 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
264 Transition transitionFound = getTransitionByName(transitions, "Estimate");
265
266 assertNotNull(transitionFound);
267 assertTrue(Iterables.contains(transitionFound.getFields(),
268 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
269 final double newValue = 123;
270 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
271 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
272 Comment.valueOf("My test comment")), pm);
273 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
274 assertEquals(newValue, changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
275 }
276
277 @Test
278 public void testTransitionWithInvalidNumericField() throws Exception {
279 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
280 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
281 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
282 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
283
284 assertNotNull(transitionFound);
285 assertTrue(Iterables.contains(transitionFound.getFields(),
286 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false, NUMERIC_CUSTOMFIELD_TYPE)));
287 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, "]432jl");
288
289 assertErrorCode(Response.Status.BAD_REQUEST, "']432jl' nie jest prawid\u0142ow\u0105 liczb\u0105", new Runnable() {
290 @Override
291 public void run() {
292 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
293 Comment.valueOf("My test comment")), pm);
294 }
295 });
296 }
297
298
299 public void testTransitionWithNoRoleOrGroup() {
300 Comment comment = Comment.valueOf("My text which I am just adding " + new DateTime());
301 testTransitionImpl(comment);
302 }
303
304 @Test
305 public void testTransitionWithRoleLevel() {
306 Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "Users");
307 testTransitionImpl(comment);
308 }
309
310 @Test
311 public void testTransitionWithGroupLevel() {
312 Comment comment = Comment.createWithGroupLevel("My text which I am just adding " + new DateTime(), "jira-users");
313 testTransitionImpl(comment);
314 }
315
316 @Test
317 public void testTransitionWithInvalidRole() {
318 final Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "some-fake-role");
319 assertInvalidCommentInput(comment, "Invalid role [some-fake-role]");
320 }
321
322 @Test
323 public void testTransitionWithInvalidGroup() {
324 final Comment comment = Comment.createWithGroupLevel("My text which I am just adding " + new DateTime(), "some-fake-group");
325 assertInvalidCommentInput(comment, "Group: some-fake-group does not exist.");
326 }
327
328 private void assertInvalidCommentInput(final Comment comment, String expectedErrorMsg) {
329 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
330 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
331 final Transition transitionFound = getTransitionByName(transitions, "Estimate");
332 final String errorMsg = doesJiraServeCorrectlyErrorMessagesForBadRequestWhileTransitioningIssue()
333 ? expectedErrorMsg : null;
334 assertErrorCode(Response.Status.BAD_REQUEST, errorMsg, new Runnable() {
335 @Override
336 public void run() {
337 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), comment), pm);
338 }
339 });
340 }
341
342 private void testTransitionImpl(Comment comment) {
343 final Issue issue = client.getIssueClient().getIssue("TST-1", pm);
344 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue.getTransitionsUri(), pm);
345 Transition transitionFound = getTransitionByName(transitions, "Estimate");
346 DateTime now = new DateTime();
347 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), comment), pm);
348
349 final Issue changedIssue = client.getIssueClient().getIssue("TST-1", pm);
350 final Comment lastComment = Iterables.getLast(changedIssue.getComments());
351 assertEquals(comment.getBody(), lastComment.getBody());
352 assertEquals(USER_ADMIN, lastComment.getAuthor());
353 assertEquals(USER_ADMIN, lastComment.getUpdateAuthor());
354 assertEquals(lastComment.getCreationDate(), lastComment.getUpdateDate());
355 assertTrue(lastComment.getCreationDate().isAfter(now) || lastComment.getCreationDate().isEqual(now));
356 assertEquals(comment.getVisibility(), lastComment.getVisibility());
357 }
358
359 @Test
360 public void testVoteUnvote() {
361 final Issue issue1 = client.getIssueClient().getIssue("TST-1", pm);
362 assertFalse(issue1.getVotes().hasVoted());
363 assertEquals(1, issue1.getVotes().getVotes());
364
365
366 assertErrorCode(Response.Status.NOT_FOUND, "Nie mo\u017cesz g\u0142osowa\u0107 na zadanie kt\u00f3re utworzy\u0142e\u015b.", new Runnable() {
367 @Override
368 public void run() {
369 client.getIssueClient().vote(issue1.getVotesUri(), pm);
370 }
371 });
372
373
374 final String issueKey = "TST-7";
375 Issue issue = client.getIssueClient().getIssue(issueKey, pm);
376 assertFalse(issue.getVotes().hasVoted());
377 assertEquals(0, issue.getVotes().getVotes());
378
379 client.getIssueClient().vote(issue.getVotesUri(), pm);
380 issue = client.getIssueClient().getIssue(issueKey, pm);
381 assertTrue(issue.getVotes().hasVoted());
382 assertEquals(1, issue.getVotes().getVotes());
383
384 client.getIssueClient().unvote(issue.getVotesUri(), pm);
385 issue = client.getIssueClient().getIssue(issueKey, pm);
386 assertFalse(issue.getVotes().hasVoted());
387 assertEquals(0, issue.getVotes().getVotes());
388
389 setUser2();
390 issue = client.getIssueClient().getIssue(issueKey, pm);
391 assertFalse(issue.getVotes().hasVoted());
392 assertEquals(0, issue.getVotes().getVotes());
393 final Issue finalIssue = issue;
394 assertErrorCode(Response.Status.NOT_FOUND, "Cannot remove a vote for an issue that the user has not already voted for.",
395 new Runnable() {
396 @Override
397 public void run() {
398 client.getIssueClient().unvote(finalIssue.getVotesUri(), pm);
399 }
400 });
401
402
403 issue = client.getIssueClient().getIssue(issueKey, pm);
404 assertFalse(issue.getVotes().hasVoted());
405 assertEquals(0, issue.getVotes().getVotes());
406 client.getIssueClient().vote(issue.getVotesUri(), pm);
407 issue = client.getIssueClient().getIssue(issueKey, pm);
408 assertTrue(issue.getVotes().hasVoted());
409 assertEquals(1, issue.getVotes().getVotes());
410
411 setClient(ADMIN_USERNAME, ADMIN_PASSWORD);
412 client.getIssueClient().vote(issue.getVotesUri(), pm);
413 issue = client.getIssueClient().getIssue(issueKey, pm);
414 assertTrue(issue.getVotes().hasVoted());
415 assertEquals(2, issue.getVotes().getVotes());
416 }
417
418 @Test
419 public void testWatchUnwatch() {
420 final IssueRestClient issueClient = client.getIssueClient();
421 final Issue issue1 = issueClient.getIssue("TST-1", pm);
422
423 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(),
424 Matchers.not(IterableMatcher.contains(USER_ADMIN)));
425
426 issueClient.watch(issue1.getWatchers().getSelf(), pm);
427 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER_ADMIN));
428
429 issueClient.unwatch(issue1.getWatchers().getSelf(), pm);
430 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), Matchers.not(IterableMatcher.contains(USER_ADMIN)));
431
432 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
433 issueClient.removeWatcher(issue1.getWatchers().getSelf(), USER1.getName(), pm);
434 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), Matchers.not(IterableMatcher.contains(USER1)));
435 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER1.getName(), pm);
436 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
437 }
438
439 @Test
440 public void testRemoveWatcherUnauthorized() {
441 final IssueRestClient issueClient = client.getIssueClient();
442 final Issue issue1 = issueClient.getIssue("TST-1", pm);
443 issueClient.watch(issue1.getWatchers().getSelf(), pm);
444
445 setUser1();
446 final IssueRestClient issueClient2 = client.getIssueClient();
447 assertErrorCode(Response.Status.UNAUTHORIZED,
448 "User 'wseliga' is not allowed to remove watchers from issue 'TST-1'", new Runnable() {
449 @Override
450 public void run() {
451 issueClient2.removeWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME, pm);
452 }
453 });
454 }
455
456
457 @Test
458 public void testWatchAlreadyWatched() {
459 setUser1();
460 final IssueRestClient issueClient = client.getIssueClient();
461 final Issue issue = issueClient.getIssue("TST-1", pm);
462 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
463
464 issueClient.watch(issue.getWatchers().getSelf(), pm);
465 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
466 }
467
468 @Test
469 public void testAddWatcherUnauthorized() {
470 final IssueRestClient issueClient = client.getIssueClient();
471 final Issue issue1 = issueClient.getIssue("TST-1", pm);
472 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER1_USERNAME, pm);
473 assertThat(client.getIssueClient().getWatchers(issue1.getWatchers().getSelf(), pm).getUsers(), IterableMatcher.contains(USER1));
474
475 setUser1();
476 assertTrue(client.getIssueClient().getIssue("TST-1", pm).getWatchers().isWatching());
477 String expectedErrorMsg = isJraDev3516Fixed() ? ("User '" + USER1_USERNAME
478 + "' is not allowed to add watchers to issue 'TST-1'") : null;
479 assertErrorCode(Response.Status.UNAUTHORIZED, expectedErrorMsg, new Runnable() {
480 @Override
481 public void run() {
482 client.getIssueClient().addWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME, pm);
483 }
484 });
485 }
486
487 private boolean isJraDev3516Fixed() {
488 return client.getMetadataClient().getServerInfo(pm).getBuildNumber() >= ServerVersionConstants.BN_JIRA_4_3_OR_NEWER;
489 }
490
491
492 public void xtestAddWatcherWhoDoesNotHaveViewIssuePermissions() {
493 final IssueRestClient issueClient = client.getIssueClient();
494 final Issue issue1 = issueClient.getIssue("RST-1", pm);
495 assertErrorCode(Response.Status.BAD_REQUEST, "The user \"" + USER2_USERNAME
496 + "\" does not have permission to view this issue. This user will not be added to the watch list.",
497 new Runnable() {
498 @Override
499 public void run() {
500 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER2_USERNAME, pm);
501 }
502 });
503
504 }
505
506 @Test
507 public void testLinkIssuesWithRoleLevel() {
508 testLinkIssuesImpl(Comment.createWithRoleLevel("A comment about linking", "Administrators"));
509 }
510
511 @Test
512 public void testLinkIssuesWithGroupLevel() {
513 testLinkIssuesImpl(Comment.createWithGroupLevel("A comment about linking", "jira-administrators"));
514 }
515
516 @Test
517 public void testLinkIssuesWithSimpleComment() {
518 testLinkIssuesImpl(Comment.valueOf("A comment about linking"));
519 }
520
521 @Test
522 public void testLinkIssuesWithoutComment() {
523 testLinkIssuesImpl(null);
524 }
525
526 @Test
527 public void testLinkIssuesWithInvalidParams() {
528 if (!doesJiraSupportRestIssueLinking()) {
529 return;
530 }
531 assertErrorCode(Response.Status.NOT_FOUND, "The issue no longer exists.", new Runnable() {
532 @Override
533 public void run() {
534 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "FAKEKEY-1", "Duplicate", null), pm);
535 }
536 });
537
538 assertErrorCode(Response.Status.NOT_FOUND, "No issue link type with name 'NonExistingLinkType' found.", new Runnable() {
539 @Override
540 public void run() {
541 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "NonExistingLinkType", null), pm);
542 }
543 });
544
545 setUser1();
546 assertErrorCode(Response.Status.NOT_FOUND, "You do not have the permission to see the specified issue", new Runnable() {
547 @Override
548 public void run() {
549 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "RST-1", "Duplicate", null), pm);
550 }
551 });
552 assertErrorCode(Response.Status.BAD_REQUEST, "Failed to create comment for issue 'TST-6'\nYou are currently not a member of the project role: Administrators.", new Runnable() {
553 @Override
554 public void run() {
555 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
556 Comment.createWithRoleLevel("my body", "Administrators")), pm);
557 }
558 });
559 assertErrorCode(Response.Status.BAD_REQUEST, "You are currently not a member of the group: jira-administrators.", new Runnable() {
560 @Override
561 public void run() {
562 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
563 Comment.createWithGroupLevel("my body", "jira-administrators")), pm);
564 }
565 });
566 assertErrorCode(Response.Status.BAD_REQUEST, "Group: somefakegroup does not exist.", new Runnable() {
567 @Override
568 public void run() {
569 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
570 Comment.createWithGroupLevel("my body", "somefakegroup")), pm);
571 }
572 });
573
574
575 setUser2();
576 assertErrorCode(Response.Status.UNAUTHORIZED, "No Link Issue Permission for issue 'TST-7'", new Runnable() {
577 @Override
578 public void run() {
579 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate", null), pm);
580 }
581 });
582
583 }
584
585
586 private void testLinkIssuesImpl(@Nullable Comment commentInput) {
587 if (!doesJiraSupportRestIssueLinking()) {
588 return;
589 }
590
591 final IssueRestClient issueClient = client.getIssueClient();
592 final Issue originalIssue = issueClient.getIssue("TST-7", pm);
593 int origNumComments = Iterables.size(originalIssue.getComments());
594 assertFalse(originalIssue.getIssueLinks().iterator().hasNext());
595
596 issueClient.linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate", commentInput), pm);
597
598 final Issue linkedIssue = issueClient.getIssue("TST-7", pm);
599 assertEquals(1, Iterables.size(linkedIssue.getIssueLinks()));
600 final IssueLink addedLink = linkedIssue.getIssueLinks().iterator().next();
601 assertEquals("Duplicate", addedLink.getIssueLinkType().getName());
602 assertEquals("TST-6", addedLink.getTargetIssueKey());
603 assertEquals(IssueLinkType.Direction.OUTBOUND, addedLink.getIssueLinkType().getDirection());
604
605 final int expectedNumComments = commentInput != null ? origNumComments + 1 : origNumComments;
606 assertEquals(expectedNumComments, Iterables.size(linkedIssue.getComments()));
607 if (commentInput != null) {
608 final Comment comment = linkedIssue.getComments().iterator().next();
609 assertEquals(commentInput.getBody(), comment.getBody());
610 assertEquals(IntegrationTestUtil.USER_ADMIN, comment.getAuthor());
611 assertEquals(commentInput.getVisibility(), comment.getVisibility());
612 } else {
613 assertFalse(linkedIssue.getComments().iterator().hasNext());
614 }
615
616
617 final Issue targetIssue = issueClient.getIssue("TST-6", pm);
618 final IssueLink targetLink = targetIssue.getIssueLinks().iterator().next();
619 assertEquals(IssueLinkType.Direction.INBOUND, targetLink.getIssueLinkType().getDirection());
620 assertEquals("Duplicate", targetLink.getIssueLinkType().getName());
621 }
622
623 private boolean doesJiraSupportRestIssueLinking() {
624 return client.getMetadataClient().getServerInfo(pm).getBuildNumber() >= ServerVersionConstants.BN_JIRA_4_3_OR_NEWER;
625 }
626
627 private boolean doesJiraSupportAddingAttachment() {
628 return client.getMetadataClient().getServerInfo(pm).getBuildNumber() >= ServerVersionConstants.BN_JIRA_4_3_OR_NEWER;
629 }
630
631 private boolean doesJiraServeCorrectlyErrorMessagesForBadRequestWhileTransitioningIssue() {
632 return client.getMetadataClient().getServerInfo(pm).getBuildNumber() >= ServerVersionConstants.BN_JIRA_4_3_OR_NEWER;
633 }
634
635 @Test
636 public void testAddAttachment() throws IOException {
637 if (!doesJiraSupportAddingAttachment()) {
638 return;
639 }
640 final IssueRestClient issueClient = client.getIssueClient();
641 final Issue issue = issueClient.getIssue("TST-3", pm);
642 assertFalse(issue.getAttachments().iterator().hasNext());
643
644 String str = "Wojtek";
645 final String filename1 = "my-test-file";
646 issueClient.addAttachment(pm, issue.getAttachmentsUri(), new ByteArrayInputStream(str.getBytes("UTF-8")), filename1);
647 final String filename2 = "my-picture.png";
648 issueClient.addAttachment(pm, issue.getAttachmentsUri(), JerseyIssueRestClientTest.class.getResourceAsStream("/attachment-test/transparent-png.png"), filename2);
649
650 final Issue issueWithAttachments = issueClient.getIssue("TST-3", pm);
651 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
652 assertEquals(2, Iterables.size(attachments));
653 final Iterable<String> attachmentsNames = Iterables.transform(attachments, new Function<Attachment, String>() {
654 @Override
655 public String apply(@Nullable Attachment from) {
656 return from.getFilename();
657 }
658 });
659 assertThat(attachmentsNames, IterableMatcher.hasOnlyElements(filename1, filename2));
660 final Attachment pictureAttachment = Iterables.find(attachments, new Predicate<Attachment>() {
661 @Override
662 public boolean apply(@Nullable Attachment input) {
663 return filename2.equals(input.getFilename());
664 }
665 });
666
667
668
669 assertTrue(
670 IOUtils.contentEquals(JerseyIssueRestClientTest.class.getResourceAsStream("/attachment-test/transparent-png.png"),
671 issueClient.getAttachment(pm, pictureAttachment.getContentUri())));
672 }
673
674 @Test
675 public void testAddAttachments() throws IOException {
676 if (!doesJiraSupportAddingAttachment()) {
677 return;
678 }
679 final IssueRestClient issueClient = client.getIssueClient();
680 final Issue issue = issueClient.getIssue("TST-4", pm);
681 assertFalse(issue.getAttachments().iterator().hasNext());
682
683 final AttachmentInput[] attachmentInputs = new AttachmentInput[3];
684 for (int i = 1; i <= 3; i++) {
685 attachmentInputs[i - 1] = new AttachmentInput("my-test-file-" + i + ".txt", new ByteArrayInputStream(("content-of-the-file-" + i).getBytes("UTF-8")));
686 }
687 issueClient.addAttachments(pm, issue.getAttachmentsUri(), attachmentInputs);
688
689 final Issue issueWithAttachments = issueClient.getIssue("TST-4", pm);
690 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
691 assertEquals(3, Iterables.size(attachments));
692 Pattern pattern = Pattern.compile("my-test-file-(\\d)\\.txt");
693 for (Attachment attachment : attachments) {
694 assertTrue(pattern.matcher(attachment.getFilename()).matches());
695 final Matcher matcher = pattern.matcher(attachment.getFilename());
696 matcher.find();
697 final String interfix = matcher.group(1);
698 assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(("content-of-the-file-" + interfix).getBytes("UTF-8")),
699 issueClient.getAttachment(pm, attachment.getContentUri())));
700
701 }
702 }
703
704 @Test
705 public void testAddFileAttachments() throws IOException {
706 if (!doesJiraSupportAddingAttachment()) {
707 return;
708 }
709 final IssueRestClient issueClient = client.getIssueClient();
710 final Issue issue = issueClient.getIssue("TST-5", pm);
711 assertFalse(issue.getAttachments().iterator().hasNext());
712
713 final File tempFile = File.createTempFile("jim-integration-test", ".txt");
714 tempFile.deleteOnExit();
715 FileWriter writer = new FileWriter(tempFile);
716 writer.write("This is the content of my file which I am going to upload to JIRA for testing.");
717 writer.close();
718 issueClient.addAttachments(pm, issue.getAttachmentsUri(), tempFile);
719
720 final Issue issueWithAttachments = issueClient.getIssue("TST-5", pm);
721 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
722 assertEquals(1, Iterables.size(attachments));
723 assertTrue(IOUtils.contentEquals(new FileInputStream(tempFile),
724 issueClient.getAttachment(pm, attachments.iterator().next().getContentUri())));
725 }
726
727
728 @Test
729 public void testFetchingUnassignedIssue() {
730 administration.generalConfiguration().setAllowUnassignedIssues(true);
731 assertEquals(IntegrationTestUtil.USER_ADMIN, client.getIssueClient().getIssue("TST-5", pm).getAssignee());
732
733
734
735
736 navigation.issue().assignIssue("TST-5", "unassigning issue", "Nieprzydzielone");
737
738 assertNull(client.getIssueClient().getIssue("TST-5", pm).getAssignee());
739 }
740
741 @Test
742 public void testFetchingIssueWithAnonymousComment() {
743 navigation.userProfile().changeUserLanguage("angielski (UK)");
744 administration.permissionSchemes().scheme("Anonymous Permission Scheme").grantPermissionToGroup(15, "");
745 assertEquals(IntegrationTestUtil.USER_ADMIN, client.getIssueClient().getIssue("TST-5", pm).getAssignee());
746 navigation.logout();
747 navigation.issue().addComment("ANNON-1", "my nice comment");
748 final Issue issue = client.getIssueClient().getIssue("ANNON-1", pm);
749 assertEquals(1, Iterables.size(issue.getComments()));
750 final Comment comment = issue.getComments().iterator().next();
751 assertEquals("my nice comment", comment.getBody());
752 assertNull(comment.getAuthor());
753 assertNull(comment.getUpdateAuthor());
754
755 }
756
757 }