3 * Copyright (C) 2009-2017 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.step;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.List;
26 import java.util.Random;
27 import java.util.stream.Collectors;
28 import java.util.stream.IntStream;
29 import java.util.stream.Stream;
30 import org.apache.commons.lang.RandomStringUtils;
31 import org.junit.Before;
32 import org.junit.Rule;
33 import org.junit.Test;
34 import org.junit.rules.TemporaryFolder;
35 import org.mockito.ArgumentCaptor;
36 import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
37 import org.sonar.api.notifications.Notification;
38 import org.sonar.api.rules.RuleType;
39 import org.sonar.api.utils.Duration;
40 import org.sonar.api.utils.System2;
41 import org.sonar.core.issue.DefaultIssue;
42 import org.sonar.db.component.ComponentDto;
43 import org.sonar.db.rule.RuleDefinitionDto;
44 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
45 import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
46 import org.sonar.server.computation.task.projectanalysis.component.Component;
47 import org.sonar.server.computation.task.projectanalysis.component.Component.Type;
48 import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
49 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
50 import org.sonar.server.computation.task.projectanalysis.issue.IssueCache;
51 import org.sonar.server.computation.task.projectanalysis.issue.RuleRepositoryRule;
52 import org.sonar.server.computation.task.step.ComputationStep;
53 import org.sonar.server.issue.notification.DistributedMetricStatsInt;
54 import org.sonar.server.issue.notification.IssueChangeNotification;
55 import org.sonar.server.issue.notification.MyNewIssuesNotification;
56 import org.sonar.server.issue.notification.NewIssuesNotification;
57 import org.sonar.server.issue.notification.NewIssuesNotificationFactory;
58 import org.sonar.server.issue.notification.NewIssuesStatistics;
59 import org.sonar.server.notification.NotificationService;
60 import org.sonar.server.util.cache.DiskCache;
62 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
63 import static org.assertj.core.api.Java6Assertions.assertThat;
64 import static org.mockito.Matchers.anyString;
65 import static org.mockito.Matchers.eq;
66 import static org.mockito.Mockito.any;
67 import static org.mockito.Mockito.mock;
68 import static org.mockito.Mockito.never;
69 import static org.mockito.Mockito.verify;
70 import static org.mockito.Mockito.when;
71 import static org.sonar.db.component.ComponentTesting.newBranchDto;
72 import static org.sonar.db.component.ComponentTesting.newFileDto;
73 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
74 import static org.sonar.db.component.ComponentTesting.newProjectBranch;
75 import static org.sonar.db.issue.IssueTesting.newIssue;
76 import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
77 import static org.sonar.db.rule.RuleTesting.newRule;
78 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
80 public class SendIssueNotificationsStepTest extends BaseStepTest {
82 private static final String BRANCH_NAME = "feature";
84 private static final long ANALYSE_DATE = 123L;
85 private static final int FIVE_MINUTES_IN_MS = 1000 * 60 * 5;
87 private static final Duration ISSUE_DURATION = Duration.create(100L);
88 private static final String ISSUE_ASSIGNEE = "John";
90 private static final Component FILE = builder(Component.Type.FILE, 11).build();
91 private static final Component PROJECT = builder(Type.PROJECT, 1)
92 .setVersion(RandomStringUtils.randomAlphanumeric(10))
93 .addChildren(FILE).build();
96 public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
99 public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
100 .setBranch(new DefaultBranchImpl())
101 .setAnalysisDate(new Date(ANALYSE_DATE));
103 public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
105 public TemporaryFolder temp = new TemporaryFolder();
107 private final Random random = new Random();
108 private final RuleType randomRuleType = RuleType.values()[random.nextInt(RuleType.values().length)];
109 private NotificationService notificationService = mock(NotificationService.class);
110 private NewIssuesNotificationFactory newIssuesNotificationFactory = mock(NewIssuesNotificationFactory.class);
111 private NewIssuesNotification newIssuesNotificationMock = createNewIssuesNotificationMock();
112 private MyNewIssuesNotification myNewIssuesNotificationMock = createMyNewIssuesNotificationMock();
114 private IssueCache issueCache;
115 private SendIssueNotificationsStep underTest;
118 public void setUp() throws Exception {
119 issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
120 underTest = new SendIssueNotificationsStep(issueCache, ruleRepository, treeRootHolder, notificationService, analysisMetadataHolder,
121 newIssuesNotificationFactory);
123 when(newIssuesNotificationFactory.newNewIssuesNotication()).thenReturn(newIssuesNotificationMock);
124 when(newIssuesNotificationFactory.newMyNewIssuesNotification()).thenReturn(myNewIssuesNotificationMock);
128 public void do_not_send_notifications_if_no_subscribers() {
129 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(false);
133 verify(notificationService, never()).deliver(any(Notification.class));
137 public void send_global_new_issues_notification() throws Exception {
138 issueCache.newAppender().append(
139 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION)
140 .setCreationDate(new Date(ANALYSE_DATE)))
142 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
146 verify(notificationService).deliver(newIssuesNotificationMock);
147 verify(newIssuesNotificationMock).setProject(PROJECT.getPublicKey(), PROJECT.getUuid(), PROJECT.getName(), null);
148 verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
149 verify(newIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), any(NewIssuesStatistics.Stats.class));
150 verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
154 public void send_global_new_issues_notification_only_for_non_backdated_issues() {
155 Random random = new Random();
156 Integer[] efforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10_000 * i).toArray(Integer[]::new);
157 Integer[] backDatedEfforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10 + random.nextInt(100)).toArray(Integer[]::new);
158 Duration expectedEffort = Duration.create(Arrays.stream(efforts).mapToInt(i -> i).sum());
159 List<DefaultIssue> issues = Stream.concat(Arrays.stream(efforts)
160 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
161 .setCreationDate(new Date(ANALYSE_DATE))),
162 Arrays.stream(backDatedEfforts)
163 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
164 .setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))))
165 .collect(Collectors.toList());
166 Collections.shuffle(issues);
167 DiskCache<DefaultIssue>.DiskAppender issueCache = this.issueCache.newAppender();
168 issues.forEach(issueCache::append);
169 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
173 verify(notificationService).deliver(newIssuesNotificationMock);
174 ArgumentCaptor<NewIssuesStatistics.Stats> statsCaptor = ArgumentCaptor.forClass(NewIssuesStatistics.Stats.class);
175 verify(newIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), statsCaptor.capture());
176 verify(newIssuesNotificationMock).setDebt(expectedEffort);
177 NewIssuesStatistics.Stats stats = statsCaptor.getValue();
178 assertThat(stats.hasIssues()).isTrue();
179 // just checking all issues have been added to the stats
180 DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
181 assertThat(severity.getOnLeak()).isEqualTo(efforts.length);
182 assertThat(severity.getOffLeak()).isEqualTo(backDatedEfforts.length);
183 assertThat(severity.getTotal()).isEqualTo(backDatedEfforts.length + efforts.length);
187 public void do_not_send_global_new_issues_notification_if_issue_has_been_backdated() {
188 issueCache.newAppender().append(
189 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION)
190 .setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS)))
192 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
196 verify(notificationService, never()).deliver(any(Notification.class));
200 public void send_global_new_issues_notification_on_branch() throws Exception {
201 ComponentDto branch = setUpProjectWithBranch();
202 issueCache.newAppender().append(
203 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE))).close();
204 when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
205 analysisMetadataHolder.setBranch(newBranch());
209 verify(notificationService).deliver(newIssuesNotificationMock);
210 verify(newIssuesNotificationMock).setProject(branch.getKey(), branch.uuid(), branch.longName(), BRANCH_NAME);
211 verify(newIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
212 verify(newIssuesNotificationMock).setStatistics(eq(branch.longName()), any(NewIssuesStatistics.Stats.class));
213 verify(newIssuesNotificationMock).setDebt(ISSUE_DURATION);
217 public void do_not_send_global_new_issues_notification_on_branch_if_issue_has_been_backdated() throws Exception {
218 ComponentDto branch = setUpProjectWithBranch();
219 issueCache.newAppender().append(
220 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))).close();
221 when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
222 analysisMetadataHolder.setBranch(newBranch());
226 verify(notificationService, never()).deliver(any(Notification.class));
230 public void send_new_issues_notification_to_user() throws Exception {
231 issueCache.newAppender().append(
232 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
233 .setCreationDate(new Date(ANALYSE_DATE)))
235 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
239 verify(notificationService).deliver(newIssuesNotificationMock);
240 verify(notificationService).deliver(myNewIssuesNotificationMock);
241 verify(myNewIssuesNotificationMock).setAssignee(ISSUE_ASSIGNEE);
242 verify(myNewIssuesNotificationMock).setProject(PROJECT.getPublicKey(), PROJECT.getUuid(), PROJECT.getName(), null);
243 verify(myNewIssuesNotificationMock).setAnalysisDate(new Date(ANALYSE_DATE));
244 verify(myNewIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), any(NewIssuesStatistics.Stats.class));
245 verify(myNewIssuesNotificationMock).setDebt(ISSUE_DURATION);
249 public void send_new_issues_notification_to_user_only_for_those_assigned_to_her() {
250 Random random = new Random();
251 Integer[] assigned = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10_000 * i).toArray(Integer[]::new);
252 Integer[] assignedToOther = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10 + random.nextInt(100)).toArray(Integer[]::new);
253 Duration expectedEffort = Duration.create(Arrays.stream(assigned).mapToInt(i -> i).sum());
254 String assignee = randomAlphanumeric(5);
255 String otherAssignee = randomAlphanumeric(5);
256 List<DefaultIssue> issues = Stream.concat(Arrays.stream(assigned)
257 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
258 .setAssignee(assignee)
259 .setCreationDate(new Date(ANALYSE_DATE))),
260 Arrays.stream(assignedToOther)
261 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
262 .setAssignee(otherAssignee)
263 .setCreationDate(new Date(ANALYSE_DATE))))
264 .collect(Collectors.toList());
265 Collections.shuffle(issues);
266 DiskCache<DefaultIssue>.DiskAppender issueCache = this.issueCache.newAppender();
267 issues.forEach(issueCache::append);
268 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
269 MyNewIssuesNotification myNewIssuesNotificationMock2 = createMyNewIssuesNotificationMock();
270 when(newIssuesNotificationFactory.newMyNewIssuesNotification())
271 .thenReturn(myNewIssuesNotificationMock)
272 .thenReturn(myNewIssuesNotificationMock2);
276 verify(notificationService).deliver(newIssuesNotificationMock);
277 verify(notificationService).deliver(myNewIssuesNotificationMock);
278 verify(notificationService).deliver(myNewIssuesNotificationMock2);
280 MyNewIssuesNotification effectiveMyNewIssuesNotificationMock = this.myNewIssuesNotificationMock;
282 verify(effectiveMyNewIssuesNotificationMock).setAssignee(assignee);
283 } catch (ArgumentsAreDifferent e) {
284 assertThat(e.getMessage())
285 .contains("Wanted:\nmyNewIssuesNotification.setAssignee(\"" + assignee + "\")")
286 .contains("Actual invocation has different arguments:\n" +
287 "myNewIssuesNotification.setAssignee(\"" + otherAssignee + "\")");
288 effectiveMyNewIssuesNotificationMock = myNewIssuesNotificationMock2;
290 ArgumentCaptor<NewIssuesStatistics.Stats> statsCaptor = ArgumentCaptor.forClass(NewIssuesStatistics.Stats.class);
291 verify(effectiveMyNewIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), statsCaptor.capture());
292 verify(effectiveMyNewIssuesNotificationMock).setDebt(expectedEffort);
293 NewIssuesStatistics.Stats stats = statsCaptor.getValue();
294 assertThat(stats.hasIssues()).isTrue();
295 // just checking all issues have been added to the stats
296 DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
297 assertThat(severity.getOnLeak()).isEqualTo(assigned.length);
298 assertThat(severity.getOffLeak()).isEqualTo(0);
299 assertThat(severity.getTotal()).isEqualTo(assigned.length);
303 public void send_new_issues_notification_to_user_only_for_non_backdated_issues() throws Exception {
304 Random random = new Random();
305 Integer[] efforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10_000 * i).toArray(Integer[]::new);
306 Integer[] backDatedEfforts = IntStream.range(0, 1 + random.nextInt(10)).mapToObj(i -> 10 + random.nextInt(100)).toArray(Integer[]::new);
307 Duration expectedEffort = Duration.create(Arrays.stream(efforts).mapToInt(i -> i).sum());
308 List<DefaultIssue> issues = Stream.concat(Arrays.stream(efforts)
309 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
310 .setAssignee(ISSUE_ASSIGNEE)
311 .setCreationDate(new Date(ANALYSE_DATE))),
312 Arrays.stream(backDatedEfforts)
313 .map(effort -> new DefaultIssue().setType(randomRuleType).setEffort(Duration.create(effort))
314 .setAssignee(ISSUE_ASSIGNEE)
315 .setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS))))
316 .collect(Collectors.toList());
317 Collections.shuffle(issues);
318 DiskCache<DefaultIssue>.DiskAppender issueCache = this.issueCache.newAppender();
319 issues.forEach(issueCache::append);
320 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
324 verify(notificationService).deliver(newIssuesNotificationMock);
325 verify(notificationService).deliver(myNewIssuesNotificationMock);
326 verify(myNewIssuesNotificationMock).setAssignee(ISSUE_ASSIGNEE);
327 ArgumentCaptor<NewIssuesStatistics.Stats> statsCaptor = ArgumentCaptor.forClass(NewIssuesStatistics.Stats.class);
328 verify(myNewIssuesNotificationMock).setStatistics(eq(PROJECT.getName()), statsCaptor.capture());
329 verify(myNewIssuesNotificationMock).setDebt(expectedEffort);
330 NewIssuesStatistics.Stats stats = statsCaptor.getValue();
331 assertThat(stats.hasIssues()).isTrue();
332 // just checking all issues have been added to the stats
333 DistributedMetricStatsInt severity = stats.getDistributedMetricStats(NewIssuesStatistics.Metric.RULE_TYPE);
334 assertThat(severity.getOnLeak()).isEqualTo(efforts.length);
335 assertThat(severity.getOffLeak()).isEqualTo(backDatedEfforts.length);
336 assertThat(severity.getTotal()).isEqualTo(backDatedEfforts.length + efforts.length);
340 public void do_not_send_new_issues_notification_to_user_if_issue_is_backdated() throws Exception {
341 issueCache.newAppender().append(
342 new DefaultIssue().setType(randomRuleType).setEffort(ISSUE_DURATION).setAssignee(ISSUE_ASSIGNEE)
343 .setCreationDate(new Date(ANALYSE_DATE - FIVE_MINUTES_IN_MS)))
345 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
349 verify(notificationService, never()).deliver(any(Notification.class));
353 public void send_issues_change_notification() throws Exception {
354 sendIssueChangeNotification(ANALYSE_DATE);
358 public void send_issues_change_notification_even_if_issue_is_backdated() throws Exception {
359 sendIssueChangeNotification(ANALYSE_DATE - FIVE_MINUTES_IN_MS);
362 private void sendIssueChangeNotification(long issueCreatedAt) {
363 ComponentDto project = newPrivateProjectDto(newOrganizationDto()).setDbKey(PROJECT.getKey()).setLongName(PROJECT.getName());
364 ComponentDto file = newFileDto(project).setDbKey(FILE.getKey()).setLongName(FILE.getName());
365 RuleDefinitionDto ruleDefinitionDto = newRule();
366 DefaultIssue issue = newIssue(ruleDefinitionDto, project, file).toDefaultIssue()
367 .setNew(false).setChanged(true).setSendNotifications(true).setCreationDate(new Date(issueCreatedAt));
368 ruleRepository.add(ruleDefinitionDto.getKey()).setName(ruleDefinitionDto.getName());
369 issueCache.newAppender().append(issue).close();
370 when(notificationService.hasProjectSubscribersForTypes(PROJECT.getUuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
374 ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class);
375 verify(notificationService).deliver(issueChangeNotificationCaptor.capture());
376 IssueChangeNotification issueChangeNotification = issueChangeNotificationCaptor.getValue();
377 assertThat(issueChangeNotification.getFieldValue("key")).isEqualTo(issue.key());
378 assertThat(issueChangeNotification.getFieldValue("assignee")).isEqualTo(issue.assignee());
379 assertThat(issueChangeNotification.getFieldValue("message")).isEqualTo(issue.message());
380 assertThat(issueChangeNotification.getFieldValue("ruleName")).isEqualTo(ruleDefinitionDto.getName());
381 assertThat(issueChangeNotification.getFieldValue("projectName")).isEqualTo(project.longName());
382 assertThat(issueChangeNotification.getFieldValue("projectKey")).isEqualTo(project.getKey());
383 assertThat(issueChangeNotification.getFieldValue("componentKey")).isEqualTo(file.getKey());
384 assertThat(issueChangeNotification.getFieldValue("componentName")).isEqualTo(file.longName());
388 public void send_issues_change_notification_on_branch() throws Exception {
389 sendIssueChangeNotificationOnBranch(ANALYSE_DATE);
393 public void send_issues_change_notification_on_branch_even_if_issue_is_backdated() throws Exception {
394 sendIssueChangeNotificationOnBranch(ANALYSE_DATE - FIVE_MINUTES_IN_MS);
397 private void sendIssueChangeNotificationOnBranch(long issueCreatedAt) {
398 ComponentDto project = newPrivateProjectDto(newOrganizationDto());
399 ComponentDto branch = newProjectBranch(project, newBranchDto(project).setKey(BRANCH_NAME));
400 ComponentDto file = newFileDto(branch);
401 treeRootHolder.setRoot(builder(Type.PROJECT, 2).setKey(branch.getDbKey()).setPublicKey(branch.getKey()).setName(branch.longName()).setUuid(branch.uuid()).addChildren(
402 builder(Type.FILE, 11).setKey(file.getDbKey()).setPublicKey(file.getKey()).setName(file.longName()).build()).build());
403 RuleDefinitionDto ruleDefinitionDto = newRule();
404 DefaultIssue issue = newIssue(ruleDefinitionDto, branch, file).toDefaultIssue()
407 .setSendNotifications(true)
408 .setCreationDate(new Date(issueCreatedAt));
409 ruleRepository.add(ruleDefinitionDto.getKey()).setName(ruleDefinitionDto.getName());
410 issueCache.newAppender().append(issue).close();
411 when(notificationService.hasProjectSubscribersForTypes(branch.uuid(), SendIssueNotificationsStep.NOTIF_TYPES)).thenReturn(true);
412 analysisMetadataHolder.setBranch(newBranch());
416 ArgumentCaptor<IssueChangeNotification> issueChangeNotificationCaptor = ArgumentCaptor.forClass(IssueChangeNotification.class);
417 verify(notificationService).deliver(issueChangeNotificationCaptor.capture());
418 IssueChangeNotification issueChangeNotification = issueChangeNotificationCaptor.getValue();
419 assertThat(issueChangeNotification.getFieldValue("projectName")).isEqualTo(branch.longName());
420 assertThat(issueChangeNotification.getFieldValue("projectKey")).isEqualTo(branch.getKey());
421 assertThat(issueChangeNotification.getFieldValue("branch")).isEqualTo(BRANCH_NAME);
422 assertThat(issueChangeNotification.getFieldValue("componentKey")).isEqualTo(file.getKey());
423 assertThat(issueChangeNotification.getFieldValue("componentName")).isEqualTo(file.longName());
426 private NewIssuesNotification createNewIssuesNotificationMock() {
427 NewIssuesNotification notification = mock(NewIssuesNotification.class);
428 when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
429 when(notification.setProjectVersion(anyString())).thenReturn(notification);
430 when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
431 when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
432 when(notification.setDebt(any(Duration.class))).thenReturn(notification);
436 private MyNewIssuesNotification createMyNewIssuesNotificationMock() {
437 MyNewIssuesNotification notification = mock(MyNewIssuesNotification.class);
438 when(notification.setAssignee(anyString())).thenReturn(notification);
439 when(notification.setProject(anyString(), anyString(), anyString(), anyString())).thenReturn(notification);
440 when(notification.setProjectVersion(anyString())).thenReturn(notification);
441 when(notification.setAnalysisDate(any(Date.class))).thenReturn(notification);
442 when(notification.setStatistics(anyString(), any(NewIssuesStatistics.Stats.class))).thenReturn(notification);
443 when(notification.setDebt(any(Duration.class))).thenReturn(notification);
447 private static Branch newBranch() {
448 Branch branch = mock(Branch.class);
449 when(branch.isMain()).thenReturn(false);
450 when(branch.getName()).thenReturn(BRANCH_NAME);
454 private ComponentDto setUpProjectWithBranch() {
455 ComponentDto project = newPrivateProjectDto(newOrganizationDto());
456 ComponentDto branch = newProjectBranch(project, newBranchDto(project).setKey(BRANCH_NAME));
457 ComponentDto file = newFileDto(branch);
458 treeRootHolder.setRoot(builder(Type.PROJECT, 2).setKey(branch.getDbKey()).setPublicKey(branch.getKey()).setName(branch.longName()).setUuid(branch.uuid()).addChildren(
459 builder(Type.FILE, 11).setKey(file.getDbKey()).setPublicKey(file.getKey()).setName(file.longName()).build()).build());
464 protected ComputationStep step() {