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.functest.framework.UserProfile;
20 import com.atlassian.jira.nimblefunctests.annotation.JiraBuildNumberDependent;
21 import com.atlassian.jira.nimblefunctests.annotation.LongCondition;
22 import com.atlassian.jira.rest.client.IntegrationTestUtil;
23 import com.atlassian.jira.rest.client.TestUtil;
24 import com.atlassian.jira.rest.client.api.GetCreateIssueMetadataOptionsBuilder;
25 import com.atlassian.jira.rest.client.api.IssueRestClient;
26 import com.atlassian.jira.rest.client.api.RestClientException;
27 import com.atlassian.jira.rest.client.api.domain.Attachment;
28 import com.atlassian.jira.rest.client.api.domain.BasicIssue;
29 import com.atlassian.jira.rest.client.api.domain.CimIssueType;
30 import com.atlassian.jira.rest.client.api.domain.CimProject;
31 import com.atlassian.jira.rest.client.api.domain.Comment;
32 import com.atlassian.jira.rest.client.api.domain.Issue;
33 import com.atlassian.jira.rest.client.api.domain.IssueLink;
34 import com.atlassian.jira.rest.client.api.domain.IssueLinkType;
35 import com.atlassian.jira.rest.client.api.domain.Transition;
36 import com.atlassian.jira.rest.client.api.domain.input.AttachmentInput;
37 import com.atlassian.jira.rest.client.api.domain.input.ComplexIssueInputFieldValue;
38 import com.atlassian.jira.rest.client.api.domain.input.FieldInput;
39 import com.atlassian.jira.rest.client.api.domain.input.IssueInput;
40 import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder;
41 import com.atlassian.jira.rest.client.api.domain.input.LinkIssuesInput;
42 import com.atlassian.jira.rest.client.api.domain.input.TransitionInput;
43 import com.atlassian.jira.rest.client.api.domain.util.ErrorCollection;
44 import com.atlassian.jira.rest.client.internal.json.TestConstants;
45 import com.google.common.base.Function;
46 import com.google.common.base.Predicate;
47 import com.google.common.collect.ImmutableList;
48 import com.google.common.collect.Iterables;
49 import org.apache.commons.io.IOUtils;
50 import org.joda.time.DateTime;
51 import org.junit.Assert;
52 import org.junit.Before;
53 import org.junit.Rule;
54 import org.junit.Test;
55 import org.junit.rules.ExpectedException;
56
57 import javax.annotation.Nullable;
58 import javax.ws.rs.core.Response;
59 import java.io.ByteArrayInputStream;
60 import java.io.File;
61 import java.io.FileInputStream;
62 import java.io.FileWriter;
63 import java.io.IOException;
64 import java.lang.reflect.InvocationTargetException;
65 import java.lang.reflect.Method;
66 import java.text.NumberFormat;
67 import java.util.Arrays;
68 import java.util.Collections;
69 import java.util.Locale;
70 import java.util.regex.Matcher;
71 import java.util.regex.Pattern;
72
73 import static com.atlassian.jira.rest.client.IntegrationTestUtil.NUMERIC_CUSTOMFIELD_ID;
74 import static com.atlassian.jira.rest.client.IntegrationTestUtil.NUMERIC_CUSTOMFIELD_TYPE;
75 import static com.atlassian.jira.rest.client.IntegrationTestUtil.NUMERIC_CUSTOMFIELD_TYPE_V5;
76 import static com.atlassian.jira.rest.client.IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER;
77 import static com.atlassian.jira.rest.client.IntegrationTestUtil.TEXT_CUSTOMFIELD_ID;
78 import static com.atlassian.jira.rest.client.IntegrationTestUtil.USER2;
79 import static com.atlassian.jira.rest.client.TestUtil.assertErrorCode;
80 import static com.atlassian.jira.rest.client.TestUtil.assertExpectedErrorCollection;
81 import static com.atlassian.jira.rest.client.api.domain.EntityHelper.findEntityByName;
82 import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_4_3;
83 import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_5;
84 import static com.atlassian.jira.rest.client.internal.json.TestConstants.ADMIN_PASSWORD;
85 import static com.atlassian.jira.rest.client.internal.json.TestConstants.ADMIN_USERNAME;
86 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER1_USERNAME;
87 import static com.atlassian.jira.rest.client.internal.json.TestConstants.USER2_USERNAME;
88 import static com.atlassian.jira.rest.client.test.matchers.RestClientExceptionMatchers.rceWithSingleError;
89 import static org.hamcrest.Matchers.equalTo;
90 import static org.hamcrest.Matchers.hasItem;
91 import static org.hamcrest.Matchers.not;
92 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
93 import static org.junit.Assert.assertEquals;
94 import static org.junit.Assert.assertFalse;
95 import static org.junit.Assert.assertNotNull;
96 import static org.junit.Assert.assertNull;
97 import static org.junit.Assert.assertThat;
98 import static org.junit.Assert.assertTrue;
99 import static org.junit.Assert.fail;
100
101
102
103 @SuppressWarnings("ConstantConditions")
104 public class AsynchronousIssueRestClientTest extends AbstractAsynchronousRestClientTest {
105
106 @Rule
107 public ExpectedException expectedException = ExpectedException.none();
108
109 public static final String UTF8_FILE_BODY = "File body encoded in utf8: Ka\u017a\u0144 i \u017c\u00f3\u0142to\u015b\u0107 b\u0119d\u0105! | \u1f55\u03b1\u03bb\u03bf\u03bd \u03d5\u03b1\u03b3\u03b5\u1fd6\u03bd \u03b4\u1f7b\u03bd\u03b1\u03bc\u03b1\u03b9\u0387 \u03c4\u03bf\u1fe6\u03c4\u03bf \u03bf\u1f54 \u03bc\u03b5 \u03b2\u03bb\u1f71\u03c0\u03c4\u03b5\u03b9 \u0411\u0438 \u0448\u0438\u043b \u0438\u0434\u044d\u0439 \u0447\u0430\u0434\u043d\u0430, \u043d\u0430\u0434\u0430\u0434 \u0445\u043e\u0440\u0442\u043e\u0439 \u0431\u0438\u0448., or 2\u03c0R";
110 public static final String UTF8_FILE_NAME = "utf8 file name Ka\u017a\u0144 i \u017c\u00f3\u0142to\u015b\u0107 b\u0119d\u0105! \u1f55\u03b1\u03bb\u03bf\u03bd \u03d5\u03b1\u03b3\u03b5\u1fd6\u03bd \u03b4\u1f7b\u03bd\u03b1\u03bc\u03b1\u03b9\u0387 \u03c4\u03bf\u1fe6\u03c4\u03bf \u03bf\u1f54 \u03bc\u03b5 \u03b2\u03bb\u1f71\u03c0\u03c4\u03b5\u03b9 \u0411\u0438 \u0448\u0438\u043b \u0438\u0434\u044d\u0439 \u0447\u0430\u0434\u043d\u0430, \u043d\u0430\u0434\u0430\u0434 \u0445\u043e\u0440\u0442\u043e\u0439 \u0431\u0438\u0448., or 2\u03c0R";
111
112 @Before
113 public void setup() {
114 IntegrationTestUtil.restoreAppropriateJiraData(TestConstants.DEFAULT_JIRA_DUMP_FILE, administration);
115 }
116
117 @Test
118 public void testTransitionWithNumericCustomFieldPolishLocale() throws Exception {
119 final double newValue = 123.45;
120 final FieldInput fieldInput;
121 if (IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER) {
122 fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
123 } else {
124 fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, NumberFormat.getNumberInstance(new Locale("pl"))
125 .format(newValue));
126 }
127 assertTransitionWithNumericCustomField(fieldInput, newValue);
128 }
129
130 @Test
131 public void testTransitionWithNumericCustomFieldEnglishLocale() throws Exception {
132 setUser1();
133 final double newValue = 123.45;
134 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID,
135 NumberFormat.getNumberInstance(new Locale("pl")).format(newValue));
136
137 assertErrorCode(Response.Status.BAD_REQUEST, IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER
138 ? "Operation value must be a number" : ("'" + fieldInput.getValue() + "' is an invalid number"), new Runnable() {
139 @Override
140 public void run() {
141 assertTransitionWithNumericCustomField(fieldInput, newValue);
142 }
143 });
144
145 final FieldInput fieldInput2 = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
146 assertTransitionWithNumericCustomField(fieldInput2, newValue);
147 }
148
149
150 private void assertTransitionWithNumericCustomField(FieldInput fieldInput, Double expectedValue) {
151 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
152 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
153 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
154
155 final Transition transitionFound = TestUtil.getTransitionByName(transitions, "Estimate");
156 assertNotNull(transitionFound);
157 assertTrue(Iterables.contains(transitionFound.getFields(),
158 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false,
159 IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ? NUMERIC_CUSTOMFIELD_TYPE_V5 : NUMERIC_CUSTOMFIELD_TYPE)));
160 client.getIssueClient().transition(issue, new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
161 Comment.valueOf("My test comment"))).claim();
162 final Issue changedIssue = client.getIssueClient().getIssue("TST-1").claim();
163 assertTrue(changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue().equals(expectedValue));
164 }
165
166 @Test
167 public void testDeleteIssue() {
168 final IssueRestClient issueClient = client.getIssueClient();
169
170
171 final String issueKey = "TST-1";
172 final Issue issue = issueClient.getIssue(issueKey).claim();
173 assertEquals(issueKey, issue.getKey());
174
175
176 issueClient.deleteIssue(issueKey, false).claim();
177
178
179 assertThatIssueNotExists(issueKey);
180 }
181
182 @Test
183 public void testDeleteIssueWithSubtasks() {
184 final IssueRestClient issueClient = client.getIssueClient();
185
186
187 final String issueKey = "TST-1";
188 final Issue issue = issueClient.getIssue(issueKey).claim();
189 assertEquals(issueKey, issue.getKey());
190 final BasicIssue subtask = addSubtaskToIssue(issue);
191 System.out.println(subtask);
192
193
194 issueClient.deleteIssue(issueKey, true).claim();
195
196
197 assertThatIssueNotExists(issueKey);
198 assertThatIssueNotExists(subtask.getKey());
199 }
200
201 @Test
202 public void testDeleteIssueWithSubtasksWhenDeleteSubtasksIsFalse() {
203 final IssueRestClient issueClient = client.getIssueClient();
204
205
206 final String issueKey = "TST-1";
207 final Issue issue = issueClient.getIssue(issueKey).claim();
208 assertEquals(issueKey, issue.getKey());
209 BasicIssue subtask = addSubtaskToIssue(issue);
210 System.out.println(subtask);
211
212
213 expectedException.expect(rceWithSingleError(400, String.format("The issue '%s' has subtasks. "
214 + "You must specify the 'deleteSubtasks' parameter to delete this issue and all its subtasks.", issueKey)));
215 issueClient.deleteIssue(issueKey, false).claim();
216 }
217
218 @Test
219 public void testDeleteIssueWhenNoSuchIssue() {
220 final IssueRestClient issueClient = client.getIssueClient();
221
222
223 final String issueKey = "TST-999";
224 assertThatIssueNotExists(issueKey);
225
226
227 expectedException.expect(rceWithSingleError(404, "Issue Does Not Exist"));
228 issueClient.deleteIssue(issueKey, false).claim();
229 }
230
231 @Test
232 public void testDeleteIssueWithoutDeletePermission() {
233 setAnonymousMode();
234 final IssueRestClient issueClient = client.getIssueClient();
235
236
237 final String issueKey = "ANONEDIT-2";
238 final Issue issue = issueClient.getIssue(issueKey).claim();
239 assertEquals(issueKey, issue.getKey());
240
241
242 expectedException.expect(rceWithSingleError(401, "You do not have permission to delete issues in this project."));
243 issueClient.deleteIssue(issueKey, false).claim();
244 }
245
246 @JiraBuildNumberDependent(BN_JIRA_5)
247 @Test
248 public void testUpdateField() {
249 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
250 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
251 final double newValue = 123;
252 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
253 client.getIssueClient().updateIssue(issue.getKey(), IssueInput.createWithFields(fieldInput)).claim();
254 final Issue changedIssue = client.getIssueClient().getIssue("TST-1").claim();
255 assertEquals(newValue, changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
256 }
257
258 @JiraBuildNumberDependent(BN_JIRA_5)
259 @Test
260 public void testUpdateMultipleFields() {
261 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
262 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
263 final double newNumericValue = 123;
264 final String newTextValue = "my new text";
265
266 final IssueInputBuilder issueInputBuilder = new IssueInputBuilder()
267 .setFieldValue(NUMERIC_CUSTOMFIELD_ID, newNumericValue)
268 .setFieldValue(TEXT_CUSTOMFIELD_ID, newTextValue);
269
270 client.getIssueClient().updateIssue(issue.getKey(), issueInputBuilder.build()).claim();
271 final Issue changedIssue = client.getIssueClient().getIssue("TST-1").claim();
272 assertNotNull(changedIssue);
273 assertEquals(newNumericValue, changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
274 assertEquals(newTextValue, changedIssue.getField(TEXT_CUSTOMFIELD_ID).getValue());
275 }
276
277 @JiraBuildNumberDependent(BN_JIRA_5)
278 @Test
279 public void testUpdateIssueWithInvalidAdditionalField() {
280 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
281 final String fieldId = "invalidField";
282
283 expectedException.expect(RestClientException.class);
284 expectedException.expectMessage(String.format(
285 "Field '%s' cannot be set. It is not on the appropriate screen, or unknown.", fieldId));
286 final FieldInput fieldInput = new FieldInput(fieldId, "who cares?");
287 client.getIssueClient().updateIssue(issue.getKey(), IssueInput.createWithFields(fieldInput)).claim();
288 }
289
290 @JiraBuildNumberDependent(BN_JIRA_5)
291 @Test
292 public void testUpdateIssueWithoutPermissions() {
293 setUser2();
294
295 expectedException.expect(RestClientException.class);
296 expectedException.expectMessage(String.format(
297 "Field '%s' cannot be set. It is not on the appropriate screen, or unknown.", NUMERIC_CUSTOMFIELD_ID));
298 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, 1.23d);
299 client.getIssueClient().updateIssue("TST-1", IssueInput.createWithFields(fieldInput)).claim();
300 }
301
302 @Test
303 public void testTransitionWithNumericCustomFieldAndInteger() throws Exception {
304 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
305 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
306 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
307 final Transition transitionFound = TestUtil.getTransitionByName(transitions, "Estimate");
308
309 assertNotNull(transitionFound);
310 assertTrue(Iterables.contains(transitionFound.getFields(),
311 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false,
312 IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ? NUMERIC_CUSTOMFIELD_TYPE_V5 : NUMERIC_CUSTOMFIELD_TYPE)));
313 final double newValue = 123;
314 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, newValue);
315 client.getIssueClient().transition(issue.getTransitionsUri(), new TransitionInput(transitionFound.getId(), Arrays
316 .asList(fieldInput),
317 Comment.valueOf("My test comment"))).claim();
318 final Issue changedIssue = client.getIssueClient().getIssue("TST-1").claim();
319 assertEquals(newValue, changedIssue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
320 }
321
322 @Test
323 public void testTransitionWithInvalidNumericField() throws Exception {
324 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
325 assertNull(issue.getField(NUMERIC_CUSTOMFIELD_ID).getValue());
326 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
327 final Transition transitionFound = TestUtil.getTransitionByName(transitions, "Estimate");
328
329 assertNotNull(transitionFound);
330 assertTrue(Iterables.contains(transitionFound.getFields(),
331 new Transition.Field(NUMERIC_CUSTOMFIELD_ID, false,
332 TESTING_JIRA_5_OR_NEWER ? NUMERIC_CUSTOMFIELD_TYPE_V5 : NUMERIC_CUSTOMFIELD_TYPE)));
333 final FieldInput fieldInput = new FieldInput(NUMERIC_CUSTOMFIELD_ID, "]432jl");
334
335
336 assertErrorCode(Response.Status.BAD_REQUEST, TESTING_JIRA_5_OR_NEWER
337 ? "Operation value must be a number" : "']432jl' nie jest prawid\u0142ow\u0105 liczb\u0105", new Runnable() {
338 @Override
339 public void run() {
340 client.getIssueClient().transition(issue, new TransitionInput(transitionFound.getId(), Arrays.asList(fieldInput),
341 Comment.valueOf("My test comment"))).claim();
342 }
343 });
344 }
345
346 @Test
347 public void testTransitionWithNoRoleOrGroup() {
348 Comment comment = Comment.valueOf("My text which I am just adding " + new DateTime());
349 testTransitionImpl(comment);
350 }
351
352 @Test
353 public void testTransitionWithRoleLevel() {
354 Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "Users");
355 testTransitionImpl(comment);
356 }
357
358 @Test
359 public void testTransitionWithGroupLevel() {
360 Comment comment = Comment.createWithGroupLevel("My text which I am just adding " + new DateTime(), "jira-users");
361 testTransitionImpl(comment);
362 }
363
364 @Test
365 public void testTransitionWithInvalidRole() {
366 final Comment comment = Comment.createWithRoleLevel("My text which I am just adding " + new DateTime(), "some-fake-role");
367 if (IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER) {
368 assertInvalidCommentInput(comment, "Invalid role level specified.");
369 } else {
370 assertInvalidCommentInput(comment, "Invalid role [some-fake-role]");
371 }
372 }
373
374 @Test
375 public void testTransitionWithInvalidGroup() {
376 final Comment comment = Comment.createWithGroupLevel(
377 "My text which I am just adding " + new DateTime(), "some-fake-group");
378 assertInvalidCommentInput(comment, "Group: some-fake-group does not exist.");
379 }
380
381 private void assertInvalidCommentInput(final Comment comment, String expectedErrorMsg) {
382 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
383 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
384 final Transition transitionFound = TestUtil.getTransitionByName(transitions, "Estimate");
385 final String errorMsg = doesJiraServeCorrectlyErrorMessagesForBadRequestWhileTransitioningIssue()
386 ? expectedErrorMsg : null;
387 assertErrorCode(Response.Status.BAD_REQUEST, errorMsg, new Runnable() {
388 @Override
389 public void run() {
390 client.getIssueClient().transition(issue, new TransitionInput(transitionFound.getId(), comment)).claim();
391 }
392 });
393 }
394
395 private void testTransitionImpl(Comment comment) {
396 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
397 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
398 Transition transitionFound = TestUtil.getTransitionByName(transitions, "Estimate");
399 DateTime now = new DateTime();
400 client.getIssueClient().transition(issue, new TransitionInput(transitionFound.getId(), comment)).claim();
401
402 final Issue changedIssue = client.getIssueClient().getIssue("TST-1").claim();
403 final Comment lastComment = Iterables.getLast(changedIssue.getComments());
404 assertEquals(comment.getBody(), lastComment.getBody());
405 assertEquals(IntegrationTestUtil.USER_ADMIN, lastComment.getAuthor());
406 assertEquals(IntegrationTestUtil.USER_ADMIN, lastComment.getUpdateAuthor());
407 assertEquals(lastComment.getCreationDate(), lastComment.getUpdateDate());
408 assertTrue(lastComment.getCreationDate().isAfter(now) || lastComment.getCreationDate().isEqual(now));
409 assertEquals(comment.getVisibility(), lastComment.getVisibility());
410 }
411
412 @Test
413 public void testVoteUnvote() {
414 final Issue issue1 = client.getIssueClient().getIssue("TST-1").claim();
415 assertFalse(issue1.getVotes().hasVoted());
416 assertEquals(1, issue1.getVotes().getVotes());
417 final String expectedMessage = isJira5xOrNewer()
418 ? "You cannot vote for an issue you have reported."
419 : "Nie mo\u017cesz g\u0142osowa\u0107 na zadanie kt\u00f3re utworzy\u0142e\u015b.";
420
421
422 assertErrorCode(Response.Status.NOT_FOUND, expectedMessage, new Runnable() {
423 @Override
424 public void run() {
425 client.getIssueClient().vote(issue1.getVotesUri()).claim();
426 }
427 });
428
429
430 final String issueKey = "TST-7";
431 Issue issue = client.getIssueClient().getIssue(issueKey).claim();
432 assertFalse(issue.getVotes().hasVoted());
433 assertEquals(0, issue.getVotes().getVotes());
434
435 client.getIssueClient().vote(issue.getVotesUri()).claim();
436 issue = client.getIssueClient().getIssue(issueKey).claim();
437 assertTrue(issue.getVotes().hasVoted());
438 assertEquals(1, issue.getVotes().getVotes());
439
440 client.getIssueClient().unvote(issue.getVotesUri()).claim();
441 issue = client.getIssueClient().getIssue(issueKey).claim();
442 assertFalse(issue.getVotes().hasVoted());
443 assertEquals(0, issue.getVotes().getVotes());
444
445 setUser2();
446 issue = client.getIssueClient().getIssue(issueKey).claim();
447 assertFalse(issue.getVotes().hasVoted());
448 assertEquals(0, issue.getVotes().getVotes());
449 final Issue finalIssue = issue;
450 if (isJira6_3_7_OrNewer()) {
451 client.getIssueClient().unvote(finalIssue.getVotesUri()).claim();
452 issue = client.getIssueClient().getIssue(issueKey).claim();
453 assertEquals(0, issue.getVotes().getVotes());
454 } else {
455 assertErrorCode(Response.Status.NOT_FOUND, "Cannot remove a vote for an issue that the user has not already voted for.",
456 new Runnable() {
457 @Override
458 public void run() {
459 client.getIssueClient().unvote(finalIssue.getVotesUri()).claim();
460 }
461 });
462 }
463
464 issue = client.getIssueClient().getIssue(issueKey).claim();
465 assertFalse(issue.getVotes().hasVoted());
466 assertEquals(0, issue.getVotes().getVotes());
467 client.getIssueClient().vote(issue.getVotesUri()).claim();
468 issue = client.getIssueClient().getIssue(issueKey).claim();
469 assertTrue(issue.getVotes().hasVoted());
470 assertEquals(1, issue.getVotes().getVotes());
471
472 setClient(ADMIN_USERNAME, ADMIN_PASSWORD);
473 client.getIssueClient().vote(issue.getVotesUri()).claim();
474 issue = client.getIssueClient().getIssue(issueKey).claim();
475 assertTrue(issue.getVotes().hasVoted());
476 assertEquals(2, issue.getVotes().getVotes());
477 }
478
479 @Test
480 public void testWatchUnwatch() {
481 final IssueRestClient issueClient = client.getIssueClient();
482 final Issue issue1 = issueClient.getIssue("TST-1").claim();
483
484 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
485 .getUsers(), not(hasItem(IntegrationTestUtil.USER_ADMIN)));
486
487 issueClient.watch(issue1.getWatchers().getSelf()).claim();
488 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
489 .getUsers(), hasItem(IntegrationTestUtil.USER_ADMIN));
490
491 issueClient.unwatch(issue1.getWatchers().getSelf()).claim();
492 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
493 .getUsers(), not(hasItem(IntegrationTestUtil.USER_ADMIN)));
494
495 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
496 .getUsers(), hasItem(IntegrationTestUtil.USER1));
497 issueClient.removeWatcher(issue1.getWatchers().getSelf(), IntegrationTestUtil.USER1.getName()).claim();
498 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
499 .getUsers(), not(hasItem(IntegrationTestUtil.USER1)));
500 issueClient.addWatcher(issue1.getWatchers().getSelf(), IntegrationTestUtil.USER1.getName()).claim();
501 Assert.assertThat(issueClient.getWatchers(issue1.getWatchers().getSelf()).claim()
502 .getUsers(), hasItem(IntegrationTestUtil.USER1));
503 }
504
505 @Test
506 public void testRemoveWatcherUnauthorized() {
507 final IssueRestClient issueClient = client.getIssueClient();
508 final Issue issue1 = issueClient.getIssue("TST-1").claim();
509 issueClient.watch(issue1.getWatchers().getSelf()).claim();
510
511 setUser1();
512 final IssueRestClient issueClient2 = client.getIssueClient();
513 assertErrorCode(Response.Status.UNAUTHORIZED,
514 "User 'wseliga' is not allowed to remove watchers from issue 'TST-1'", new Runnable() {
515 @Override
516 public void run() {
517 issueClient2.removeWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME).claim();
518 }
519 });
520 }
521
522
523 @Test
524 public void testWatchAlreadyWatched() {
525 setUser1();
526 final IssueRestClient issueClient = client.getIssueClient();
527 final Issue issue = issueClient.getIssue("TST-1").claim();
528 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf()).claim()
529 .getUsers(), hasItem(IntegrationTestUtil.USER1));
530
531 issueClient.watch(issue.getWatchers().getSelf()).claim();
532 Assert.assertThat(client.getIssueClient().getWatchers(issue.getWatchers().getSelf()).claim()
533 .getUsers(), hasItem(IntegrationTestUtil.USER1));
534 }
535
536 @Test
537 public void testAddWatcherUnauthorized() {
538 final IssueRestClient issueClient = client.getIssueClient();
539 final Issue issue1 = issueClient.getIssue("TST-1").claim();
540 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER1_USERNAME).claim();
541 assertThat(client.getIssueClient().getWatchers(issue1.getWatchers().getSelf()).claim()
542 .getUsers(), hasItem(IntegrationTestUtil.USER1));
543
544 setUser1();
545 assertTrue(client.getIssueClient().getIssue("TST-1").claim().getWatchers().isWatching());
546 String expectedErrorMsg = isJraDev3516Fixed() ? ("User '" + USER1_USERNAME
547 + "' is not allowed to add watchers to issue 'TST-1'") : null;
548 assertErrorCode(Response.Status.UNAUTHORIZED, expectedErrorMsg, new Runnable() {
549 @Override
550 public void run() {
551 client.getIssueClient().addWatcher(issue1.getWatchers().getSelf(), ADMIN_USERNAME).claim();
552 }
553 });
554 }
555
556 private boolean isJraDev3516Fixed() {
557 return client.getMetadataClient().getServerInfo().claim().getBuildNumber() >= BN_JIRA_4_3;
558 }
559
560 @Test
561 public void testAddWatcherWhoDoesNotHaveViewIssuePermissions() {
562 final IssueRestClient issueClient = client.getIssueClient();
563 final String issueKey = "RST-1";
564 final Issue issue1 = issueClient.getIssue(issueKey).claim();
565 final String expectedErrorMessage;
566
567 if (isJira5xOrNewer()) {
568 expectedErrorMessage = "The user \"" + USER2_USERNAME + "\" does not have permission to view this issue."
569 + " This user will not be added to the watch list.";
570 } else if (isJira43xOrNewer()) {
571 expectedErrorMessage = "User '" + ADMIN_USERNAME + "' is not allowed to add watchers to issue '" + issueKey + "'";
572 } else {
573 expectedErrorMessage = "com.sun.jersey.api.client.UniformInterfaceException: Client response status: 401";
574 }
575
576 assertErrorCode(Response.Status.UNAUTHORIZED, expectedErrorMessage,
577 new Runnable() {
578 @Override
579 public void run() {
580 issueClient.addWatcher(issue1.getWatchers().getSelf(), USER2_USERNAME).claim();
581 }
582 });
583 }
584
585 @JiraBuildNumberDependent(BN_JIRA_4_3)
586 @Test
587 public void testLinkIssuesWithRoleLevel() {
588 testLinkIssuesImpl(Comment.createWithRoleLevel("A comment about linking", "Administrators"));
589 }
590
591 @JiraBuildNumberDependent(BN_JIRA_4_3)
592 @Test
593 public void testLinkIssuesWithGroupLevel() {
594 testLinkIssuesImpl(Comment.createWithGroupLevel("A comment about linking", "jira-administrators"));
595 }
596
597 @JiraBuildNumberDependent(BN_JIRA_4_3)
598 @Test
599 public void testLinkIssuesWithSimpleComment() {
600 testLinkIssuesImpl(Comment.valueOf("A comment about linking"));
601 }
602
603 @JiraBuildNumberDependent(BN_JIRA_4_3)
604 @Test
605 public void testLinkIssuesWithoutComment() {
606 testLinkIssuesImpl(null);
607 }
608
609 @JiraBuildNumberDependent(BN_JIRA_4_3)
610 @Test
611 public void testLinkIssuesWithInvalidParams() {
612 assertErrorCode(Response.Status.NOT_FOUND,
613 IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ? "Issue Does Not Exist"
614 : "The issue no longer exists.", new Runnable() {
615 @Override
616 public void run() {
617 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "FAKEKEY-1", "Duplicate", null)).claim();
618 }
619 });
620
621 assertErrorCode(Response.Status.NOT_FOUND, "No issue link type with name 'NonExistingLinkType' found.", new Runnable() {
622 @Override
623 public void run() {
624 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "NonExistingLinkType", null)).claim();
625 }
626 });
627
628 setUser1();
629 final String optionalDot = isJira5xOrNewer() ? "." : "";
630 assertErrorCode(Response.Status.NOT_FOUND,
631 "You do not have the permission to see the specified issue" + optionalDot, new Runnable() {
632 @Override
633 public void run() {
634 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "RST-1", "Duplicate", null)).claim();
635 }
636 });
637 final ErrorCollection.Builder ecb = ErrorCollection.builder();
638 ecb.status(Response.Status.BAD_REQUEST.getStatusCode())
639 .errorMessage("Failed to create comment for issue 'TST-6'")
640 .error("commentLevel", "You are currently not a member of the project role: Administrators.");
641 final ImmutableList<ErrorCollection> errorCollections = ImmutableList.of(ecb.build());
642
643 assertExpectedErrorCollection(errorCollections, new Runnable() {
644 @Override
645 public void run() {
646 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
647 Comment.createWithRoleLevel("my body", "Administrators"))).claim();
648 }
649 });
650 assertErrorCode(Response.Status.BAD_REQUEST, "You are currently not a member of the group: jira-administrators.", new Runnable() {
651 @Override
652 public void run() {
653 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
654 Comment.createWithGroupLevel("my body", "jira-administrators"))).claim();
655 }
656 });
657 assertErrorCode(Response.Status.BAD_REQUEST, "Group: somefakegroup does not exist.", new Runnable() {
658 @Override
659 public void run() {
660 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate",
661 Comment.createWithGroupLevel("my body", "somefakegroup"))).claim();
662 }
663 });
664 }
665
666 @JiraBuildNumberDependent(condition = LongCondition.LESS_THAN, value = 6211)
667 @Test
668 public void testLinkIssuesWithInvalidParamsBeforeUpgradeTask6211() {
669 setUser2();
670 assertErrorCode(Response.Status.UNAUTHORIZED, "No Link Issue Permission for issue 'TST-7'", new Runnable() {
671 @Override
672 public void run() {
673 client.getIssueClient().linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate", null)).claim();
674 }
675 });
676 }
677
678 @JiraBuildNumberDependent(6211)
679 @Test
680 public void testLinkIssuesForUserRoleLevelAfterUpgradeTask6211() {
681 testLinkIssuesImpl(Comment.createWithRoleLevel("A comment about linking", "Users"));
682 }
683
684 private void testLinkIssuesImpl(@Nullable Comment commentInput) {
685 final IssueRestClient issueClient = client.getIssueClient();
686 final Issue originalIssue = issueClient.getIssue("TST-7").claim();
687 int origNumComments = Iterables.size(originalIssue.getComments());
688 assertFalse(originalIssue.getIssueLinks().iterator().hasNext());
689
690 issueClient.linkIssue(new LinkIssuesInput("TST-7", "TST-6", "Duplicate", commentInput)).claim();
691
692 final Issue linkedIssue = issueClient.getIssue("TST-7").claim();
693 assertEquals(1, Iterables.size(linkedIssue.getIssueLinks()));
694 final IssueLink addedLink = linkedIssue.getIssueLinks().iterator().next();
695 assertEquals("Duplicate", addedLink.getIssueLinkType().getName());
696 assertEquals("TST-6", addedLink.getTargetIssueKey());
697 assertEquals(IssueLinkType.Direction.OUTBOUND, addedLink.getIssueLinkType().getDirection());
698
699 final int expectedNumComments = commentInput != null ? origNumComments + 1 : origNumComments;
700 assertEquals(expectedNumComments, Iterables.size(linkedIssue.getComments()));
701 if (commentInput != null) {
702 final Comment comment = linkedIssue.getComments().iterator().next();
703 assertEquals(commentInput.getBody(), comment.getBody());
704 assertEquals(IntegrationTestUtil.USER_ADMIN, comment.getAuthor());
705 assertEquals(commentInput.getVisibility(), comment.getVisibility());
706 } else {
707 assertFalse(linkedIssue.getComments().iterator().hasNext());
708 }
709
710
711 final Issue targetIssue = issueClient.getIssue("TST-6").claim();
712 final IssueLink targetLink = targetIssue.getIssueLinks().iterator().next();
713 assertEquals(IssueLinkType.Direction.INBOUND, targetLink.getIssueLinkType().getDirection());
714 assertEquals("Duplicate", targetLink.getIssueLinkType().getName());
715 }
716
717 private boolean doesJiraSupportAddingAttachment() {
718 return client.getMetadataClient().getServerInfo().claim().getBuildNumber() >= BN_JIRA_4_3;
719 }
720
721 private boolean doesJiraServeCorrectlyErrorMessagesForBadRequestWhileTransitioningIssue() {
722 return client.getMetadataClient().getServerInfo().claim().getBuildNumber() >= BN_JIRA_4_3;
723 }
724
725 @Test
726
727 public void testAddAttachment() throws IOException {
728
729 if (!doesJiraSupportAddingAttachment()) {
730 return;
731 }
732 final IssueRestClient issueClient = client.getIssueClient();
733 final Issue issue = issueClient.getIssue("TST-3").claim();
734 assertFalse(issue.getAttachments().iterator().hasNext());
735
736 String str = "Wojtek";
737 final String filename1 = "my-test-file";
738 issueClient.addAttachment(issue.getAttachmentsUri(), new ByteArrayInputStream(str.getBytes("UTF-8")), filename1).claim();
739 final String filename2 = "my-picture.png";
740 issueClient.addAttachment(issue.getAttachmentsUri(), AsynchronousIssueRestClientTest.class
741 .getResourceAsStream("/attachment-test/transparent-png.png"), filename2).claim();
742
743 final Issue issueWithAttachments = issueClient.getIssue("TST-3").claim();
744 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
745 assertEquals(2, Iterables.size(attachments));
746 final Iterable<String> attachmentsNames = Iterables.transform(attachments, new Function<Attachment, String>() {
747 @Override
748 public String apply(@Nullable Attachment from) {
749 return from.getFilename();
750 }
751 });
752 assertThat(attachmentsNames, containsInAnyOrder(filename1, filename2));
753 final Attachment pictureAttachment = Iterables.find(attachments, new Predicate<Attachment>() {
754 @Override
755 public boolean apply(@Nullable Attachment input) {
756 return filename2.equals(input.getFilename());
757 }
758 });
759
760
761
762 assertTrue(
763 IOUtils.contentEquals(AsynchronousIssueRestClientTest.class
764 .getResourceAsStream("/attachment-test/transparent-png.png"),
765 issueClient.getAttachment(pictureAttachment.getContentUri()).claim()));
766 }
767
768 @Test
769 public void testAddAttachmentWithUtf8InNameAndBody() throws IOException {
770 final IssueRestClient issueClient = client.getIssueClient();
771 final Issue issue = issueClient.getIssue("TST-3").claim();
772 assertFalse(issue.getAttachments().iterator().hasNext());
773
774 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(UTF8_FILE_BODY.getBytes("UTF-8"));
775 issueClient.addAttachment(issue.getAttachmentsUri(), byteArrayInputStream, UTF8_FILE_NAME).claim();
776
777 final Issue issueWithAttachments = issueClient.getIssue("TST-3").claim();
778 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
779 assertEquals(1, Iterables.size(attachments));
780 final Attachment attachment = attachments.iterator().next();
781 assertThat(attachment.getFilename(), equalTo(UTF8_FILE_NAME));
782
783 assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(UTF8_FILE_BODY.getBytes("UTF-8")),
784 issueClient.getAttachment(attachment.getContentUri()).claim()));
785 }
786
787 @Test
788
789 public void testAddAttachments() throws IOException {
790 if (!doesJiraSupportAddingAttachment()) {
791 return;
792 }
793 final IssueRestClient issueClient = client.getIssueClient();
794 final Issue issue = issueClient.getIssue("TST-4").claim();
795 assertFalse(issue.getAttachments().iterator().hasNext());
796
797 final AttachmentInput[] attachmentInputs = new AttachmentInput[3];
798 for (int i = 1; i <= 3; i++) {
799 attachmentInputs[i - 1] = new AttachmentInput("my-test-file-" + i + ".txt", new ByteArrayInputStream((
800 "content-of-the-file-" + i).getBytes("UTF-8")));
801 }
802 issueClient.addAttachments(issue.getAttachmentsUri(), attachmentInputs).claim();
803
804 final Issue issueWithAttachments = issueClient.getIssue("TST-4").claim();
805 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
806 assertEquals(3, Iterables.size(attachments));
807 Pattern pattern = Pattern.compile("my-test-file-(\\d)\\.txt");
808 for (Attachment attachment : attachments) {
809 assertTrue(pattern.matcher(attachment.getFilename()).matches());
810 final Matcher matcher = pattern.matcher(attachment.getFilename());
811 matcher.find();
812 final String interfix = matcher.group(1);
813 assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(("content-of-the-file-" + interfix).getBytes("UTF-8")),
814 issueClient.getAttachment(attachment.getContentUri()).claim()));
815
816 }
817 }
818
819 @Test
820 public void testAddAttachmentsWithUtf8InNameAndBody() throws IOException {
821 final IssueRestClient issueClient = client.getIssueClient();
822 final Issue issue = issueClient.getIssue("TST-4").claim();
823 assertFalse(issue.getAttachments().iterator().hasNext());
824
825 final AttachmentInput[] attachmentInputs = new AttachmentInput[3];
826 final String[] names = new String[3];
827 final String[] contents = new String[3];
828 for (int i = 0; i < 3; i++) {
829 names[i] = UTF8_FILE_NAME + "-" + i + ".txt";
830 contents[i] = "content-of-the-file-" + i + " with some utf8: " + UTF8_FILE_BODY;
831 attachmentInputs[i] = new AttachmentInput(names[i], new ByteArrayInputStream(contents[i].getBytes("UTF-8")));
832 }
833 issueClient.addAttachments(issue.getAttachmentsUri(), attachmentInputs).claim();
834
835 final Issue issueWithAttachments = issueClient.getIssue("TST-4").claim();
836 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
837 assertEquals(3, Iterables.size(attachments));
838 Pattern pattern = Pattern.compile(".*-(\\d)\\.txt");
839 for (Attachment attachment : attachments) {
840 assertTrue(pattern.matcher(attachment.getFilename()).matches());
841 final Matcher matcher = pattern.matcher(attachment.getFilename());
842 matcher.find();
843 final int attachmentNum = Integer.parseInt(matcher.group(1));
844 assertThat(attachment.getFilename(), equalTo(names[attachmentNum]));
845 assertTrue(IOUtils.contentEquals(new ByteArrayInputStream((contents[attachmentNum]).getBytes("UTF-8")),
846 issueClient.getAttachment(attachment.getContentUri()).claim()));
847
848 }
849 }
850
851 @Test
852
853 public void testAddFileAttachments() throws IOException {
854 if (!doesJiraSupportAddingAttachment()) {
855 return;
856 }
857 final IssueRestClient issueClient = client.getIssueClient();
858 final Issue issue = issueClient.getIssue("TST-5").claim();
859 assertFalse(issue.getAttachments().iterator().hasNext());
860
861 final File tempFile = File.createTempFile("jim-integration-test", ".txt");
862 tempFile.deleteOnExit();
863 FileWriter writer = new FileWriter(tempFile);
864 writer.write("This is the content of my file which I am going to upload to JIRA for testing.");
865 writer.close();
866 issueClient.addAttachments(issue.getAttachmentsUri(), tempFile).claim();
867
868 final Issue issueWithAttachments = issueClient.getIssue("TST-5").claim();
869 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
870 assertEquals(1, Iterables.size(attachments));
871 assertTrue(IOUtils.contentEquals(new FileInputStream(tempFile),
872 issueClient.getAttachment(attachments.iterator().next().getContentUri()).claim()));
873 }
874
875 @Test
876 public void testAddFileAttachmentWithUtf8InNameAndBody() throws IOException {
877 final IssueRestClient issueClient = client.getIssueClient();
878 final Issue issue = issueClient.getIssue("TST-5").claim();
879 assertFalse(issue.getAttachments().iterator().hasNext());
880
881 final File tempFile = File.createTempFile(UTF8_FILE_NAME, ".txt");
882 tempFile.deleteOnExit();
883 FileWriter writer = new FileWriter(tempFile);
884 writer.write(UTF8_FILE_BODY);
885 writer.close();
886 issueClient.addAttachments(issue.getAttachmentsUri(), tempFile).claim();
887
888 final Issue issueWithAttachments = issueClient.getIssue("TST-5").claim();
889 final Iterable<Attachment> attachments = issueWithAttachments.getAttachments();
890 assertEquals(1, Iterables.size(attachments));
891 final Attachment firstAttachment = attachments.iterator().next();
892 assertTrue(IOUtils.contentEquals(new FileInputStream(tempFile),
893 issueClient.getAttachment(firstAttachment.getContentUri()).claim()));
894 assertThat(firstAttachment.getFilename(), equalTo(tempFile.getName()));
895 }
896
897 private void setUserLanguageToEnUk() {
898 changeUserLanguageByValueOrName("en_UK", "angielski (UK)");
899 }
900
901 private void changeUserLanguageByValueOrName(String value, String name) {
902 final UserProfile userProfile = navigation.userProfile();
903 boolean fallbackToChangeByValue = false;
904 try {
905 Method changeUserLanguageByValue = userProfile.getClass().getMethod("changeUserLanguageByValue", String.class);
906 changeUserLanguageByValue.invoke(userProfile, value);
907 } catch (NoSuchMethodException e) {
908
909 fallbackToChangeByValue = true;
910 } catch (InvocationTargetException e) {
911 fallbackToChangeByValue = true;
912 } catch (IllegalAccessException e) {
913 fallbackToChangeByValue = true;
914 }
915
916 if (fallbackToChangeByValue) {
917 userProfile.changeUserLanguage(name);
918 }
919 }
920
921 @Test
922 public void testFetchingUnassignedIssue() {
923 administration.generalConfiguration().setAllowUnassignedIssues(true);
924 assertEquals(IntegrationTestUtil.USER_ADMIN, client.getIssueClient().getIssue("TST-5").claim().getAssignee());
925
926 setUserLanguageToEnUk();
927 navigation.issue().unassignIssue("TST-5", "unassigning issue");
928
929
930
931
932 assertNull(client.getIssueClient().getIssue("TST-5").claim().getAssignee());
933 }
934
935 @Test
936 public void testFetchingIssueWithAnonymousComment() {
937 setUserLanguageToEnUk();
938 final String commentText = "my nice comment";
939 final String issueKey = "ANONEDIT-1";
940
941 navigation.logout();
942 navigation.issue().addComment(issueKey, commentText);
943
944 final Issue issue = client.getIssueClient().getIssue(issueKey).claim();
945 assertEquals(1, Iterables.size(issue.getComments()));
946 final Comment comment = issue.getComments().iterator().next();
947 assertEquals(commentText, comment.getBody());
948 if (isJira5xOrNewer()) {
949 assertNotNull(comment.getId());
950 } else {
951 assertNull(comment.getId());
952 }
953 assertNull(comment.getAuthor());
954 assertNull(comment.getUpdateAuthor());
955 }
956
957 @Test
958 public void testGetIssueWithNoViewWatchersPermission() {
959 setUser1();
960 assertTrue(client.getIssueClient().getIssue("TST-1").claim().getWatchers().isWatching());
961
962 setUser2();
963 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
964 assertFalse(issue.getWatchers().isWatching());
965 client.getIssueClient().watch(issue.getWatchers().getSelf()).claim();
966 final Issue watchedIssue = client.getIssueClient().getIssue("TST-1").claim();
967 assertTrue(watchedIssue.getWatchers().isWatching());
968 assertEquals(2, watchedIssue.getWatchers().getNumWatchers());
969
970
971
972 assertThat(client.getIssueClient().getWatchers(watchedIssue.getWatchers().getSelf()).claim().getUsers(),
973 containsInAnyOrder(USER2));
974 }
975
976 @Test
977 public void testTransition() throws Exception {
978 final Issue issue = client.getIssueClient().getIssue("TST-1").claim();
979 final Iterable<Transition> transitions = client.getIssueClient().getTransitions(issue).claim();
980 assertEquals(4, Iterables.size(transitions));
981 final Transition startProgressTransition = new Transition("Start Progress", IntegrationTestUtil.START_PROGRESS_TRANSITION_ID, Collections
982 .<Transition.Field>emptyList());
983 assertTrue(Iterables.contains(transitions, startProgressTransition));
984
985 client.getIssueClient().transition(issue, new TransitionInput(IntegrationTestUtil.START_PROGRESS_TRANSITION_ID,
986 Collections.<FieldInput>emptyList(), Comment.valueOf("My test comment"))).claim();
987 final Issue transitionedIssue = client.getIssueClient().getIssue("TST-1").claim();
988 assertEquals("In Progress", transitionedIssue.getStatus().getName());
989 final Iterable<Transition> transitionsAfterTransition = client.getIssueClient().getTransitions(issue).claim();
990 assertFalse(Iterables.contains(transitionsAfterTransition, startProgressTransition));
991 final Transition stopProgressTransition = new Transition("Stop Progress", IntegrationTestUtil.STOP_PROGRESS_TRANSITION_ID, Collections
992 .<Transition.Field>emptyList());
993 assertTrue(Iterables.contains(transitionsAfterTransition, stopProgressTransition));
994 }
995
996 private void assertThatIssueNotExists(String issueKey) {
997 try {
998 final Issue issue = client.getIssueClient().getIssue(issueKey).claim();
999 fail("It looks that issue exists, and it should not be here! issue = " + issue);
1000 } catch (RestClientException ex) {
1001 assertThat(ex, rceWithSingleError(404, "Issue Does Not Exist"));
1002 }
1003 }
1004
1005 private BasicIssue addSubtaskToIssue(final Issue issue) {
1006
1007 final IssueRestClient issueClient = client.getIssueClient();
1008 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
1009 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys(issue.getProject().getKey())
1010 .withExpandedIssueTypesFields().build()).claim();
1011
1012
1013 assertEquals(1, Iterables.size(metadataProjects));
1014 final CimProject project = metadataProjects.iterator().next();
1015 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Sub-task");
1016
1017
1018 final String summary = "Some subtask";
1019 final String description = "Some description for substask";
1020
1021
1022 final IssueInputBuilder issueInputBuilder = new IssueInputBuilder(project, issueType, summary)
1023 .setDescription(description)
1024 .setFieldValue("parent", ComplexIssueInputFieldValue.with("key", issue.getKey()));
1025
1026
1027 final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInputBuilder.build()).claim();
1028 assertNotNull(basicCreatedIssue.getKey());
1029
1030 return basicCreatedIssue;
1031 }
1032 }