1   /*
2    * Copyright (C) 2010 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 com.atlassian.jira.rest.client.internal.json;
18  
19  import com.atlassian.jira.rest.client.BasicComponentNameExtractionFunction;
20  import com.atlassian.jira.rest.client.IterableMatcher;
21  import com.atlassian.jira.rest.client.domain.Attachment;
22  import com.atlassian.jira.rest.client.domain.BasicIssueType;
23  import com.atlassian.jira.rest.client.domain.BasicPriority;
24  import com.atlassian.jira.rest.client.domain.BasicProject;
25  import com.atlassian.jira.rest.client.domain.BasicUser;
26  import com.atlassian.jira.rest.client.domain.BasicWatchers;
27  import com.atlassian.jira.rest.client.domain.Comment;
28  import com.atlassian.jira.rest.client.domain.Field;
29  import com.atlassian.jira.rest.client.domain.Issue;
30  import com.atlassian.jira.rest.client.domain.IssueLink;
31  import com.atlassian.jira.rest.client.domain.IssueLinkType;
32  import com.atlassian.jira.rest.client.domain.Subtask;
33  import com.atlassian.jira.rest.client.domain.TimeTracking;
34  import com.atlassian.jira.rest.client.domain.Visibility;
35  import com.atlassian.jira.rest.client.domain.Worklog;
36  import com.google.common.collect.Iterables;
37  import org.codehaus.jettison.json.JSONException;
38  import org.codehaus.jettison.json.JSONObject;
39  import org.junit.Assert;
40  import org.junit.Test;
41  
42  import java.util.Iterator;
43  
44  import static com.atlassian.jira.rest.client.TestUtil.toDateTime;
45  import static com.atlassian.jira.rest.client.TestUtil.toUri;
46  import static org.junit.Assert.*;
47  
48  public class IssueJsonParserTest {
49  	@Test
50  	public void testParseIssue() throws Exception {
51  		final Issue issue = parseIssue("/json/issue/valid-all-expanded.json");
52  		assertExpectedIssue(issue);
53  	}
54  
55  	@Test
56  	public void testParseIssueJira4x2() throws Exception {
57  		final Issue issue = parseIssue("/json/issue/valid-all-expanded-jira-4-2.json");
58  		assertExpectedIssue(issue);
59  	}
60  
61  	private void assertExpectedIssue(Issue issue) {
62  		assertEquals("Testing issue", issue.getSummary());
63  		assertEquals("TST-2", issue.getKey());
64  		assertEquals(new BasicIssueType(toUri("http://localhost:8090/jira/rest/api/latest/issueType/1"), "Bug", false),
65  				issue.getIssueType());
66  		assertEquals(new BasicProject(toUri("http://localhost:8090/jira/rest/api/latest/project/TST"), "TST", null), issue.getProject());
67  		assertEquals("Major", issue.getPriority().getName());
68  		assertNull(issue.getResolution());
69  		assertEquals(toDateTime("2010-07-26T13:29:18.262+0200"), issue.getCreationDate());
70  		assertEquals(toDateTime("2010-08-27T15:00:02.107+0200"), issue.getUpdateDate());
71  
72  		assertEquals(TestConstants.USER_ADMIN, issue.getReporter());
73  		assertEquals(TestConstants.USER1, issue.getAssignee());
74  
75  		// issue links
76  		Assert.assertThat(issue.getIssueLinks(), IterableMatcher.hasOnlyElements(
77  				new IssueLink("TST-1", toUri("http://localhost:8090/jira/rest/api/latest/issue/TST-1"),
78  						new IssueLinkType("Duplicate", "duplicates", IssueLinkType.Direction.OUTBOUND)),
79  				new IssueLink("TST-1", toUri("http://localhost:8090/jira/rest/api/latest/issue/TST-1"),
80  						new IssueLinkType("Duplicate", "is duplicated by", IssueLinkType.Direction.INBOUND))
81  		));
82  
83  
84  		// watchers
85  		final BasicWatchers watchers = issue.getWatchers();
86  		assertFalse(watchers.isWatching());
87  		assertEquals(toUri("http://localhost:8090/jira/rest/api/latest/issue/TST-2/watchers"), watchers.getSelf());
88  		assertEquals(1, watchers.getNumWatchers());
89  		assertEquals(new TimeTracking(0, 0, 145), issue.getTimeTracking());
90  
91  		// attachments
92  		final Iterable<Attachment> attachments = issue.getAttachments();
93  		assertEquals(3, Iterables.size(attachments));
94  		final Attachment attachment = attachments.iterator().next();
95  		assertEquals("jira_logo.gif", attachment.getFilename());
96  		assertEquals(TestConstants.USER_ADMIN, attachment.getAuthor());
97  		assertEquals(2517, attachment.getSize());
98  		assertEquals(toUri("http://localhost:8090/jira/secure/thumbnail/10036/10036_jira_logo.gif"), attachment.getThumbnailUri());
99  		final Iterator<Attachment> attachmentIt = attachments.iterator();
100 		attachmentIt.next();
101 		attachmentIt.next();
102 		final Attachment lastAttachment = attachmentIt.next();
103 		assertEquals("transparent-png.png", lastAttachment.getFilename());
104 
105 		// worklogs
106 		final Iterable<Worklog> worklogs = issue.getWorklogs();
107 		assertEquals(5, Iterables.size(worklogs));
108 		final Worklog worklog = Iterables.get(worklogs, 2);
109 		assertEquals(new Worklog(toUri("http://localhost:8090/jira/rest/api/latest/worklog/10012"),
110 				toUri("http://localhost:8090/jira/rest/api/latest/issue/TST-2"), TestConstants.USER1,
111 				TestConstants.USER1, "a worklog viewable just by jira-users",
112 				toDateTime("2010-08-17T16:53:15.848+0200"), toDateTime("2010-08-17T16:53:15.848+0200"),
113 				toDateTime("2010-08-11T16:52:00.000+0200"), 3, Visibility.group("jira-users")), worklog);
114 
115 		final Worklog worklog3 = Iterables.get(worklogs, 3);
116 		assertEquals("", worklog3.getComment());
117 
118 		// comments
119 		assertEquals(3, Iterables.size(issue.getComments()));
120 		final Comment comment = issue.getComments().iterator().next();
121 		assertEquals(Visibility.Type.ROLE, comment.getVisibility().getType());
122 		assertEquals(TestConstants.USER_ADMIN, comment.getAuthor());
123 		assertEquals(TestConstants.USER_ADMIN, comment.getUpdateAuthor());
124 	}
125 
126 	private Issue parseIssue(final String resourcePath) throws JSONException {
127 		final JSONObject issueJson = ResourceUtil.getJsonObjectFromResource(resourcePath);
128 		final IssueJsonParser parser = new IssueJsonParser();
129 		return parser.parse(issueJson);
130 	}
131 
132 	@Test
133 	public void testParseIssueWithResolution() throws JSONException {
134 		final Issue issue = parseIssue("/json/issue/valid-all-expanded-with-resolution.json");
135 		assertEquals("Incomplete", issue.getResolution().getName());
136 
137 	}
138 
139 	@Test
140 	public void testParseIssueWhenWatchersAndVotersAreSwitchedOff() throws JSONException {
141 		final Issue issue = parseIssue("/json/issue/valid-no-votes-no-watchers.json");
142 		assertNull(issue.getWatchers());
143 		assertNull(issue.getVotes());
144 	}
145 
146 	@Test
147 	public void testParseUnassignedIssue() throws JSONException {
148 		final Issue issue = parseIssue("/json/issue/valid-unassigned.json");
149 		assertNull(issue.getAssignee());
150 	}
151 
152 	@Test
153 	public void testParseNoTimeTrackingInfo() throws JSONException {
154 		final Issue issue = parseIssue("/json/issue/valid-unassigned.json");
155 		assertNull(issue.getTimeTracking());
156 	}
157 
158 	@Test
159 	public void testParseUnassignedIssueJira4x3() throws JSONException {
160 		final Issue issue = parseIssue("/json/issue/valid-unassigned-jira-4.3.json");
161 		assertNull(issue.getAssignee());
162 	}
163 
164 	@Test
165 	public void testParseIssueWithAnonymousComment() throws JSONException {
166 		final Issue issue = parseIssue("/json/issue/valid-anonymous-comment-jira-4.3.json");
167 		assertEquals(1, Iterables.size(issue.getComments()));
168 		final Comment comment = issue.getComments().iterator().next();
169 		assertEquals("A comment from anonymous user", comment.getBody());
170 		assertNull(comment.getAuthor());
171 
172 	}
173 
174 	@Test
175 	public void testParseIssueWithVisibilityJira4x3() throws JSONException {
176 		final Issue issue = parseIssue("/json/issue/valid-visibility-jira-4.3.json");
177 		assertEquals(Visibility.role("Administrators"), issue.getComments().iterator().next().getVisibility());
178 		assertEquals(Visibility.role("Developers"), Iterables.get(issue.getWorklogs(), 1).getVisibility());
179 		assertEquals(Visibility.group("jira-users"), Iterables.get(issue.getWorklogs(), 2).getVisibility());
180 	}
181 
182 	@Test
183 	public void testParseIssueWithUserPickerCustomFieldFilledOut() throws JSONException {
184 		final Issue issue = parseIssue("/json/issue/valid-user-picker-custom-field-filled-out.json");
185 		final Field extraUserField = issue.getFieldByName("Extra User");
186 		assertNotNull(extraUserField);
187 		assertEquals(BasicUser.class, extraUserField.getValue().getClass());
188 		assertEquals(TestConstants.USER1, extraUserField.getValue());
189 	}
190 
191 	@Test
192 	public void testParseIssueWithUserPickerCustomFieldEmpty() throws JSONException {
193 		final Issue issue = parseIssue("/json/issue/valid-user-picker-custom-field-empty.json");
194 		final Field extraUserField = issue.getFieldByName("Extra User");
195 		assertNotNull(extraUserField);
196 		assertNull(extraUserField.getValue());
197 	}
198 
199 	@Test
200 	public void testParseIssueJira5x0Representation() throws JSONException {
201 		final Issue issue = parseIssue("/json/issue/valid-5.0.json");
202 		assertEquals(3, Iterables.size(issue.getComments()));
203 		final BasicPriority priority = issue.getPriority();
204 		assertNotNull(priority);
205 		assertEquals("Major", priority.getName());
206 		assertEquals("my description", issue.getDescription());
207 		assertEquals("TST", issue.getProject().getKey());
208 		assertEquals(4, Iterables.size(issue.getAttachments()));
209 		assertEquals(1, Iterables.size(issue.getIssueLinks()));
210 		assertEquals(1.457, issue.getField("customfield_10000").getValue());
211 		assertThat(Iterables.transform(issue.getComponents(), new BasicComponentNameExtractionFunction()), IterableMatcher.hasOnlyElements("Component A", "Component B"));
212 		assertEquals(2, Iterables.size(issue.getWorklogs()));
213 		assertEquals(1, issue.getWatchers().getNumWatchers());
214 		assertFalse(issue.getWatchers().isWatching());
215 		assertEquals(new TimeTracking(2700, 2220, 180), issue.getTimeTracking());
216 
217 		assertEquals(Visibility.role("Developers"), issue.getWorklogs().iterator().next().getVisibility());
218 		assertEquals(Visibility.group("jira-users"), Iterables.get(issue.getWorklogs(), 1).getVisibility());
219 
220 	}
221 
222 	@Test
223 	public void testParseIssueJira50Representation() throws JSONException {
224 		final Issue issue = parseIssue("/json/issue/valid-5.0-1.json");
225 	}
226 
227     @Test
228     public void testParseIssueWithProjectNamePresentInRepresentation() throws JSONException {
229         final Issue issue = parseIssue("/json/issue/issue-with-project-name-present.json");
230         assertEquals("My Test Project", issue.getProject().getName());
231     }
232 
233     @Test
234     public void testParseIssueJiraRepresentationJrjc49() throws JSONException {
235         final Issue issue = parseIssue("/json/issue/jrjc49.json");
236         final Iterable<Worklog> worklogs = issue.getWorklogs();
237         assertEquals(1, Iterables.size(worklogs));
238         final Worklog worklog = Iterables.get(worklogs, 0);
239         assertNull(worklog.getComment());
240         assertEquals(180, worklog.getMinutesSpent());
241         assertEquals("Sample, User", worklog.getAuthor().getDisplayName());
242 
243     }
244 
245 	@Test
246 	public void testParseIssueJira5x0RepresentationNullCustomField() throws JSONException {
247 		final Issue issue = parseIssue("/json/issue/valid-5.0-null-custom-field.json");
248 		assertEquals(null, issue.getField("customfield_10000").getValue());
249 		assertNull(issue.getIssueLinks());
250 	}
251 
252 	@Test
253 	public void issueWithSubtasks() throws JSONException {
254 		final Issue issue = parseIssue("/json/issue/subtasks-5.json");
255 		Iterable<Subtask> subtasks = issue.getSubtasks();
256 		assertEquals(1, Iterables.size(subtasks));
257 		Subtask subtask = Iterables.get(subtasks, 0, null);
258 		assertNotNull(subtask);
259 		assertEquals("SAM-2", subtask.getIssueKey());
260 		assertEquals("Open", subtask.getStatus().getName());
261 		assertEquals("Subtask", subtask.getIssueType().getName());
262 	}
263 
264 }