@Test public void do_not_automatically_reopen_closed_issue_which_have_no_previous_status_in_changelog() { DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(IssueWorkflowTest::newClosedIssue) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.updateDate()).isNull(); }); }
@Test public void setIssueMoved_has_no_effect_if_component_uuid_is_not_changed() { String componentUuid = "a"; issue.setComponentUuid(componentUuid); underTest.setIssueMoved(issue, componentUuid, context); assertThat(issue.changes()).isEmpty(); assertThat(issue.componentUuid()).isEqualTo(componentUuid); assertThat(issue.isChanged()).isFalse(); assertThat(issue.updateDate()).isNull(); assertThat(issue.mustSendNotifications()).isFalse(); }
@Test public void initNewOpenIssue() { DefaultIssue issue = new DefaultIssue() .setRuleKey(XOO_X1); when(debtCalculator.calculate(issue)).thenReturn(DEFAULT_DURATION); underTest.initNewOpenIssue(issue); assertThat(issue.key()).isNotNull(); assertThat(issue.creationDate()).isNotNull(); assertThat(issue.updateDate()).isNotNull(); assertThat(issue.status()).isEqualTo(STATUS_OPEN); assertThat(issue.effort()).isEqualTo(DEFAULT_DURATION); assertThat(issue.isNew()).isTrue(); assertThat(issue.isCopied()).isFalse(); assertThat(issue.isFromHotspot()).isFalse(); }
@Test public void setIssueMoved_changes_componentUuid_adds_a_change() { String oldComponentUuid = "a"; String newComponentUuid = "b"; issue.setComponentUuid(oldComponentUuid); underTest.setIssueMoved(issue, newComponentUuid, context); assertThat(issue.changes()).hasSize(1); FieldDiffs fieldDiffs = issue.changes().get(0); assertThat(fieldDiffs.creationDate()).isEqualTo(context.date()); assertThat(fieldDiffs.diffs()).hasSize(1); Map.Entry<String, FieldDiffs.Diff> entry = fieldDiffs.diffs().entrySet().iterator().next(); assertThat(entry.getKey()).isEqualTo("file"); assertThat(entry.getValue().oldValue()).isEqualTo(oldComponentUuid); assertThat(entry.getValue().newValue()).isEqualTo(newComponentUuid); assertThat(issue.componentUuid()).isEqualTo(newComponentUuid); assertThat(issue.isChanged()).isTrue(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(context.date(), Calendar.SECOND)); } }
@Test public void initNewOpenHotspot() { rule.setType(RuleType.SECURITY_HOTSPOT); DefaultIssue issue = new DefaultIssue() .setRuleKey(XOO_X1); when(debtCalculator.calculate(issue)).thenReturn(DEFAULT_DURATION); underTest.initNewOpenIssue(issue); assertThat(issue.key()).isNotNull(); assertThat(issue.creationDate()).isNotNull(); assertThat(issue.updateDate()).isNotNull(); assertThat(issue.status()).isEqualTo(STATUS_OPEN); assertThat(issue.effort()).isEqualTo(DEFAULT_DURATION); assertThat(issue.isNew()).isTrue(); assertThat(issue.isCopied()).isFalse(); assertThat(issue.isFromHotspot()).isTrue(); }
@Test @UseDataProvider("allResolutionsBeforeClosing") public void automatically_reopen_closed_issue_to_previous_resolution_from_changelog(String resolutionBeforeClosed) { String randomPreviousStatus = ALL_STATUSES_LEADING_TO_CLOSED[new Random().nextInt(ALL_STATUSES_LEADING_TO_CLOSED.length)]; DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); addResolutionAndStatusChange(issue, new Date(), randomPreviousStatus, STATUS_CLOSED, resolutionBeforeClosed, resolution); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(randomPreviousStatus); assertThat(issue.resolution()).isEqualTo(resolutionBeforeClosed); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); assertThat(issue.closeDate()).isNull(); assertThat(issue.isChanged()).isTrue(); }); }
@Test @UseDataProvider("allStatusesLeadingToClosed") public void do_not_automatically_reopen_closed_issues_of_security_hotspots(String previousStatus) { DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); setStatusPreviousToClosed(issue, previousStatus); issue.setType(RuleType.SECURITY_HOTSPOT); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.updateDate()).isNull(); }); }
@Test public void automatically_reopen_closed_issue_to_no_resolution_if_no_previous_one_changelog() { String randomPreviousStatus = ALL_STATUSES_LEADING_TO_CLOSED[new Random().nextInt(ALL_STATUSES_LEADING_TO_CLOSED.length)]; DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); setStatusPreviousToClosed(issue, randomPreviousStatus); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(randomPreviousStatus); assertThat(issue.resolution()).isNull(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); assertThat(issue.closeDate()).isNull(); assertThat(issue.isChanged()).isTrue(); }); }
@Test public void set_severity() { IssueDto issueDto = newIssue().setSeverity(MAJOR); DefaultIssue issue = issueDto.toDefaultIssue(); setUserWithBrowseAndAdministerIssuePermission(issueDto); BulkChangeAction.ActionContext context = new BulkChangeAction.ActionContext(issue, IssueChangeContext.createUser(NOW, userSession.getUuid()), null); action.execute(ImmutableMap.of("severity", MINOR), context); assertThat(issue.severity()).isEqualTo(MINOR); assertThat(issue.isChanged()).isTrue(); assertThat(issue.manualSeverity()).isTrue(); assertThat(issue.updateDate()).isEqualTo(NOW); assertThat(issue.mustSendNotifications()).isTrue(); Map<String, FieldDiffs.Diff> change = issue.currentChange().diffs(); assertThat(change.get("severity").newValue()).isEqualTo(MINOR); assertThat(change.get("severity").oldValue()).isEqualTo(MAJOR); }
@Test @UseDataProvider("allStatusesLeadingToClosed") public void do_not_automatically_reopen_closed_issues_of_manual_vulnerability(String previousStatus) { DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); setStatusPreviousToClosed(issue, previousStatus); issue.setIsFromHotspot(true); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.updateDate()).isNull(); }); }
@Test public void set_type() { IssueDto issueDto = newIssue().setType(BUG); DefaultIssue issue = issueDto.toDefaultIssue(); setUserWithBrowseAndAdministerIssuePermission(issueDto); action.execute(ImmutableMap.of("type", VULNERABILITY.name()), new BulkChangeAction.ActionContext(issue, IssueChangeContext.createUser(NOW, userSession.getUuid()), null)); assertThat(issue.type()).isEqualTo(VULNERABILITY); assertThat(issue.isChanged()).isTrue(); assertThat(issue.updateDate()).isEqualTo(NOW); assertThat(issue.mustSendNotifications()).isFalse(); Map<String, FieldDiffs.Diff> change = issue.currentChange().diffs(); assertThat(change.get("type").newValue()).isEqualTo(VULNERABILITY); assertThat(change.get("type").oldValue()).isEqualTo(BUG); }
@Test @UseDataProvider("allStatusesLeadingToClosed") public void automatically_reopen_closed_issue_to_its_previous_status_from_changelog(String previousStatus) { DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); setStatusPreviousToClosed(issue, previousStatus); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(previousStatus); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); assertThat(issue.closeDate()).isNull(); assertThat(issue.isChanged()).isTrue(); }); }
@Test @UseDataProvider("allResolutionsBeforeClosing") public void automatically_reopen_closed_issue_to_previous_resolution_of_closing_the_issue_if_most_recent_of_all_resolution_changes(String resolutionBeforeClosed) { String randomPreviousStatus = ALL_STATUSES_LEADING_TO_CLOSED[new Random().nextInt(ALL_STATUSES_LEADING_TO_CLOSED.length)]; DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); Date now = new Date(); addResolutionChange(issue, addDays(now, -60), null, RESOLUTION_FALSE_POSITIVE); addResolutionChange(issue, addDays(now, -10), RESOLUTION_FALSE_POSITIVE, resolutionBeforeClosed); addResolutionAndStatusChange(issue, now, randomPreviousStatus, STATUS_CLOSED, resolutionBeforeClosed, resolution); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(randomPreviousStatus); assertThat(issue.resolution()).isEqualTo(resolutionBeforeClosed); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); assertThat(issue.closeDate()).isNull(); assertThat(issue.isChanged()).isTrue(); }); }
@Test @UseDataProvider("allStatusesLeadingToClosed") public void automatically_reopen_closed_issue_to_most_recent_previous_status_from_changelog(String previousStatus) { DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING) .map(resolution -> { DefaultIssue issue = newClosedIssue(resolution); Date now = new Date(); addStatusChange(issue, addDays(now, -60), STATUS_OPEN, STATUS_CONFIRMED); addStatusChange(issue, addDays(now, -10), STATUS_CONFIRMED, previousStatus); setStatusPreviousToClosed(issue, previousStatus); return issue; }) .toArray(DefaultIssue[]::new); Date now = new Date(); workflow.start(); Arrays.stream(issues).forEach(issue -> { workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.status()).isEqualTo(previousStatus); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); assertThat(issue.closeDate()).isNull(); assertThat(issue.isChanged()).isTrue(); }); }
@Test public void set_empty_dates() { issue .setCreationDate(null) .setUpdateDate(null) .setCloseDate(null) .setSelectedAt(null); assertThat(issue.creationDate()).isNull(); assertThat(issue.updateDate()).isNull(); assertThat(issue.closeDate()).isNull(); assertThat(issue.selectedAt()).isNull(); }
@Test public void close_open_dead_issue() { workflow.start(); DefaultIssue issue = new DefaultIssue() .setKey("ABCDE") .setResolution(null) .setStatus(STATUS_OPEN) .setNew(false) .setBeingClosed(true); Date now = new Date(); workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.closeDate()).isNotNull(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); }
@Test public void close_reopened_dead_issue() { workflow.start(); DefaultIssue issue = new DefaultIssue() .setKey("ABCDE") .setResolution(null) .setStatus(STATUS_REOPENED) .setNew(false) .setBeingClosed(true); Date now = new Date(); workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.closeDate()).isNotNull(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); }
@Test public void close_confirmed_dead_issue() { workflow.start(); DefaultIssue issue = new DefaultIssue() .setKey("ABCDE") .setResolution(null) .setStatus(STATUS_CONFIRMED) .setNew(false) .setBeingClosed(true); Date now = new Date(); workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.closeDate()).isNotNull(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); }
@Test public void automatically_close_resolved_issue() { workflow.start(); DefaultIssue issue = new DefaultIssue() .setKey("ABCDE") .setRuleKey(RuleKey.of("js", "S001")) .setResolution(RESOLUTION_FIXED) .setStatus(STATUS_RESOLVED) .setNew(false) .setBeingClosed(true); Date now = new Date(); workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now)); assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED); assertThat(issue.status()).isEqualTo(STATUS_CLOSED); assertThat(issue.closeDate()).isNotNull(); assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND)); }
private void copyFields(DefaultIssue toIssue, DefaultIssue fromIssue) { toIssue.setType(fromIssue.type()); toIssue.setCreationDate(fromIssue.creationDate()); toIssue.setUpdateDate(fromIssue.updateDate()); toIssue.setCloseDate(fromIssue.closeDate()); toIssue.setResolution(fromIssue.resolution()); toIssue.setStatus(fromIssue.status()); toIssue.setAssigneeUuid(fromIssue.assignee()); toIssue.setAuthorLogin(fromIssue.authorLogin()); toIssue.setTags(fromIssue.tags()); toIssue.setAttributes(fromIssue.attributes()); toIssue.setEffort(debtCalculator.calculate(toIssue)); toIssue.setOnDisabledRule(fromIssue.isOnDisabledRule()); toIssue.setSelectedAt(fromIssue.selectedAt()); } }