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