1   /*
2    * Copyright (C) 2012 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package it;
18  
19  import com.atlassian.jira.nimblefunctests.annotation.JiraBuildNumberDependent;
20  import com.atlassian.jira.nimblefunctests.annotation.RestoreOnce;
21  import com.atlassian.jira.rest.client.GetCreateIssueMetadataOptionsBuilder;
22  import com.atlassian.jira.rest.client.IntegrationTestUtil;
23  import com.atlassian.jira.rest.client.IssueRestClient;
24  import com.atlassian.jira.rest.client.RestClientException;
25  import com.atlassian.jira.rest.client.domain.BasicComponent;
26  import com.atlassian.jira.rest.client.domain.BasicIssue;
27  import com.atlassian.jira.rest.client.domain.BasicPriority;
28  import com.atlassian.jira.rest.client.domain.BasicUser;
29  import com.atlassian.jira.rest.client.domain.CimFieldInfo;
30  import com.atlassian.jira.rest.client.domain.CimIssueType;
31  import com.atlassian.jira.rest.client.domain.CimProject;
32  import com.atlassian.jira.rest.client.domain.CustomFieldOption;
33  import com.atlassian.jira.rest.client.domain.EntityHelper;
34  import com.atlassian.jira.rest.client.domain.Issue;
35  import com.atlassian.jira.rest.client.domain.IssueFieldId;
36  import com.atlassian.jira.rest.client.domain.TimeTracking;
37  import com.atlassian.jira.rest.client.domain.input.CannotTransformValueException;
38  import com.atlassian.jira.rest.client.domain.input.ComplexIssueInputFieldValue;
39  import com.atlassian.jira.rest.client.domain.input.FieldInput;
40  import com.atlassian.jira.rest.client.domain.input.IssueInput;
41  import com.atlassian.jira.rest.client.domain.input.IssueInputBuilder;
42  import com.atlassian.jira.rest.client.internal.json.JsonParseUtil;
43  import com.google.common.base.Predicate;
44  import com.google.common.collect.ImmutableList;
45  import com.google.common.collect.ImmutableMap;
46  import com.google.common.collect.Iterables;
47  import com.google.common.collect.Lists;
48  import org.joda.time.DateTime;
49  import org.junit.Rule;
50  import org.junit.Test;
51  import org.junit.rules.ExpectedException;
52  
53  import java.text.MessageFormat;
54  import java.util.ArrayList;
55  import java.util.Collection;
56  import java.util.Collections;
57  import java.util.Date;
58  import java.util.List;
59  import java.util.Map;
60  
61  import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_5;
62  import static com.google.common.collect.Iterables.toArray;
63  import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
64  import static org.hamcrest.core.IsCollectionContaining.hasItems;
65  import static org.junit.Assert.*;
66  
67  // Ignore "May produce NPE" warnings, as we know what we are doing in tests
68  @SuppressWarnings("ConstantConditions")
69  // Restore data only once as we just creates issues here - tests doesn't change any settings and doesn't rely on other issues
70  @RestoreOnce("jira3-export-for-creating-issue-tests.xml")
71  public class JerseyIssueRestClientCreateIssueTest extends AbstractJerseyRestClientTest {
72  
73  	@Rule
74  	public ExpectedException thrown = ExpectedException.none();
75  
76  	@JiraBuildNumberDependent(BN_JIRA_5)
77  	@Test
78  	public void testCreateIssue() {
79  		// collect CreateIssueMetadata for project with key TST
80  		final IssueRestClient issueClient = client.getIssueClient();
81  		final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
82  				new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build(), pm);
83  
84  		// select project and issue
85  		assertEquals(1, Iterables.size(metadataProjects));
86  		final CimProject project = metadataProjects.iterator().next();
87  		final CimIssueType issueType = EntityHelper.findEntityByName(project.getIssueTypes(), "Bug");
88  
89  		// grab the first component
90  		final Iterable<Object> allowedValuesForComponents = issueType.getField(IssueFieldId.COMPONENTS_FIELD).getAllowedValues();
91  		assertNotNull(allowedValuesForComponents);
92  		assertTrue(allowedValuesForComponents.iterator().hasNext());
93  		final BasicComponent component = (BasicComponent) allowedValuesForComponents.iterator().next();
94  
95  		// grab the first priority
96  		final Iterable<Object> allowedValuesForPriority = issueType.getField(IssueFieldId.PRIORITY_FIELD).getAllowedValues();
97  		assertNotNull(allowedValuesForPriority);
98  		assertTrue(allowedValuesForPriority.iterator().hasNext());
99  		final BasicPriority priority = (BasicPriority) allowedValuesForPriority.iterator().next();
100 
101 		// build issue input
102 		final String summary = "My new issue!";
103 		final String description = "Some description";
104 		final BasicUser assignee = IntegrationTestUtil.USER1;
105 		final List<String> affectedVersionsNames = Collections.emptyList();
106 		final DateTime dueDate = new DateTime(new Date().getTime());
107 		final ArrayList<String> fixVersionsNames = Lists.newArrayList("1.1");
108 
109 		// prepare IssueInput
110 		final IssueInputBuilder issueInputBuilder = new IssueInputBuilder(project, issueType, summary)
111 				.setDescription(description)
112 				.setAssignee(assignee)
113 				.setAffectedVersionsNames(affectedVersionsNames)
114 				.setFixVersionsNames(fixVersionsNames)
115 				.setComponents(component)
116 				.setDueDate(dueDate)
117 				.setPriority(priority);
118 
119 		// create
120 		final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInputBuilder.build(), pm);
121 		assertNotNull(basicCreatedIssue.getKey());
122 
123 		// get issue and check if everything was set as we expected
124 		final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey(), pm);
125 		assertNotNull(createdIssue);
126 
127 		assertEquals(basicCreatedIssue.getKey(), createdIssue.getKey());
128 		assertEquals(project.getKey(), createdIssue.getProject().getKey());
129 		assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
130 		assertEquals(summary, createdIssue.getSummary());
131 		assertEquals(description, createdIssue.getDescription());
132 
133 		final BasicUser actualAssignee = createdIssue.getAssignee();
134 		assertNotNull(actualAssignee);
135 		assertEquals(assignee.getSelf(), actualAssignee.getSelf());
136 
137 		final Iterable<String> actualAffectedVersionsNames = EntityHelper.toNamesList(createdIssue.getAffectedVersions());
138 		assertThat(affectedVersionsNames, containsInAnyOrder(toArray(actualAffectedVersionsNames, String.class)));
139 
140 		final Iterable<String> actualFixVersionsNames = EntityHelper.toNamesList(createdIssue.getFixVersions());
141 		assertThat(fixVersionsNames, containsInAnyOrder(toArray(actualFixVersionsNames, String.class)));
142 
143 		assertTrue(createdIssue.getComponents().iterator().hasNext());
144 		assertEquals(component.getId(), createdIssue.getComponents().iterator().next().getId());
145 
146 		// strip time from dueDate
147 		final DateTime expectedDueDate = JsonParseUtil.parseDate(JsonParseUtil.formatDate(dueDate));
148 		assertEquals(expectedDueDate, createdIssue.getDueDate());
149 
150 		final BasicPriority actualPriority = createdIssue.getPriority();
151 		assertNotNull(actualPriority);
152 		assertEquals(priority.getId(), actualPriority.getId());
153 	}
154 
155 	@JiraBuildNumberDependent(BN_JIRA_5)
156 	@Test
157 	public void testCreateIssueWithOnlyRequiredFields() {
158 		// collect CreateIssueMetadata for project with key TST
159 		final IssueRestClient issueClient = client.getIssueClient();
160 		final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
161 				new GetCreateIssueMetadataOptionsBuilder().withProjectKeys("TST").withExpandedIssueTypesFields().build(),
162 				pm
163 		);
164 
165 		// select project and issue
166 		assertEquals(1, Iterables.size(metadataProjects));
167 		final CimProject project = metadataProjects.iterator().next();
168 		final CimIssueType issueType = EntityHelper.findEntityByName(project.getIssueTypes(), "Bug");
169 
170 		// build issue input
171 		final String summary = "My new issue!";
172 
173 		// create
174 		final IssueInput issueInput = new IssueInputBuilder(project, issueType, summary).build();
175 		final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInput, pm);
176 		assertNotNull(basicCreatedIssue.getKey());
177 
178 		// get issue and check if everything was set as we expected
179 		final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey(), pm);
180 		assertNotNull(createdIssue);
181 
182 		assertEquals(basicCreatedIssue.getKey(), createdIssue.getKey());
183 		assertEquals(project.getKey(), createdIssue.getProject().getKey());
184 		assertEquals(issueType.getId(), createdIssue.getIssueType().getId());
185 		assertEquals(summary, createdIssue.getSummary());
186 	}
187 
188 	@JiraBuildNumberDependent(BN_JIRA_5)
189 	@Test
190 	public void testCreateIssueWithoutSummary() {
191 		final IssueRestClient issueClient = client.getIssueClient();
192 
193 		thrown.expect(RestClientException.class);
194 		thrown.expectMessage("You must specify a summary of the issue.");
195 
196 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L).build();
197 		issueClient.createIssue(issueInput, pm);
198 	}
199 
200 	@JiraBuildNumberDependent(BN_JIRA_5)
201 	@Test
202 	public void testCreateIssueWithNotExistentProject() {
203 		final IssueRestClient issueClient = client.getIssueClient();
204 
205 		thrown.expect(RestClientException.class);
206 		thrown.expectMessage("project is required");
207 
208 		final IssueInput issueInput = new IssueInputBuilder("BAD", 1L, "Should fail").build();
209 		issueClient.createIssue(issueInput, pm);
210 	}
211 
212 	@JiraBuildNumberDependent(BN_JIRA_5)
213 	@Test
214 	public void testCreateIssueWithNotExistentIssueType() {
215 		final IssueRestClient issueClient = client.getIssueClient();
216 
217 		thrown.expect(RestClientException.class);
218 		thrown.expectMessage("valid issue type is required");
219 
220 		final IssueInput issueInput = new IssueInputBuilder("TST", 666L, "Should fail").build();
221 		issueClient.createIssue(issueInput, pm);
222 	}
223 
224 
225 	@JiraBuildNumberDependent(BN_JIRA_5)
226 	@Test
227 	public void testCreateIssueWithoutProject() {
228 		final IssueRestClient issueClient = client.getIssueClient();
229 
230 		thrown.expect(RestClientException.class);
231 		thrown.expectMessage("project is required");
232 
233 		final IssueInput issueInput = new IssueInput(ImmutableMap.of(
234 				"summary", new FieldInput("summary", "Summary"),
235 				"issuetype", new FieldInput("issuetype", ComplexIssueInputFieldValue.with("id", "1"))
236 		));
237 		issueClient.createIssue(issueInput, pm);
238 	}
239 
240 	@JiraBuildNumberDependent(BN_JIRA_5)
241 	@Test
242 	public void testCreateIssueWithInvalidAdditionalField() {
243 		final IssueRestClient issueClient = client.getIssueClient();
244 		final String fieldId = "invalidField";
245 
246 		thrown.expect(RestClientException.class);
247 		thrown.expectMessage(String
248 				.format("Field '%s' cannot be set. It is not on the appropriate screen, or unknown.", fieldId));
249 
250 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Should fail")
251 				.setFieldValue(fieldId, "test")
252 				.build();
253 		issueClient.createIssue(issueInput, pm);
254 	}
255 
256 	@JiraBuildNumberDependent(BN_JIRA_5)
257 	@Test
258 	public void testCreateIssueWithFieldValueThatIsNotAllowed() {
259 		final IssueRestClient issueClient = client.getIssueClient();
260 		final BasicPriority invalidPriority = new BasicPriority(null, 666L, "Invalid Priority");
261 
262 		thrown.expect(RestClientException.class);
263 		thrown.expectMessage(String
264 				.format("Invalid value '%s' passed for customfield 'My Radio buttons'. Allowed values are: 10000[abc], 10001[Another], 10002[The last option], -1", invalidPriority
265 						.getId()));
266 
267 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Should fail")
268 				.setFieldValue("customfield_10001", invalidPriority)
269 				.build();
270 		issueClient.createIssue(issueInput, pm);
271 	}
272 
273 	@JiraBuildNumberDependent(BN_JIRA_5)
274 	@Test
275 	public void testCreateIssueAsAnonymous() {
276 		setAnonymousMode();
277 
278 		final IssueRestClient issueClient = client.getIssueClient();
279 
280 		final IssueInput issueInput = new IssueInputBuilder("ANONEDIT", 1L, "Anonymously created issue").build();
281 		final BasicIssue createdIssue = issueClient.createIssue(issueInput, pm);
282 
283 		assertNotNull(createdIssue);
284 		assertNotNull(createdIssue.getKey());
285 	}
286 
287 	@JiraBuildNumberDependent(BN_JIRA_5)
288 	@Test
289 	public void testCreateIssueAsAnonymousWhenNotAllowed() {
290 		setAnonymousMode();
291 		final IssueRestClient issueClient = client.getIssueClient();
292 
293 		thrown.expect(RestClientException.class);
294 		thrown.expectMessage("Anonymous users do not have permission to create issues in this project. Please try logging in first.");
295 
296 		// TODO: add summary when JIRA bug is fixed (JRADEV-13412)
297 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L/*, "Issue created by testCreateIssueAsAnonymousWhenNotAllowed"*/)
298 				.build();
299 		issueClient.createIssue(issueInput, pm);
300 	}
301 
302 	@JiraBuildNumberDependent(BN_JIRA_5)
303 	@Test
304 	public void testJiradev13412BugNotFixedIfThisFailsThenCorrectAffectedTests() {
305 		// This test checks if JRADEV-13412 is fixed.
306 		// TODO: When fixed please correct testCreateIssueAsAnonymousWhenNotAllowed, testCreateIssueWithoutCreateIssuePermission, testCreateIssueWithoutBrowseProjectPermission and remove this test.
307 		//
308 		// We should get something like that when this is fixed:
309 		//    Anonymous users do not have permission to create issues in this project. Please try logging in first.
310 		// instead of:
311 		//    Field 'summary' cannot be set. It is not on the appropriate screen, or unknown.
312 		setAnonymousMode();
313 		final IssueRestClient issueClient = client.getIssueClient();
314 
315 		thrown.expect(RestClientException.class);
316 		thrown.expectMessage("Field 'summary' cannot be set. It is not on the appropriate screen, or unknown.");
317 
318 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Sample summary").build();
319 		issueClient.createIssue(issueInput, pm);
320 	}
321 
322 	@JiraBuildNumberDependent(BN_JIRA_5)
323 	@Test
324 	public void testCreateIssueWithAssigneeWhenNotAllowedToAssignIssue() {
325 		setUser2();
326 		final IssueRestClient issueClient = client.getIssueClient();
327 
328 		thrown.expect(RestClientException.class);
329 		thrown.expectMessage("Field 'assignee' cannot be set. It is not on the appropriate screen, or unknown.");
330 
331 		final IssueInput issueInput = new IssueInputBuilder("TST", 1L, "Issue created by testCreateIssueWithAssigneeWhenNotAllowedToAssignIssue")
332 				.setAssignee(IntegrationTestUtil.USER_ADMIN)
333 				.build();
334 		issueClient.createIssue(issueInput, pm);
335 	}
336 
337 	@JiraBuildNumberDependent(BN_JIRA_5)
338 	@Test
339 	public void testCreateIssueWithoutCreateIssuePermission() {
340 		setUser1();
341 		final IssueRestClient issueClient = client.getIssueClient();
342 
343 		thrown.expect(RestClientException.class);
344 		thrown.expectMessage("You do not have permission to create issues in this project.");
345 
346 		// TODO: add summary when JIRA bug is fixed (JRADEV-13412)
347 		final IssueInput issueInput = new IssueInputBuilder("NCIFU", 1L/*, "Issue created by testCreateIssueWithoutCreateIssuePermission"*/)
348 				.build();
349 		issueClient.createIssue(issueInput, pm);
350 	}
351 
352 
353 	@JiraBuildNumberDependent(BN_JIRA_5)
354 	@Test
355 	public void testCreateIssueWithoutBrowseProjectPermission() {
356 		setUser1();
357 		final IssueRestClient issueClient = client.getIssueClient();
358 
359 		thrown.expect(RestClientException.class);
360 		thrown.expectMessage("You do not have permission to create issues in this project.");
361 
362 		// TODO: add summary when JIRA bug is fixed (JRADEV-13412)
363 		final IssueInput issueInput = new IssueInputBuilder("RST", 1L/*, "Issue created by testCreateIssueWithoutBrowseProjectPermission"*/)
364 				.build();
365 		issueClient.createIssue(issueInput, pm);
366 	}
367 
368 	@JiraBuildNumberDependent(BN_JIRA_5)
369 	@Test
370 	public void interactiveUseCase() throws CannotTransformValueException {
371 		final IssueRestClient issueClient = client.getIssueClient();
372 
373 		// get project list with fields expanded
374 		final Iterable<CimProject> metadataProjects = issueClient.getCreateIssueMetadata(
375 				new GetCreateIssueMetadataOptionsBuilder().withExpandedIssueTypesFields().build(),
376 				pm
377 		);
378 		log.log("Available projects: ");
379 		for (CimProject p : metadataProjects) {
380 			log.log(MessageFormat.format("\t* [{0}] {1}", p.getKey(), p.getName()));
381 		}
382 		log.log("");
383 		assertTrue("There is no project to select!", metadataProjects.iterator().hasNext());
384 
385 		// select project
386 		final CimProject project = metadataProjects.iterator().next();
387 		log.log(MessageFormat.format("Selected project: [{0}] {1}\n", project.getKey(), project.getName()));
388 
389 		// select issue type
390 		log.log("Available issue types for selected project:");
391 		for (CimIssueType t : project.getIssueTypes()) {
392 			log.log(MessageFormat.format("\t* [{0}] {1}", t.getId(), t.getName()));
393 		}
394 		log.log("");
395 
396 		final CimIssueType issueType = project.getIssueTypes().iterator().next();
397 		log.log(MessageFormat.format("Selected issue type: [{0}] {1}\n", issueType.getId(), issueType.getName()));
398 
399 		final IssueInputBuilder builder = new IssueInputBuilder(project.getKey(), issueType.getId());
400 
401 		// fill fields
402 		log.log("Filling fields:");
403 		for (Map.Entry<String, CimFieldInfo> entry : issueType.getFields().entrySet()) {
404 			final CimFieldInfo fieldInfo = entry.getValue();
405 			final String fieldCustomType = fieldInfo.getSchema().getCustom();
406 			final String fieldType = fieldInfo.getSchema().getType();
407 			final String fieldId = fieldInfo.getId();
408 
409 			if ("project".equals(fieldId) || "issuetype".equals(fieldId)) {
410 				// this field was already set by IssueInputBuilder constructor - skip it
411 				continue;
412 			}
413 
414 			log.log(MessageFormat.format("\t* [{0}] {1}\n\t\t| schema: {2}\n\t\t| required: {3}", fieldId, fieldInfo
415 					.getName(), fieldInfo.getSchema(), fieldInfo.isRequired()));
416 
417 			// choose value for this field
418 			Object value = null;
419 			final Iterable<Object> allowedValues = fieldInfo.getAllowedValues();
420 			if (allowedValues != null) {
421 				log.log("\t\t| field only accepts those values:");
422 				for (Object val : allowedValues) {
423 					log.log("\t\t\t* " + val);
424 				}
425 				if (allowedValues.iterator().hasNext()) {
426 					final boolean expectedArray = "array".equals(fieldType);
427 					Object singleValue = allowedValues.iterator().next();
428 
429 					if ("com.atlassian.jira.plugin.system.customfieldtypes:cascadingselect".equals(fieldCustomType)) {
430 						// select option with children - if any
431 						final Iterable<Object> optionsWithChildren = Iterables.filter(allowedValues, new Predicate<Object>() {
432 							@Override
433 							public boolean apply(Object input) {
434 								return ((CustomFieldOption) input).getChildren().iterator().hasNext();
435 							}
436 						});
437 
438 						if (optionsWithChildren.iterator().hasNext()) {
439 							// there is option with children - set it
440 							final CustomFieldOption option = (CustomFieldOption) optionsWithChildren.iterator().next();
441 							value = new CustomFieldOption(option.getId(), option.getSelf(), option.getValue(),
442 								Collections.<CustomFieldOption>emptyList(), option.getChildren().iterator().next());
443 						}
444 						else {
445 							// no sub-values available, set only top level value
446 							value = allowedValues.iterator().next();
447 						}
448 					}
449 					else {
450 						value = expectedArray ? Collections.singletonList(singleValue) : singleValue;	
451 					}
452 					log.log("\t\t| selecting value: " + value);
453 				} else {
454 					log.log("\t\t| there is no allowed value - leaving field blank");
455 				}
456 			} else {
457 				if ("com.atlassian.jirafisheyeplugin:jobcheckbox".equals(fieldCustomType)) {
458 					value = "false";
459 				}
460 				else if ("com.atlassian.jira.plugin.system.customfieldtypes:url".equals(fieldCustomType)) {
461 					value = "http://www.atlassian.com/";
462 				}
463 				else if ("string".equals(fieldType)) {
464 					value = "This is simple string value for field " + fieldId + " named " + fieldInfo.getName() + ".";
465 				} else if ("number".equals(fieldType)) {
466 					value = 124;
467 				} else if ("user".equals(fieldType)) {
468 					value = IntegrationTestUtil.USER_ADMIN;
469 				} else if ("array".equals(fieldType) && "user".equals(fieldInfo.getSchema().getItems())) {
470 					value = ImmutableList.of(IntegrationTestUtil.USER_ADMIN);
471 				} else if ("group".equals(fieldType)) {
472 					// TODO change to group object when implemented
473 					value = ComplexIssueInputFieldValue.with("name", IntegrationTestUtil.GROUP_JIRA_ADMINISTRATORS);
474 				} else if ("array".equals(fieldType) && "group".equals(fieldInfo.getSchema().getItems())) {
475 					// TODO change to group object when implemented
476 					value = ImmutableList.of(ComplexIssueInputFieldValue.with("name", IntegrationTestUtil.GROUP_JIRA_ADMINISTRATORS));
477 				} else if ("date".equals(fieldType)) {
478 					value = JsonParseUtil.formatDate(new DateTime());
479 				} else if ("datetime".equals(fieldType)) {
480 					value = JsonParseUtil.formatDateTime(new DateTime());
481 				} else if ("array".equals(fieldType) && "string".equals(fieldInfo.getSchema().getItems())) {
482 					value = ImmutableList.of("one", "two", "three");
483 				} else if ("timetracking".equals(fieldType)) {
484 					value = new TimeTracking(60, 40, null); // time spent is not allowed
485 				} else {
486 					if (fieldInfo.isRequired()) {
487 						fail("I don't know how to fill that required field, sorry.");
488 					} else {
489 						log.log("\t\t| field value is not required, leaving blank");
490 					}
491 				}
492 			}
493 			if (value == null) {
494 				log.log("\t\t| value is null, skipping filed");
495 			} else {
496 				log.log(MessageFormat.format("\t\t| setting value => {0}", value));
497 				builder.setFieldValue(fieldId, value);
498 			}
499 		}
500 		log.log("");
501 
502 		// all required data is provided, let's create issue
503 		final IssueInput issueInput = builder.build();
504 
505 		final BasicIssue basicCreatedIssue = issueClient.createIssue(issueInput, pm);
506 		assertNotNull(basicCreatedIssue);
507 
508 		final Issue createdIssue = issueClient.getIssue(basicCreatedIssue.getKey(), pm);
509 		assertNotNull(createdIssue);
510 
511 		log.log("Created new issue successfully, key: " + basicCreatedIssue.getKey());
512 
513 		// assert few fields
514 		IssueInputBuilder actualBuilder = new IssueInputBuilder(createdIssue.getProject(), createdIssue
515 				.getIssueType(), createdIssue.getSummary())
516 				.setPriority(createdIssue.getPriority())
517 				.setReporter(createdIssue.getReporter())
518 				.setAssignee(createdIssue.getAssignee())
519 				.setDescription(createdIssue.getDescription());
520 
521 		final Collection<FieldInput> actualValues = actualBuilder.build().getFields().values();
522 		final Collection<FieldInput> expectedValues = issueInput.getFields().values();
523 
524 		assertThat(expectedValues, hasItems(toArray(actualValues, FieldInput.class)));
525 	}
526 }