1   /*
2    * Copyright (C) 2012 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.JiraBuildNumberDependent;
20  import com.atlassian.jira.nimblefunctests.annotation.RestoreOnce;
21  import com.atlassian.jira.rest.client.IssueRestClient;
22  import com.atlassian.jira.rest.client.RestClientException;
23  import com.atlassian.jira.rest.client.domain.Issue;
24  import com.atlassian.jira.rest.client.domain.TimeTracking;
25  import com.atlassian.jira.rest.client.domain.Visibility;
26  import com.atlassian.jira.rest.client.domain.Worklog;
27  import com.atlassian.jira.rest.client.domain.input.WorklogInput;
28  import com.atlassian.jira.rest.client.domain.input.WorklogInputBuilder;
29  import com.atlassian.jira.rest.client.internal.json.TestConstants;
30  import com.google.common.collect.ImmutableSet;
31  import com.google.common.collect.Sets;
32  import org.joda.time.DateTime;
33  import org.junit.Test;
34  
35  import javax.annotation.Nullable;
36  import java.util.Set;
37  
38  import static com.atlassian.jira.rest.client.IntegrationTestUtil.GROUP_JIRA_ADMINISTRATORS;
39  import static com.atlassian.jira.rest.client.TestUtil.toUri;
40  import static com.atlassian.jira.rest.client.internal.ServerVersionConstants.BN_JIRA_5;
41  import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
42  import static org.junit.Assert.*;
43  
44  @RestoreOnce(TestConstants.DEFAULT_JIRA_DUMP_FILE)
45  public class JerseyIssueRestClientWorklogTest extends AbstractJerseyRestClientTest {
46  
47  	public static final String ISSUE_KEY = "TST-5";
48  	public static final String ISSUE_KEY_ANONYMOUS = "ANONEDIT-2";
49  
50  	@JiraBuildNumberDependent(BN_JIRA_5)
51  	@Test
52  	public void testAddWorklogAsLoggedUser() {
53  		testAddWorklogImpl(ISSUE_KEY, createDefaulWorklogInputBuilder());
54  	}
55  
56  	@JiraBuildNumberDependent(BN_JIRA_5)
57  	@Test
58  	public void testAddWorklogAsAnonymousWithoutPermissions() {
59  		setAnonymousMode();
60  		try {
61  			testAddWorklogImpl(ISSUE_KEY, createDefaulWorklogInputBuilder());
62  		} catch (RestClientException ex) {
63  			assertThat(ex.getErrorMessages(),
64  					containsInAnyOrder("You do not have the permission to see the specified issue.", "Login Required"));
65  		}
66  	}
67  
68  	@JiraBuildNumberDependent(BN_JIRA_5)
69  	@Test
70  	public void testAddWorklogAsAnonymous() {
71  		setAnonymousMode();
72  		testAddWorklogImpl(ISSUE_KEY_ANONYMOUS, createDefaulWorklogInputBuilder());
73  	}
74  
75  	@JiraBuildNumberDependent(BN_JIRA_5)
76  	@Test
77  	public void testAddWorklogWithEmptyComment() {
78  		testAddWorklogImpl(ISSUE_KEY, createDefaulWorklogInputBuilder().setComment(""));
79  	}
80  
81  	@JiraBuildNumberDependent(BN_JIRA_5)
82  	@Test
83  	public void testAddWorklogWithVisibility() {
84  		Visibility visibility = Visibility.group(GROUP_JIRA_ADMINISTRATORS);
85  		testAddWorklogImpl(ISSUE_KEY, createDefaulWorklogInputBuilder().setVisibility(visibility));
86  	}
87  
88  	@JiraBuildNumberDependent(BN_JIRA_5)
89  	@Test
90  	public void testAddWorklogsWithEstimateAdjustment() {		
91  		final String issueKey = ISSUE_KEY;
92  		
93  		// set estimate in issue
94  		navigation.issue().setEstimates(ISSUE_KEY, "20", "20");
95  		
96  		final WorklogInputBuilder worklogInputBuilder = createDefaulWorklogInputBuilder();
97  		final IssueRestClient issueClient = client.getIssueClient();
98  
99  		// get issue
100 		final Issue initialIssue = issueClient.getIssue(issueKey, pm);
101 
102 		// # First change - test auto
103 		final WorklogInput worklogInput = worklogInputBuilder
104 				.setIssueUri(initialIssue.getSelf())
105 				.setMinutesSpent(2)
106 				.build();
107 		issueClient.addWorklog(initialIssue.getWorklogUri(), worklogInput, pm);
108 
109 		// check if estimate has changed
110 		final Issue issueAfterFirstChange = issueClient.getIssue(issueKey, pm);
111 		final Integer actualTimeSpentAfterChange = getTimeSpentMinutesNotNull(issueAfterFirstChange.getTimeTracking());
112 		final Integer expectedTimeSpentAfterChange = getTimeSpentMinutesNotNull(initialIssue.getTimeTracking()) + worklogInput.getMinutesSpent();
113 		assertEquals(expectedTimeSpentAfterChange, actualTimeSpentAfterChange);
114 
115 		final int actualRemainingEstimate = getRemainingEstimateMinutesNotNull(issueAfterFirstChange.getTimeTracking());
116 		final int expectedRemaningEstimate = getRemainingEstimateMinutesNotNull(initialIssue.getTimeTracking()) - worklogInput.getMinutesSpent();
117 		assertEquals(expectedRemaningEstimate, actualRemainingEstimate);
118 
119 		// # Second change - test new; also we want to be sure that logged time are added, and not set to given value
120 		final Integer newEstimateValue = 15;
121 		final WorklogInput worklogInput2 = worklogInputBuilder
122 				.setIssueUri(initialIssue.getSelf())
123 				.setMinutesSpent(2)
124 				.setAdjustEstimateNew(newEstimateValue)
125 				.build();
126 		issueClient.addWorklog(initialIssue.getWorklogUri(), worklogInput2, pm);
127 
128 		// check if logged time has changed
129 		final Issue issueAfterSecondChange = issueClient.getIssue(issueKey, pm);
130 		final Integer actualTimeSpentAfterChange2 = getTimeSpentMinutesNotNull(issueAfterSecondChange.getTimeTracking());
131 		final Integer expectedTimeSpentAfterChange2 = getTimeSpentMinutesNotNull(issueAfterFirstChange.getTimeTracking()) + worklogInput2.getMinutesSpent();
132 		assertEquals(expectedTimeSpentAfterChange2, actualTimeSpentAfterChange2);
133 
134 		// check if estimate has changed
135 		final Integer actualRemainingEstimate2 = getRemainingEstimateMinutesNotNull(issueAfterSecondChange.getTimeTracking());
136 		assertEquals(newEstimateValue, actualRemainingEstimate2);
137 
138 		// # Third change - test leave
139 		final WorklogInput worklogInput3 = worklogInputBuilder
140 				.setIssueUri(initialIssue.getSelf())
141 				.setMinutesSpent(2)
142 				.setAdjustEstimateLeave()
143 				.build();
144 		issueClient.addWorklog(initialIssue.getWorklogUri(), worklogInput3, pm);
145 
146 		// check if logged time has changed
147 		final Issue issueAfterThirdChange = issueClient.getIssue(issueKey, pm);
148 		final Integer actualTimeSpentAfterChange3 = getTimeSpentMinutesNotNull(issueAfterThirdChange.getTimeTracking());
149 		final Integer expectedTimeSpentAfterChange3 = getTimeSpentMinutesNotNull(issueAfterSecondChange.getTimeTracking()) + worklogInput3.getMinutesSpent();
150 		assertEquals(expectedTimeSpentAfterChange3, actualTimeSpentAfterChange3);
151 
152 		// check if estimate has NOT changed
153 		final Integer actualRemainingEstimate3 = getRemainingEstimateMinutesNotNull(issueAfterThirdChange.getTimeTracking());
154 		final Integer expectedRemainingEstimate3 = getRemainingEstimateMinutesNotNull(issueAfterSecondChange.getTimeTracking());
155 		assertEquals(expectedRemainingEstimate3, actualRemainingEstimate3);
156 
157 		// # Fourth change - test manual
158 		final int reduceByValueManual = 7;
159 		final WorklogInput worklogInput4 = worklogInputBuilder
160 				.setIssueUri(initialIssue.getSelf())
161 				.setMinutesSpent(2)
162 				.setAdjustEstimateManual(reduceByValueManual)
163 				.build();
164 
165 		issueClient.addWorklog(initialIssue.getWorklogUri(), worklogInput4, pm);
166 
167 		// check if logged time has changed
168 		final Issue issueAfterFourthChange = issueClient.getIssue(issueKey, pm);
169 		final Integer actualTimeSpentAfterChange4 = getTimeSpentMinutesNotNull(issueAfterFourthChange.getTimeTracking());
170 		final Integer expectedTimeSpentAfterChange4 = getTimeSpentMinutesNotNull(issueAfterThirdChange.getTimeTracking()) + worklogInput4.getMinutesSpent();
171 		assertEquals(expectedTimeSpentAfterChange4, actualTimeSpentAfterChange4);
172 
173 		// check if estimate has NOT changed
174 		final Integer actualRemainingEstimate4 = getRemainingEstimateMinutesNotNull(issueAfterFourthChange.getTimeTracking());
175 		final Integer expectedRemainingEstimate4 = getRemainingEstimateMinutesNotNull(issueAfterThirdChange.getTimeTracking()) - reduceByValueManual;
176 		assertEquals(expectedRemainingEstimate4, actualRemainingEstimate4);
177 	}
178 
179 	@JiraBuildNumberDependent(BN_JIRA_5)
180 	@Test
181 	public void testAddWorklogsWithEstimateAdjustmentUsingTimeUnits() {
182 		final String issueKey = ISSUE_KEY;
183 
184 		// set estimate in issue
185 		navigation.issue().setEstimates(ISSUE_KEY, "20", "20");
186 
187 		final WorklogInputBuilder worklogInputBuilder = createDefaulWorklogInputBuilder();
188 		final IssueRestClient issueClient = client.getIssueClient();
189 
190 		// get issue
191 		final Issue initialIssue = issueClient.getIssue(issueKey, pm);
192 
193 		// add worklog
194 		final int estimateWeeks = 2;
195 		final int estimateDays = 3;
196 		final int estimateHours = 4;
197 		final int estimateMinutes = 7;
198 		final WorklogInput worklogInput = worklogInputBuilder
199 				.setIssueUri(initialIssue.getSelf())
200 				.setAdjustEstimateNew(String.format("%sw %sd %sh %sm", estimateWeeks, estimateDays, estimateHours, estimateMinutes))
201 				.build();
202 		issueClient.addWorklog(initialIssue.getWorklogUri(), worklogInput, pm);
203 
204 		// check if estimate has changed
205 		final Issue modifiedIssue = issueClient.getIssue(issueKey, pm);
206 		final int actualRemainingEstimate = getRemainingEstimateMinutesNotNull(modifiedIssue.getTimeTracking());
207 		// in current configuration 1w = 5d, 1d = 8h
208 		final int expectedRemaningEstimate = ((estimateWeeks * 5 + estimateDays) * 8 + estimateHours) * 60 + estimateMinutes;
209 		assertEquals(expectedRemaningEstimate, actualRemainingEstimate);
210 	}
211 
212 	private int getTimeSpentMinutesNotNull(@Nullable TimeTracking timeTracking) {
213 		if (timeTracking == null) {
214 			return 0;
215 		}
216 
217 		Integer timeSpentMinutes = timeTracking.getTimeSpentMinutes();
218 		return timeSpentMinutes == null ? 0 : timeSpentMinutes; 
219 	}
220 	
221 	private int getRemainingEstimateMinutesNotNull(@Nullable TimeTracking timeTracking) {
222 		if (timeTracking == null) {
223 			return 0;
224 		}
225 
226 		Integer remainingEstimateMinutes = timeTracking.getRemainingEstimateMinutes();
227 		return remainingEstimateMinutes == null ? 0 : remainingEstimateMinutes; 
228 	}
229 
230 
231 	private Worklog getAddedWorklog(final Set<Worklog> initialWorklogs, Issue issue) {
232 		final Set<Worklog> worklogs = Sets.newHashSet(issue.getWorklogs());
233 		worklogs.removeAll(initialWorklogs);
234 		assertEquals(1, worklogs.size());
235 		return worklogs.iterator().next();
236 	}
237 
238 	private void testAddWorklogImpl(String issueKey, WorklogInputBuilder worklogInputBuilder) {
239 		final IssueRestClient issueClient = client.getIssueClient();
240 
241 		// get initial worklogs
242 		final Issue issue = issueClient.getIssue(issueKey, pm);
243 		final Set<Worklog> initialWorklogs = ImmutableSet.copyOf(issue.getWorklogs());
244 
245 		// create and add new
246 		final WorklogInput worklogInput = worklogInputBuilder.setIssueUri(issue.getSelf()).build();
247 		issueClient.addWorklog(issue.getWorklogUri(), worklogInput, pm);
248 
249 		// check if added correctly
250 		final Issue issueWithWorklog = issueClient.getIssue(issueKey, pm);
251 		final Worklog addedWorklog = getAddedWorklog(initialWorklogs, issueWithWorklog);
252 		assertEquals(worklogInput.getStartDate(), addedWorklog.getStartDate());
253 		assertEquals(worklogInput.getMinutesSpent(), addedWorklog.getMinutesSpent());
254 		assertEquals(worklogInput.getIssueUri(), addedWorklog.getIssueUri());
255 		assertEquals(worklogInput.getComment(), addedWorklog.getComment());
256 		assertEquals(worklogInput.getVisibility(), worklogInput.getVisibility());
257 	}
258 
259 	private WorklogInputBuilder createDefaulWorklogInputBuilder() {
260 		return new WorklogInputBuilder(toUri("dummy://uri"))
261 				.setComment("I created test for adding worklog.")
262 				.setStartDate(new DateTime())
263 				.setMinutesSpent(20);
264 	}
265 
266 }