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