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