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.nimblefunctests.annotation.JiraBuildNumberDependent;
20 import com.atlassian.jira.rest.client.IntegrationTestUtil;
21 import com.atlassian.jira.rest.client.api.GetCreateIssueMetadataOptionsBuilder;
22 import com.atlassian.jira.rest.client.api.IssueRestClient;
23 import com.atlassian.jira.rest.client.api.RestClientException;
24 import com.atlassian.jira.rest.client.api.domain.BasicComponent;
25 import com.atlassian.jira.rest.client.api.domain.BasicIssue;
26 import com.atlassian.jira.rest.client.api.domain.BasicPriority;
27 import com.atlassian.jira.rest.client.api.domain.BasicUser;
28 import com.atlassian.jira.rest.client.api.domain.BulkOperationResult;
29 import com.atlassian.jira.rest.client.api.domain.CimFieldInfo;
30 import com.atlassian.jira.rest.client.api.domain.CimIssueType;
31 import com.atlassian.jira.rest.client.api.domain.CimProject;
32 import com.atlassian.jira.rest.client.api.domain.CustomFieldOption;
33 import com.atlassian.jira.rest.client.api.domain.EntityHelper;
34 import com.atlassian.jira.rest.client.api.domain.Issue;
35 import com.atlassian.jira.rest.client.api.domain.IssueFieldId;
36 import com.atlassian.jira.rest.client.api.domain.IssueType;
37 import com.atlassian.jira.rest.client.api.domain.Subtask;
38 import com.atlassian.jira.rest.client.api.domain.TimeTracking;
39 import com.atlassian.jira.rest.client.api.domain.User;
40 import com.atlassian.jira.rest.client.api.domain.input.CannotTransformValueException;
41 import com.atlassian.jira.rest.client.api.domain.input.ComplexIssueInputFieldValue;
42 import com.atlassian.jira.rest.client.api.domain.input.FieldInput;
43 import com.atlassian.jira.rest.client.api.domain.input.IssueInput;
44 import com.atlassian.jira.rest.client.api.domain.input.IssueInputBuilder;
45 import com.atlassian.jira.rest.client.api.domain.input.PropertyInput;
46 import com.atlassian.jira.rest.client.api.domain.util.ErrorCollection;
47 import com.atlassian.jira.rest.client.internal.json.JsonParseUtil;
48 import com.atlassian.jira.rest.client.internal.json.TestConstants;
49 import com.google.common.base.Function;
50 import com.google.common.base.Predicate;
51 import com.google.common.collect.ImmutableList;
52 import com.google.common.collect.ImmutableMap;
53 import com.google.common.collect.ImmutableSet;
54 import com.google.common.collect.Iterables;
55 import com.google.common.collect.Lists;
56 import com.google.common.collect.Sets;
57 import org.codehaus.jettison.json.JSONArray;
58 import org.codehaus.jettison.json.JSONException;
59 import org.codehaus.jettison.json.JSONObject;
60 import org.hamcrest.Matchers;
61 import org.hamcrest.collection.IsIterableWithSize;
62 import org.joda.time.DateTime;
63 import org.junit.Before;
64 import org.junit.Rule;
65 import org.junit.Test;
66 import org.junit.rules.ExpectedException;
67
68 import java.text.MessageFormat;
69 import java.util.ArrayList;
70 import java.util.Collection;
71 import java.util.Collections;
72 import java.util.Date;
73 import java.util.List;
74 import java.util.Map;
75 import java.util.Set;
76
77 import static com.atlassian.jira.rest.client.api.domain.EntityHelper.findEntityByName;
78 import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_5;
79 import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_6;
80 import static com.google.common.collect.Iterables.toArray;
81 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
82 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
83 import static org.hamcrest.core.IsCollectionContaining.hasItems;
84 import static org.junit.Assert.assertEquals;
85 import static org.junit.Assert.assertFalse;
86 import static org.junit.Assert.assertNotNull;
87 import static org.junit.Assert.assertThat;
88 import static org.junit.Assert.assertTrue;
89 import static org.junit.Assert.fail;
90
91
92 @SuppressWarnings("ConstantConditions")
93
94 public class AsynchronousIssueRestClientCreateIssueTest extends AbstractAsynchronousRestClientTest {
95
96 @Rule
97 public ExpectedException thrown = ExpectedException.none();
98
99 private static boolean alreadyRestored;
100
101 @Before
102 public void setup() {
103 if (!alreadyRestored) {
104 IntegrationTestUtil.restoreAppropriateJiraData(TestConstants.JIRA_DUMP_CREATING_ISSUE_TESTS_FILE, administration);
105 alreadyRestored = true;
106 }
107 }
108
109 @JiraBuildNumberDependent(BN_JIRA_5)
110 @Test
111 public void testCreateIssue() throws JSONException {
112
113 final IssueRestClient issueClient = client.getIssueClient();
114 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
115 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
116
117
118 assertEquals(1, Iterables.size(metadataProjects));
119 final CimProject project = metadataProjects.iterator().next();
120 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Bug");
121
122
123 final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
124 assertNotNull(allowedValuesForComponents);
125 assertTrue(allowedValuesForComponents.iterator().hasNext());
126 final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
127
128
129 final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
130 assertNotNull(allowedValuesForPriority);
131 assertTrue(allowedValuesForPriority.iterator().hasNext());
132 final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
133
134
135 final String summary = "My new issue!";
136 final String description = "Some description";
137 final BasicUser assignee = IntegrationTestUtil.USER1;
138 final List<String> affectedVersionsNames = Collections.emptyList();
139 final DateTime dueDate = new DateTime(new Date().getTime());
140 final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
141
142
143 final String multiUserCustomFieldId = "customfield_10031";
144 final ImmutableList<BasicUser> multiUserCustomFieldValues = ImmutableList.of(IntegrationTestUtil.USER1, IntegrationTestUtil.USER2);
145 final IssueInputBuilder issueInputBuilder = new IssueInputBuilder(project, issueType, summary)
146 .setDescription(description)
147 .setAssignee(assignee)
148 .setAffectedVersionsNames(affectedVersionsNames)
149 .setFixVersionsNames(fixVersionsNames)
150 .setComponents(component)
151 .setDueDate(dueDate)
152 .setPriority(priority)
153 .setFieldValue(multiUserCustomFieldId, multiUserCustomFieldValues);
154
155
156 final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInputBuilder.build()).claim();
157 assertNotNull(basicCreatedIssue.getKey());
158
159
160 final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey()).claim();
161 assertNotNull(createdIssue);
162
163 assertEquals(basicCreatedIssue.getKey(), createdIssue.getKey());
164 assertEquals(project.getKey(), createdIssue.getProject().getKey());
165 assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
166 assertEquals(summary, createdIssue.getSummary());
167 assertEquals(description, createdIssue.getDescription());
168
169 final User actualAssignee = createdIssue.getAssignee();
170 assertNotNull(actualAssignee);
171 assertEquals(assignee.getSelf(), actualAssignee.getSelf());
172
173 assertEquals(actualAssignee.getEmailAddress(), "wojciech.seliga@spartez.com");
174
175 final Iterable<String> actualAffectedVersionsNames = EntityHelper.toNamesList(createdIssue.getAffectedVersions());
176 assertThat(affectedVersionsNames, containsInAnyOrder(toArray(actualAffectedVersionsNames, String.class)));
177
178 final Iterable<String> actualFixVersionsNames = EntityHelper.toNamesList(createdIssue.getFixVersions());
179 assertThat(fixVersionsNames, containsInAnyOrder(toArray(actualFixVersionsNames, String.class)));
180
181 assertTrue(createdIssue.getComponents().iterator().hasNext());
182 assertEquals(component.getId(), createdIssue.getComponents().iterator().next().getId());
183
184
185 final DateTime expectedDueDate = JsonParseUtil.parseDate(JsonParseUtil.formatDate(dueDate));
186 assertEquals(expectedDueDate, createdIssue.getDueDate());
187
188 final BasicPriority actualPriority = createdIssue.getPriority();
189 assertNotNull(actualPriority);
190 assertEquals(priority.getId(), actualPriority.getId());
191
192
193 final Object multiUserValue = createdIssue.getField(multiUserCustomFieldId).getValue();
194
195 assertThat(multiUserValue, Matchers.instanceOf(JSONArray.class));
196 final JSONArray multiUserArray = (JSONArray) multiUserValue;
197 final List<String> actualMultiUserNames = Lists.newArrayListWithCapacity(multiUserArray.length());
198 for (int i = 0; i < multiUserArray.length(); i++) {
199 final JSONObject jsonUser = (JSONObject) multiUserArray.get(i);
200 actualMultiUserNames.add((String) jsonUser.get("name"));
201 }
202 assertThat(actualMultiUserNames, containsInAnyOrder(
203 toArray(EntityHelper.toNamesList(multiUserCustomFieldValues), String.class)));
204 }
205
206 @JiraBuildNumberDependent(BN_JIRA_5)
207 @Test
208 public void testCreateSubtask() {
209
210 final IssueRestClient issueClient = client.getIssueClient();
211 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
212 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
213
214
215 assertEquals(1, Iterables.size(metadataProjects));
216 final CimProject project = metadataProjects.iterator().next();
217 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Sub-task");
218
219
220 final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
221 assertNotNull(allowedValuesForComponents);
222 assertTrue(allowedValuesForComponents.iterator().hasNext());
223 final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
224
225
226 final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
227 assertNotNull(allowedValuesForPriority);
228 assertTrue(allowedValuesForPriority.iterator().hasNext());
229 final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
230
231
232 final String summary = "My first substask!";
233 final String description = "Some description for substask";
234 final BasicUser assignee = IntegrationTestUtil.USER1;
235 final List<String> affectedVersionsNames = Collections.emptyList();
236 final DateTime dueDate = new DateTime(new Date().getTime());
237 final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
238
239
240 final IssueInputBuilder issueInputBuilder = new IssueInputBuilder(project, issueType, summary)
241 .setDescription(description)
242 .setAssignee(assignee)
243 .setAffectedVersionsNames(affectedVersionsNames)
244 .setFixVersionsNames(fixVersionsNames)
245 .setComponents(component)
246 .setDueDate(dueDate)
247 .setPriority(priority)
248 .setFieldValue("parent", ComplexIssueInputFieldValue.with("key", "TST-1"));
249
250
251 final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInputBuilder.build()).claim();
252 assertNotNull(basicCreatedIssue.getKey());
253
254
255 final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey()).claim();
256 assertNotNull(createdIssue);
257
258 assertEquals(basicCreatedIssue.getKey(), createdIssue.getKey());
259 assertEquals(project.getKey(), createdIssue.getProject().getKey());
260 assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
261 assertEquals(summary, createdIssue.getSummary());
262 assertEquals(description, createdIssue.getDescription());
263
264 final BasicUser actualAssignee = createdIssue.getAssignee();
265 assertNotNull(actualAssignee);
266 assertEquals(assignee.getSelf(), actualAssignee.getSelf());
267
268 final Iterable<String> actualAffectedVersionsNames = EntityHelper.toNamesList(createdIssue.getAffectedVersions());
269 assertThat(affectedVersionsNames, containsInAnyOrder(toArray(actualAffectedVersionsNames, String.class)));
270
271 final Iterable<String> actualFixVersionsNames = EntityHelper.toNamesList(createdIssue.getFixVersions());
272 assertThat(fixVersionsNames, containsInAnyOrder(toArray(actualFixVersionsNames, String.class)));
273
274 assertTrue(createdIssue.getComponents().iterator().hasNext());
275 assertEquals(component.getId(), createdIssue.getComponents().iterator().next().getId());
276
277
278 final DateTime expectedDueDate = JsonParseUtil.parseDate(JsonParseUtil.formatDate(dueDate));
279 assertEquals(expectedDueDate, createdIssue.getDueDate());
280
281 final BasicPriority actualPriority = createdIssue.getPriority();
282 assertNotNull(actualPriority);
283 assertEquals(priority.getId(), actualPriority.getId());
284 }
285
286 @JiraBuildNumberDependent(value = BN_JIRA_6)
287 @Test
288 public void testCreateManySubtasksInGivenOrder() throws NoSuchFieldException, IllegalAccessException {
289
290 final IssueRestClient issueClient = client.getIssueClient();
291 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
292 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
293
294
295 assertEquals(1, Iterables.size(metadataProjects));
296 final CimProject project = metadataProjects.iterator().next();
297 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Sub-task");
298
299
300 final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
301 assertNotNull(allowedValuesForComponents);
302 assertTrue(allowedValuesForComponents.iterator().hasNext());
303 final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
304
305
306 final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
307 assertNotNull(allowedValuesForPriority);
308 assertTrue(allowedValuesForPriority.iterator().hasNext());
309 final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
310
311
312 final String description = "Some description for substask";
313 final BasicUser assignee = IntegrationTestUtil.USER1;
314 final List<String> affectedVersionsNames = Collections.emptyList();
315 final DateTime dueDate = new DateTime(new Date().getTime());
316 final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
317
318 final Set<String> summaries = ImmutableSet.of("Summary 1", "Summary 2", "Summary 3", "Summary 4", "Summary 5");
319
320
321 final List<IssueInput> issuesToCreate = Lists.newArrayList();
322 for (final String summary : summaries) {
323
324 final IssueInputBuilder issueInputBuilder =
325 new IssueInputBuilder(project, issueType, summary)
326 .setDescription(description)
327 .setAssignee(assignee)
328 .setAffectedVersionsNames(affectedVersionsNames)
329 .setFixVersionsNames(fixVersionsNames)
330 .setComponents(component)
331 .setDueDate(dueDate)
332 .setPriority(priority)
333 .setFieldValue("parent", ComplexIssueInputFieldValue.with("key", "TST-1"));
334
335 issuesToCreate.add(issueInputBuilder.build());
336 }
337 assertEquals(summaries.size(), issuesToCreate.size());
338
339
340 final BulkOperationResult<BasicIssue> createdIssues = issueClient.createIssues(issuesToCreate).claim();
341 assertEquals(summaries.size(), Iterables.size(createdIssues.getIssues()));
342 assertEquals(0, Iterables.size(createdIssues.getErrors()));
343
344
345 final Set<String> createdSummariesOrder = ImmutableSet.copyOf(Iterables.transform(createdIssues
346 .getIssues(), new Function<BasicIssue, String>() {
347 @Override
348 public String apply(final BasicIssue basicIssue) {
349 return issueClient.getIssue(basicIssue.getKey()).claim().getSummary();
350 }
351 }));
352
353 assertEquals(summaries, createdSummariesOrder);
354
355 final Issue parentIssue = issueClient.getIssue("TST-1").claim();
356 final Set<String> subtaskKeys = ImmutableSet.copyOf(Iterables.transform(parentIssue
357 .getSubtasks(), new Function<Subtask, String>() {
358 @Override
359 public String apply(final Subtask subtask) {
360 return subtask.getIssueKey();
361 }
362 }));
363
364 for (final BasicIssue basicIssue : createdIssues.getIssues()) {
365
366
367 final Issue createdIssue = issueClient.getIssue(basicIssue.getKey()).claim();
368 assertNotNull(createdIssue);
369
370 assertEquals(basicIssue.getKey(), createdIssue.getKey());
371 assertEquals(project.getKey(), createdIssue.getProject().getKey());
372 assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
373 assertTrue(summaries.contains(createdIssue.getSummary()));
374 assertEquals(description, createdIssue.getDescription());
375
376 final BasicUser actualAssignee = createdIssue.getAssignee();
377 assertNotNull(actualAssignee);
378 assertEquals(assignee.getSelf(), actualAssignee.getSelf());
379
380 assertTrue(subtaskKeys.contains(createdIssue.getKey()));
381 }
382 }
383
384
385 @JiraBuildNumberDependent(value = BN_JIRA_6)
386 @Test
387 public void testCreateManySubtasksInGivenOrderWithSomeFailing() throws NoSuchFieldException, IllegalAccessException {
388
389 final IssueRestClient issueClient = client.getIssueClient();
390 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
391 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
392
393
394 assertEquals(1, Iterables.size(metadataProjects));
395 final CimProject project = metadataProjects.iterator().next();
396 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Sub-task");
397
398
399 final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
400 assertNotNull(allowedValuesForComponents);
401 assertTrue(allowedValuesForComponents.iterator().hasNext());
402 final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
403
404
405 final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
406 assertNotNull(allowedValuesForPriority);
407 assertTrue(allowedValuesForPriority.iterator().hasNext());
408 final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
409
410
411 final String description = "Some description for substask";
412 final BasicUser assignee = IntegrationTestUtil.USER1;
413 final List<String> affectedVersionsNames = Collections.emptyList();
414 final DateTime dueDate = new DateTime(new Date().getTime());
415 final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
416
417
418 final Set<String> summaries = ImmutableSet.of("Summary 1", "Summary 2", "Summary 3", "Summary 4", "Summary 5");
419 final Set<String> summariesWithError = ImmutableSet.of("Summary 1", "Summary 4");
420 final Set<String> expectedSummariesOrder = Sets.difference(summaries, summariesWithError);
421
422 final int issuecToCreateCount = summaries.size() - summariesWithError.size();
423 final int issuesInErrorCount = summariesWithError.size();
424
425 final List<IssueInput> issuesToCreate = Lists.newArrayList();
426
427 for (final String summary : summaries) {
428 String currentProjectKey = project.getKey();
429
430 if (summariesWithError.contains(summary)) {
431 currentProjectKey = "FAKE_KEY";
432 }
433
434 final IssueInputBuilder issueInputBuilder =
435 new IssueInputBuilder(currentProjectKey, issueType.getId(), summary)
436 .setDescription(description)
437 .setAssignee(assignee)
438 .setAffectedVersionsNames(affectedVersionsNames)
439 .setFixVersionsNames(fixVersionsNames)
440 .setComponents(component)
441 .setDueDate(dueDate)
442 .setPriority(priority)
443 .setFieldValue("parent", ComplexIssueInputFieldValue.with("key", "TST-1"));
444
445 issuesToCreate.add(issueInputBuilder.build());
446 }
447 assertEquals(summaries.size(), issuesToCreate.size());
448
449
450 final BulkOperationResult<BasicIssue> createdIssues = issueClient.createIssues(issuesToCreate).claim();
451 assertEquals(issuecToCreateCount, Iterables.size(createdIssues.getIssues()));
452 assertEquals(issuesInErrorCount, Iterables.size(createdIssues.getErrors()));
453
454
455 final Set<String> createdSummariesOrder = ImmutableSet.copyOf(Iterables.transform(createdIssues
456 .getIssues(), new Function<BasicIssue, String>() {
457 @Override
458 public String apply(final BasicIssue basicIssue) {
459 return issueClient.getIssue(basicIssue.getKey()).claim().getSummary();
460 }
461 }));
462
463 assertEquals(expectedSummariesOrder, createdSummariesOrder);
464
465 final Issue parentIssue = issueClient.getIssue("TST-1").claim();
466 final Set<String> subtaskKeys = ImmutableSet.copyOf(Iterables.transform(parentIssue
467 .getSubtasks(), new Function<Subtask, String>() {
468 @Override
469 public String apply(Subtask subtask) {
470 return subtask.getIssueKey();
471 }
472 }));
473
474 for (final BasicIssue basicIssue : createdIssues.getIssues()) {
475
476
477 final Issue createdIssue = issueClient.getIssue(basicIssue.getKey()).claim();
478 assertNotNull(createdIssue);
479
480 assertEquals(basicIssue.getKey(), createdIssue.getKey());
481 assertEquals(project.getKey(), createdIssue.getProject().getKey());
482 assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
483 assertEquals(description, createdIssue.getDescription());
484
485 final BasicUser actualAssignee = createdIssue.getAssignee();
486 assertNotNull(actualAssignee);
487 assertEquals(assignee.getSelf(), actualAssignee.getSelf());
488
489 assertTrue(summaries.contains(createdIssue.getSummary()));
490 assertFalse(summariesWithError.contains(createdIssue.getSummary()));
491
492 assertTrue(subtaskKeys.contains(createdIssue.getKey()));
493 }
494 }
495
496 @JiraBuildNumberDependent(value = BN_JIRA_6)
497 @Test
498 public void testCreateManySubtasksInGivenOrderWithAllFailing() throws NoSuchFieldException, IllegalAccessException {
499
500 final IssueRestClient issueClient = client.getIssueClient();
501 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
502 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
503
504
505 assertEquals(1, Iterables.size(metadataProjects));
506 final CimProject project = metadataProjects.iterator().next();
507 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Sub-task");
508
509
510 final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
511 assertNotNull(allowedValuesForComponents);
512 assertTrue(allowedValuesForComponents.iterator().hasNext());
513 final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
514
515
516 final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
517 assertNotNull(allowedValuesForPriority);
518 assertTrue(allowedValuesForPriority.iterator().hasNext());
519 final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
520
521
522 final String description = "Some description for substask";
523 final BasicUser assignee = IntegrationTestUtil.USER1;
524 final List<String> affectedVersionsNames = Collections.emptyList();
525 final DateTime dueDate = new DateTime(new Date().getTime());
526 final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
527
528 final Set<String> summaries = ImmutableSet.of("Summary 1", "Summary 2", "Summary 3", "Summary 4", "Summary 5");
529 final Set<String> summariesWithError = ImmutableSet.of("Summary 1", "Summary 2", "Summary 3", "Summary 4", "Summary 5");
530
531 final int issuesInErrorCount = summariesWithError.size();
532
533 final List<IssueInput> issuesToCreate = Lists.newArrayList();
534
535 for (final String summary : summaries) {
536 String currentProjectKey = project.getKey();
537
538 if (summariesWithError.contains(summary)) {
539 currentProjectKey = "FAKE_KEY";
540 }
541
542 final IssueInputBuilder issueInputBuilder =
543 new IssueInputBuilder(currentProjectKey, issueType.getId(), summary)
544 .setDescription(description)
545 .setAssignee(assignee)
546 .setAffectedVersionsNames(affectedVersionsNames)
547 .setFixVersionsNames(fixVersionsNames)
548 .setComponents(component)
549 .setDueDate(dueDate)
550 .setPriority(priority)
551 .setFieldValue("parent", ComplexIssueInputFieldValue.with("key", "TST-1"));
552
553 issuesToCreate.add(issueInputBuilder.build());
554 }
555 assertEquals(summaries.size(), issuesToCreate.size());
556
557
558 try {
559 issueClient.createIssues(issuesToCreate).claim();
560 } catch (RestClientException ex) {
561 assertEquals(issuesInErrorCount, ex.getErrorCollections().size());
562 for (final ErrorCollection errorCollection : ex.getErrorCollections()) {
563 assertTrue("Unexpected error messages", errorCollection.getErrorMessages().isEmpty());
564 final String message = errorCollection.getErrors().get("project");
565 assertEquals("project is required", message);
566 }
567 }
568 }
569
570 @JiraBuildNumberDependent(BN_JIRA_5)
571 @Test
572 public void testCreateIssueWithOnlyRequiredFields() {
573
574 final IssueRestClient issueClient = client.getIssueClient();
575 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
576 new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build()).claim();
577
578
579 assertEquals(1, Iterables.size(metadataProjects));
580 final CimProject project = metadataProjects.iterator().next();
581 final CimIssueType issueType = findEntityByName(project.getIssueTypes(), "Bug");
582
583
584 final String summary = "My new issue!";
585
586
587 final IssueInput issueInput = new IssueInputBuilder(project, issueType, summary).build();
588 final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInput).claim();
589 assertNotNull(basicCreatedIssue.getKey());
590
591
592 final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey()).claim();
593 assertNotNull(createdIssue);
594
595 assertEquals(basicCreatedIssue.getKey(), createdIssue.getKey());
596 assertEquals(project.getKey(), createdIssue.getProject().getKey());
597 assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
598 assertEquals(summary, createdIssue.getSummary());
599 }
600
601 @JiraBuildNumberDependent(BN_JIRA_5)
602 @Test
603 public void testCreateIssueWithoutSummary() {
604 final IssueRestClient issueClient = client.getIssueClient();
605
606 thrown.expect(RestClientException.class);
607 thrown.expectMessage("You must specify a summary of the issue.");
608
609 final IssueInput issueInput = new IssueInputBuilder("TST", 1L).build();
610 issueClient.createIssue(issueInput).claim();
611 }
612
613 @JiraBuildNumberDependent(BN_JIRA_5)
614 @Test
615 public void testCreateIssueWithNotExistentProject() {
616 final IssueRestClient issueClient = client.getIssueClient();
617
618 thrown.expect(RestClientException.class);
619 thrown.expectMessage("project is required");
620
621 final IssueInput issueInput = new IssueInputBuilder("BAD", 1L, "Should fail").build();
622 issueClient.createIssue(issueInput).claim();
623 }
624
625 @JiraBuildNumberDependent(BN_JIRA_5)
626 @Test
627 public void testCreateIssueWithNotExistentIssueType() {
628 final IssueRestClient issueClient = client.getIssueClient();
629
630 thrown.expect(RestClientException.class);
631 thrown.expectMessage("valid issue type is required");
632
633 final IssueInput issueInput = new IssueInputBuilder("TST", 666L, "Should fail").build();
634 issueClient.createIssue(issueInput).claim();
635 }
636
637
638 @JiraBuildNumberDependent(BN_JIRA_5)
639 @Test
640 public void testCreateIssueWithoutProject() {
641 final IssueRestClient issueClient = client.getIssueClient();
642
643 thrown.expect(RestClientException.class);
644 thrown.expectMessage("project is required");
645
646 final IssueInput issueInput = new IssueInput(ImmutableMap.of(
647 "summary", new FieldInput("summary", "Summary"),
648 "issuetype", new FieldInput("issuetype", ComplexIssueInputFieldValue.with("id", "1"))
649 ), ImmutableList.of(new PropertyInput("testKey", "{\"testValue\" : \"foo\"}")));
650 issueClient.createIssue(issueInput).claim();
651 }
652
653 @JiraBuildNumberDependent(BN_JIRA_5)
654 @Test
655 public void testCreateIssueWithInvalidAdditionalField() {
656 final IssueRestClient issueClient = client.getIssueClient();
657 final String fieldId = "invalidField";
658
659 thrown.expect(RestClientException.class);
660 thrown.expectMessage(String
661 .format("Field '%s' cannot be set. It is not on the appropriate screen, or unknown.", fieldId));
662
663 final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Should fail")
664 .setFieldValue(fieldId, "test")
665 .build();
666 issueClient.createIssue(issueInput).claim();
667 }
668
669 @JiraBuildNumberDependent(BN_JIRA_5)
670 @Test
671 public void testCreateIssueWithFieldValueThatIsNotAllowed() {
672 final IssueRestClient issueClient = client.getIssueClient();
673 final BasicPriority invalidPriority = new BasicPriority(null, 666L, "Invalid Priority");
674
675 thrown.expect(RestClientException.class);
676 thrown.expectMessage(String
677 .format("Invalid value '%s' passed for customfield 'My Radio buttons'. Allowed values are: 10000[abc], 10001[Another], 10002[The last option], -1", invalidPriority
678 .getId()));
679
680 final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Should fail")
681 .setFieldValue("customfield_10001", invalidPriority)
682 .build();
683 issueClient.createIssue(issueInput).claim();
684 }
685
686 @JiraBuildNumberDependent(BN_JIRA_5)
687 @Test
688 public void testCreateIssueAsAnonymous() {
689 setAnonymousMode();
690
691 final IssueRestClient issueClient = client.getIssueClient();
692
693 final IssueInput issueInput = new IssueInputBuilder("ANONEDIT", 1L, "Anonymously created issue").build();
694 final BasicIssue createdIssue = issueClient.createIssue(issueInput).claim();
695
696 assertNotNull(createdIssue);
697 assertNotNull(createdIssue.getKey());
698 }
699
700 @JiraBuildNumberDependent(BN_JIRA_5)
701 @Test
702 public void testCreateIssueAsAnonymousWhenNotAllowed() {
703 setAnonymousMode();
704 final IssueRestClient issueClient = client.getIssueClient();
705
706 thrown.expect(RestClientException.class);
707 thrown.expectMessage("Anonymous users do not have permission to create issues in this project. Please try logging in first.");
708
709
710 final IssueInput issueInput = new IssueInputBuilder("TST", 1L
711 .build();
712 issueClient.createIssue(issueInput).claim();
713 }
714
715 @JiraBuildNumberDependent(BN_JIRA_5)
716 @Test
717 public void testJiradev13412BugNotFixedIfThisFailsThenCorrectAffectedTests() {
718
719
720
721
722
723
724
725 setAnonymousMode();
726 final IssueRestClient issueClient = client.getIssueClient();
727
728 thrown.expect(RestClientException.class);
729 thrown.expectMessage("Field 'summary' cannot be set. It is not on the appropriate screen, or unknown.");
730
731 final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Sample summary").build();
732 issueClient.createIssue(issueInput).claim();
733 }
734
735 @JiraBuildNumberDependent(BN_JIRA_5)
736 @Test
737 public void testCreateIssueWithAssigneeWhenNotAllowedToAssignIssue() {
738 setUser2();
739 final IssueRestClient issueClient = client.getIssueClient();
740
741 thrown.expect(RestClientException.class);
742 thrown.expectMessage("Field 'assignee' cannot be set. It is not on the appropriate screen, or unknown.");
743
744 final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Issue created by testCreateIssueWithAssigneeWhenNotAllowedToAssignIssue")
745 .setAssignee(IntegrationTestUtil.USER_ADMIN)
746 .build();
747 issueClient.createIssue(issueInput).claim();
748 }
749
750 @JiraBuildNumberDependent(BN_JIRA_5)
751 @Test
752 public void testCreateIssueWithoutCreateIssuePermission() {
753 setUser1();
754 final IssueRestClient issueClient = client.getIssueClient();
755
756 thrown.expect(RestClientException.class);
757 thrown.expectMessage("You do not have permission to create issues in this project.");
758
759
760 final IssueInput issueInput = new IssueInputBuilder("NCIFU", 1L
761 .build();
762 issueClient.createIssue(issueInput).claim();
763 }
764
765
766 @JiraBuildNumberDependent(BN_JIRA_5)
767 @Test
768 public void testCreateIssueWithoutBrowseProjectPermission() {
769 setUser1();
770 final IssueRestClient issueClient = client.getIssueClient();
771
772 thrown.expect(RestClientException.class);
773 thrown.expectMessage("You do not have permission to create issues in this project.");
774
775
776 final IssueInput issueInput = new IssueInputBuilder("RST", 1L
777 .build();
778 issueClient.createIssue(issueInput).claim();
779 }
780
781 @JiraBuildNumberDependent(BN_JIRA_6)
782 @Test
783 public void testCreateMetaShouldReturnIssueTypeInFieldsListEvenIfIssueTypeIsNotOnCreateIssueScreen() {
784 final IssueRestClient issueClient = client.getIssueClient();
785 final Iterable<CimProject> cimProjects = issueClient.getCreateIssueMetadata(
786 new GetCreateIssueMetadataOptionsBuilder().withExpandedIssueTypesFields().build()).claim();
787
788 final CimProject testProject = findEntityByName(cimProjects, "Project With Create Issue Screen Without Issue Type");
789 assertThat(testProject.getIssueTypes(), IsIterableWithSize.<CimIssueType>iterableWithSize(greaterThanOrEqualTo(5)));
790 for (CimIssueType cimIssueType : testProject.getIssueTypes()) {
791 final CimFieldInfo issueType = cimIssueType.getField(IssueFieldId.ISSUE_TYPE_FIELD);
792 final String assertMessageIssueTypeNotPresent = String.format(
793 "Issue type is missing for project %s (%s) and issue type %s (%s)!",
794 testProject.getName(), testProject.getKey(), cimIssueType.getName(), cimIssueType.getId());
795 assertNotNull(assertMessageIssueTypeNotPresent, issueType);
796
797
798 final Iterable<Object> allowedValues = issueType.getAllowedValues();
799 final String assertMessageAllowedValuesSizeNotMatch = String.format(
800 "We expected exactly one allowed value - the issue type %s (%s) for project %s (%s)",
801 testProject.getName(), testProject.getKey(), cimIssueType.getName(), cimIssueType.getId());
802 assertEquals(assertMessageAllowedValuesSizeNotMatch, 1, Iterables.size(allowedValues));
803
804
805 final IssueType firstAllowedValue = (IssueType) Iterables.getOnlyElement(allowedValues);
806 assertEquals(firstAllowedValue.getId(), cimIssueType.getId());
807 }
808 }
809
810 @JiraBuildNumberDependent(BN_JIRA_5)
811 @Test
812 public void interactiveUseCase() throws CannotTransformValueException {
813 final IssueRestClient issueClient = client.getIssueClient();
814
815
816 final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
817 new GetCreateIssueMetadataOptionsBuilder().withExpandedIssueTypesFields().build()).claim();
818 log.log("Available projects: ");
819 for (CimProject p : metadataProjects) {
820 log.log(MessageFormat.format("\t* [{0}] {1}", p.getKey(), p.getName()));
821 }
822 log.log("");
823 assertTrue("There is no project to select!", metadataProjects.iterator().hasNext());
824
825
826 final CimProject project = metadataProjects.iterator().next();
827 log.log(MessageFormat.format("Selected project: [{0}] {1}\n", project.getKey(), project.getName()));
828
829
830 log.log("Available issue types for selected project:");
831 for (CimIssueType t : project.getIssueTypes()) {
832 log.log(MessageFormat.format("\t* [{0}] {1}", t.getId(), t.getName()));
833 }
834 log.log("");
835
836 final CimIssueType issueType = project.getIssueTypes().iterator().next();
837 log.log(MessageFormat.format("Selected issue type: [{0}] {1}\n", issueType.getId(), issueType.getName()));
838
839 final IssueInputBuilder builder = new IssueInputBuilder(project.getKey(), issueType.getId());
840
841
842 log.log("Filling fields:");
843 for (Map.Entry<String, CimFieldInfo> entry : issueType.getFields().entrySet()) {
844 final CimFieldInfo fieldInfo = entry.getValue();
845 final String fieldCustomType = fieldInfo.getSchema().getCustom();
846 final String fieldType = fieldInfo.getSchema().getType();
847 final String fieldId = fieldInfo.getId();
848
849 if ("project".equals(fieldId) || "issuetype".equals(fieldId)) {
850
851 continue;
852 }
853
854 log.log(MessageFormat.format("\t* [{0}] {1}\n\t\t| schema: {2}\n\t\t| required: {3}", fieldId, fieldInfo
855 .getName(), fieldInfo.getSchema(), fieldInfo.isRequired()));
856
857
858 Object value = null;
859 final Iterable<Object> allowedValues = fieldInfo.getAllowedValues();
860 if (allowedValues != null) {
861 log.log("\t\t| field only accepts those values:");
862 for (Object val : allowedValues) {
863 log.log("\t\t\t* " + val);
864 }
865 if (allowedValues.iterator().hasNext()) {
866 final boolean expectedArray = "array".equals(fieldType);
867 Object singleValue = allowedValues.iterator().next();
868
869 if ("com.atlassian.jira.plugin.system.customfieldtypes:cascadingselect".equals(fieldCustomType)) {
870
871 final Iterable<Object> optionsWithChildren = Iterables.filter(allowedValues, new Predicate<Object>() {
872 @Override
873 public boolean apply(Object input) {
874 return ((CustomFieldOption) input).getChildren().iterator().hasNext();
875 }
876 });
877
878 if (optionsWithChildren.iterator().hasNext()) {
879
880 final CustomFieldOption option = (CustomFieldOption) optionsWithChildren.iterator().next();
881 value = new CustomFieldOption(option.getId(), option.getSelf(), option.getValue(),
882 Collections.<CustomFieldOption>emptyList(), option.getChildren().iterator().next());
883 } else {
884
885 value = allowedValues.iterator().next();
886 }
887 } else {
888 value = expectedArray ? Collections.singletonList(singleValue) : singleValue;
889 }
890 log.log("\t\t| selecting value: " + value);
891 } else {
892 log.log("\t\t| there is no allowed value - leaving field blank");
893 }
894 } else {
895 if ("com.atlassian.jirafisheyeplugin:jobcheckbox".equals(fieldCustomType)) {
896 value = "false";
897 } else if ("com.atlassian.jira.plugin.system.customfieldtypes:url".equals(fieldCustomType)) {
898 value = "http://www.atlassian.com/";
899 } else if ("string".equals(fieldType)) {
900 value = "This is simple string value for field " + fieldId + " named " + fieldInfo.getName() + ".";
901 } else if ("number".equals(fieldType)) {
902 value = 124;
903 } else if ("user".equals(fieldType)) {
904 value = IntegrationTestUtil.USER_ADMIN;
905 } else if ("array".equals(fieldType) && "user".equals(fieldInfo.getSchema().getItems())) {
906 value = ImmutableList.of(IntegrationTestUtil.USER_ADMIN);
907 } else if ("group".equals(fieldType)) {
908
909 value = ComplexIssueInputFieldValue.with("name", IntegrationTestUtil.GROUP_JIRA_ADMINISTRATORS);
910 } else if ("array".equals(fieldType) && "group".equals(fieldInfo.getSchema().getItems())) {
911
912 value = ImmutableList.of(ComplexIssueInputFieldValue.with("name", IntegrationTestUtil.GROUP_JIRA_ADMINISTRATORS));
913 } else if ("date".equals(fieldType)) {
914 value = JsonParseUtil.formatDate(new DateTime());
915 } else if ("datetime".equals(fieldType)) {
916 value = JsonParseUtil.formatDateTime(new DateTime());
917 } else if ("array".equals(fieldType) && "string".equals(fieldInfo.getSchema().getItems())) {
918 value = ImmutableList.of("one", "two", "three");
919 } else if ("timetracking".equals(fieldType)) {
920 value = new TimeTracking(60, 40, null);
921 } else {
922 if (fieldInfo.isRequired()) {
923 fail("I don't know how to fill that required field, sorry.");
924 } else {
925 log.log("\t\t| field value is not required, leaving blank");
926 }
927 }
928 }
929 if (value == null) {
930 log.log("\t\t| value is null, skipping filed");
931 } else {
932 log.log(MessageFormat.format("\t\t| setting value => {0}", value));
933 builder.setFieldValue(fieldId, value);
934 }
935 }
936 log.log("");
937
938
939 final IssueInput issueInput = builder.build();
940
941 final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInput).claim();
942 assertNotNull(basicCreatedIssue);
943
944 final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey()).claim();
945 assertNotNull(createdIssue);
946
947 log.log("Created new issue successfully, key: " + basicCreatedIssue.getKey());
948
949
950 IssueInputBuilder actualBuilder = new IssueInputBuilder(createdIssue.getProject(), createdIssue
951 .getIssueType(), createdIssue.getSummary())
952 .setPriority(createdIssue.getPriority())
953 .setReporter(createdIssue.getReporter())
954 .setAssignee(createdIssue.getAssignee())
955 .setDescription(createdIssue.getDescription());
956
957 final Collection<FieldInput> actualValues = actualBuilder.build().getFields().values();
958 final Collection<FieldInput> expectedValues = issueInput.getFields().values();
959
960 assertThat(expectedValues, hasItems(toArray(actualValues, FieldInput.class)));
961 }
962 }