1   /*
2    * Copyright (C) 2011 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.rest.client.IntegrationTestUtil;
20  import com.atlassian.jira.rest.client.IterableMatcher;
21  import com.atlassian.jira.rest.client.TestUtil;
22  import com.atlassian.jira.rest.client.annotation.Restore;
23  import com.atlassian.jira.rest.client.domain.Issue;
24  import com.atlassian.jira.rest.client.domain.Version;
25  import com.atlassian.jira.rest.client.domain.VersionRelatedIssuesCount;
26  import com.atlassian.jira.rest.client.domain.input.VersionInput;
27  import com.atlassian.jira.rest.client.domain.input.VersionInputBuilder;
28  import com.atlassian.jira.rest.client.domain.input.VersionPosition;
29  import com.atlassian.jira.rest.client.internal.json.TestConstants;
30  import com.google.common.base.Function;
31  import com.google.common.collect.Iterables;
32  import com.google.common.collect.Lists;
33  import org.junit.Test;
34  
35  import javax.annotation.Nullable;
36  import javax.ws.rs.core.Response;
37  import java.net.URI;
38  
39  import static com.atlassian.jira.rest.client.TestUtil.getLastPathSegment;
40  import static org.junit.Assert.*;
41  
42  @Restore(TestConstants.DEFAULT_JIRA_DUMP_FILE)
43  public class JerseyVersionRestClientTest extends AbstractJerseyRestClientTest {
44  
45  	@Test
46  	public void testCreateAndUpdateVersion() throws Exception {
47  		if (!isJira4x4OrNewer()) {
48  			return;
49  		}
50  
51  		assertThat(Iterables.transform(client.getProjectClient().getProject("TST", pm).getVersions(),
52  				new VersionToNameMapper()), IterableMatcher.hasOnlyElements("1.1", "1"));
53  
54  		final VersionInput versionInput = VersionInput.create("TST", "My newly created version", "A description\nwith\new line", null, false, false);
55  		final Version version = client.getVersionRestClient().createVersion(versionInput, pm);
56  		assertVersionInputAndVersionEquals(versionInput, version);
57  		assertNotNull(version.getId());
58  		assertThat(Iterables.transform(client.getProjectClient().getProject("TST", pm).getVersions(), new VersionToNameMapper()),
59  				IterableMatcher.hasOnlyElements("1.1", "1", versionInput.getName()));
60  
61  		TestUtil.assertErrorCode(Response.Status.BAD_REQUEST, "A version with this name already exists in this project.", new Runnable() {
62  			@Override
63  			public void run() {
64  				client.getVersionRestClient().createVersion(versionInput, pm);
65  			}
66  		});
67  
68  
69  		final VersionInput versionInput2 = VersionInput.create("TST", "My newly created version2", "A description\nwith\new line", null, false, false);
70  		setAnonymousMode();
71  		TestUtil.assertErrorCode(IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ? Response.Status.NOT_FOUND : Response.Status.UNAUTHORIZED, new Runnable() {
72  			@Override
73  			public void run() {
74  				client.getVersionRestClient().createVersion(versionInput2, pm);
75  			}
76  		});
77  
78  		setUser2();
79  		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "Project with key 'TST' either does not exist or you do not have permission to create versions in it.", new Runnable() {
80  			@Override
81  			public void run() {
82  				client.getVersionRestClient().createVersion(versionInput2, pm);
83  			}
84  		});
85  
86  		// now version updates
87  		setAdmin();
88  		final VersionInput newVersionInput = new VersionInputBuilder(versionInput.getProjectKey(), version)
89  				.setDescription("my updated description").setReleased(true).setName("my updated name").build();
90  		client.getVersionRestClient().updateVersion(version.getSelf(), newVersionInput, pm);
91  		final Version modifiedVersion = client.getVersionRestClient().updateVersion(version.getSelf(), newVersionInput, pm);
92  		assertVersionInputAndVersionEquals(newVersionInput, modifiedVersion);
93  
94  		final VersionInput duplicateVersionInput = new VersionInputBuilder("TST", modifiedVersion).setName("1.1").build();
95  		TestUtil.assertErrorCode(Response.Status.BAD_REQUEST, "A version with this name already exists in this project.", new Runnable() {
96  			@Override
97  			public void run() {
98  				client.getVersionRestClient().updateVersion(modifiedVersion.getSelf(), duplicateVersionInput, pm);
99  			}
100 		});
101 
102 		setAnonymousMode();
103 		TestUtil.assertErrorCode(IntegrationTestUtil.TESTING_JIRA_5_OR_NEWER ? Response.Status.NOT_FOUND : Response.Status.UNAUTHORIZED, new Runnable() {
104 			@Override
105 			public void run() {
106 				client.getVersionRestClient().updateVersion(modifiedVersion.getSelf(), newVersionInput, pm);
107 			}
108 		});
109 
110 		setAdmin();
111 		final Version restrictedVersion = client.getVersionRestClient().createVersion(new VersionInputBuilder("RST").setName("My version").build(), pm);
112 		final VersionInput restrictedVersionInput = new VersionInputBuilder("RST", restrictedVersion).setDescription("another description").build();
113 		setUser2();
114 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "You must have browse project rights in order to view versions.", new Runnable() {
115 			@Override
116 			public void run() {
117 				client.getVersionRestClient().updateVersion(restrictedVersion.getSelf(), restrictedVersionInput, pm);
118 			}
119 		});
120 
121 	}
122 
123 	private void assertVersionInputAndVersionEquals(VersionInput versionInput, Version version) {
124 		assertEquals(version.getName(), versionInput.getName());
125 		assertEquals(version.getDescription(), versionInput.getDescription());
126 		assertEquals(version.getReleaseDate(), versionInput.getReleaseDate());
127 		assertEquals(version.isArchived(), versionInput.isArchived());
128 		assertEquals(version.isReleased(), versionInput.isReleased());
129 	}
130 
131 
132 	private static class VersionToNameMapper implements Function<Version, String> {
133 		@Override
134 		public String apply(Version from) {
135 			return from.getName();
136 		}
137 	}
138 
139 	@Test
140 	public void testGetAndRemoveVersion() {
141 		if (!isJira4x4OrNewer()) {
142 			return;
143 		}
144 		final Iterable<Version> versionsInTheBeggining = client.getProjectClient().getProject("TST", pm).getVersions();
145 		final VersionInput versionInput = VersionInput.create("TST", "My newly created version", "A description\nwith\new line", null, false, false);
146 		final Version version = client.getVersionRestClient().createVersion(versionInput, pm);
147 		assertEquals(version, client.getVersionRestClient().getVersion(version.getSelf(), pm));
148 
149 		setAnonymousMode();
150 		// weird - inconsistent with PUT/POST
151 		TestUtil.assertErrorCode(Response.Status.NOT_FOUND, "You must have browse project rights in order to view versions.", new Runnable() {
152 			@Override
153 			public void run() {
154 				client.getVersionRestClient().getVersion(version.getSelf(), pm);
155 			}
156 		});
157 
158 		setAdmin();
159 		TestUtil.assertErrorCodeWithRegexp(Response.Status.NOT_FOUND, "Could not find version for id .*", new Runnable() {
160 			@Override
161 			public void run() {
162 				client.getVersionRestClient().getVersion(TestUtil.toUri(version.getSelf().toString() + "9"), pm);
163 			}
164 		});
165 
166 		setUser1();
167 		assertEquals(version, client.getVersionRestClient().getVersion(version.getSelf(), pm));
168 
169 		TestUtil.assertErrorCode(Response.Status.UNAUTHORIZED, "The user wseliga does not have permission to complete this operation.", new Runnable() {
170 			@Override
171 			public void run() {
172 				client.getVersionRestClient().removeVersion(version.getSelf(), null, null, pm);
173 			}
174 		});
175 
176 		setAdmin();
177 		client.getVersionRestClient().removeVersion(version.getSelf(), null, null, pm);
178 		TestUtil.assertErrorCodeWithRegexp(Response.Status.NOT_FOUND, "Could not find version for id .*", new Runnable() {
179 			@Override
180 			public void run() {
181 				client.getVersionRestClient().getVersion(version.getSelf(), pm);
182 			}
183 		});
184 
185 		assertThat(client.getProjectClient().getProject("TST", pm).getVersions(), IterableMatcher.hasOnlyElements(versionsInTheBeggining));
186 		for (Version ver : versionsInTheBeggining) {
187 			client.getVersionRestClient().removeVersion(ver.getSelf(), null, null, pm);
188 		}
189 		assertThat(client.getProjectClient().getProject("TST", pm).getVersions(), IterableMatcher.<Version>isEmpty());
190 
191 	}
192 
193 
194 	@Test
195 	public void testDeleteAndMoveVersion() {
196 		if (!isJira4x4OrNewer()) {
197 			return;
198 		}
199 		final Issue issue = client.getIssueClient().getIssue("TST-2", pm);
200 		assertThat(Iterables.transform(issue.getFixVersions(), new VersionToNameMapper()), IterableMatcher.hasOnlyElements("1.1"));
201 		assertThat(Iterables.transform(issue.getAffectedVersions(), new VersionToNameMapper()), IterableMatcher.hasOnlyElements("1", "1.1"));
202 
203 		final Version version1 = TestUtil.findEntityByName(client.getProjectClient().getProject("TST", pm).getVersions(), "1");
204 
205 		final Version version = Iterables.getOnlyElement(issue.getFixVersions());
206 		final URI fakeVersionUri = TestUtil.toUri("http://localhost/version/3432");
207 		final URI fakeVersionUri2 = TestUtil.toUri("http://localhost/version/34323");
208 		// @todo expected error code should be rather NOT FOUND in all cases below - see JRA-25045
209 		assertInvalidMoveToVersion(version.getSelf(), fakeVersionUri, null, "The fix version with id " +
210 				getLastPathSegment(fakeVersionUri) + " does not exist.", Response.Status.BAD_REQUEST);
211 		// @todo fix when bug JRA-25044 is fixed
212 		assertInvalidMoveToVersion(version.getSelf(), TestUtil.toUri("http://localhost/version/fdsa34323"), null,
213 				"Could not find version for id '-1'", Response.Status.NOT_FOUND);
214 		assertInvalidMoveToVersion(version.getSelf(), null, fakeVersionUri2, "The affects version with id " +
215 				getLastPathSegment(fakeVersionUri2) + " does not exist.", Response.Status.BAD_REQUEST);
216 		assertInvalidMoveToVersion(version.getSelf(), fakeVersionUri, fakeVersionUri2, "The affects version with id " +
217 				getLastPathSegment(fakeVersionUri2) + " does not exist.", Response.Status.BAD_REQUEST);
218 
219 		assertEquals(1, client.getVersionRestClient().getNumUnresolvedIssues(version.getSelf(), pm));
220 		assertEquals(new VersionRelatedIssuesCount(version.getSelf(), 1, 1), client.getVersionRestClient().getVersionRelatedIssuesCount(version.getSelf(), pm));
221 		assertEquals(new VersionRelatedIssuesCount(version.getSelf(), 1, 1), client.getVersionRestClient().getVersionRelatedIssuesCount(version.getSelf(), pm));
222 
223 		// now removing the first version
224 		client.getVersionRestClient().removeVersion(version.getSelf(), version1.getSelf(), version1.getSelf(), pm);
225 		final Issue issueAfterVerRemoval = client.getIssueClient().getIssue("TST-2", pm);
226 		assertThat(Iterables.transform(issueAfterVerRemoval.getFixVersions(), new VersionToNameMapper()), IterableMatcher.hasOnlyElements("1"));
227 		assertThat(Iterables.transform(issueAfterVerRemoval.getAffectedVersions(), new VersionToNameMapper()), IterableMatcher.hasOnlyElements("1"));
228 		assertThat(Iterables.transform(client.getProjectClient().getProject("TST", pm).getVersions(), new VersionToNameMapper()),
229 				IterableMatcher.hasOnlyElements("1"));
230 
231 		TestUtil.assertErrorCode(Response.Status.BAD_REQUEST, "You cannot move the issues to the version being deleted.", new Runnable() {
232 			@Override
233 			public void run() {
234 				client.getVersionRestClient().removeVersion(version1.getSelf(), version1.getSelf(), version1.getSelf(), pm);
235 			}
236 		});
237 
238 		// now removing the other version
239 		client.getVersionRestClient().removeVersion(version1.getSelf(), null, null, pm);
240 		final Issue issueAfter2VerRemoval = client.getIssueClient().getIssue("TST-2", pm);
241 		assertThat(Iterables.transform(issueAfter2VerRemoval.getFixVersions(), new VersionToNameMapper()), IterableMatcher.<String>isEmpty());
242 		assertThat(Iterables.transform(issueAfter2VerRemoval.getAffectedVersions(), new VersionToNameMapper()), IterableMatcher.<String>isEmpty());
243 	}
244 
245 	private void assertInvalidMoveToVersion(final URI versionUri, @Nullable final URI moveFixIssuesToVersionUri,
246 			@Nullable final URI moveAffectedIssuesToVersionUri, final String expectedErrorMsg, final Response.Status status) {
247 		TestUtil.assertErrorCode(status, expectedErrorMsg, new Runnable() {
248 			@Override
249 			public void run() {
250 				client.getVersionRestClient().removeVersion(versionUri, moveFixIssuesToVersionUri, moveAffectedIssuesToVersionUri, pm);
251 			}
252 		});
253 	}
254 
255 	@Test
256 	public void testMoveVersion() {
257 		if (!isJira4x4OrNewer()) {
258 			return;
259 		}
260 		final Version v3 = client.getVersionRestClient().createVersion(VersionInput.create("TST", "my added version", "a description", null, false, false), pm);
261 		assertProjectHasOrderedVersions("TST", "1", "1.1", v3.getName());
262 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.FIRST, pm);
263 		assertProjectHasOrderedVersions("TST", v3.getName(), "1", "1.1");
264 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.LAST, pm);
265 		assertProjectHasOrderedVersions("TST", "1", "1.1", v3.getName());
266 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.EARLIER, pm);
267 		assertProjectHasOrderedVersions("TST", "1", v3.getName(), "1.1");
268 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.EARLIER, pm);
269 		assertProjectHasOrderedVersions("TST", v3.getName(), "1", "1.1");
270 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.LATER, pm);
271 		assertProjectHasOrderedVersions("TST", "1", v3.getName(), "1.1");
272 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.LATER, pm);
273 		assertProjectHasOrderedVersions("TST", "1", "1.1", v3.getName());
274 		// later for the last version means nothing - but also no error
275 		client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.LATER, pm);
276 		assertProjectHasOrderedVersions("TST", "1", "1.1", v3.getName());
277 
278 		setUser1();
279 		TestUtil.assertErrorCode(Response.Status.UNAUTHORIZED, "You must have global or project administrator rights in order to modify versions.", new Runnable() {
280 			@Override
281 			public void run() {
282 				client.getVersionRestClient().moveVersion(v3.getSelf(), VersionPosition.FIRST, pm);
283 			}
284 		});
285 
286 	}
287 
288 	@Test
289 	public void testMoveVersionAfter() {
290 		if (!isJira4x4OrNewer()) {
291 			return;
292 		}
293 		final Version v3 = client.getVersionRestClient().createVersion(VersionInput.create("TST", "my added version", "a description", null, false, false), pm);
294 		final Version v4 = client.getVersionRestClient().createVersion(VersionInput.create("TST", "my added version2", "a description2", null, true, false), pm);
295 		final Version v1 = Iterables.get(client.getProjectClient().getProject("TST", pm).getVersions(), 0);
296 		final String v1n = v1.getName();
297 		final String v3n = v3.getName();
298 		final String v4n = v4.getName();
299 		assertProjectHasOrderedVersions("TST", v1n, "1.1", v3n, v4n);
300 		client.getVersionRestClient().moveVersionAfter(v3.getSelf(), v4.getSelf(), pm);
301 		assertProjectHasOrderedVersions("TST", v1n, "1.1", v4n, v3n);
302 		client.getVersionRestClient().moveVersionAfter(v3.getSelf(), v1.getSelf(), pm);
303 		assertProjectHasOrderedVersions("TST", v1n, v3n, "1.1", v4n);
304 		client.getVersionRestClient().moveVersionAfter(v1.getSelf(), v4.getSelf(), pm);
305 		assertProjectHasOrderedVersions("TST", v3n, "1.1", v4n, v1n);
306 
307 		setUser1();
308 		TestUtil.assertErrorCode(Response.Status.UNAUTHORIZED, "You must have global or project administrator rights in order to modify versions.", new Runnable() {
309 			@Override
310 			public void run() {
311 				client.getVersionRestClient().moveVersionAfter(v3.getSelf(), v4.getSelf(), pm);
312 			}
313 		});
314 
315 		setAnonymousMode();
316 		TestUtil.assertErrorCode(Response.Status.UNAUTHORIZED, new Runnable() {
317 			@Override
318 			public void run() {
319 				client.getVersionRestClient().moveVersionAfter(v3.getSelf(), v4.getSelf(), pm);
320 			}
321 		});
322 	}
323 
324 
325 	private void assertProjectHasOrderedVersions(String projectKey, String... expectedVersions) {
326 		assertEquals(Lists.newArrayList(expectedVersions), Lists.newArrayList(Iterables.transform(client.getProjectClient().getProject(projectKey, pm).getVersions(), new VersionToNameMapper())));
327 	}
328 }