diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2018-07-02 15:07:45 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2018-07-09 10:39:31 +0200 |
commit | ecbd530ab653001d01a64734ad2f29889e511680 (patch) | |
tree | 84a024c27cb976fd44bda7e521904297e7de885f /server/sonar-server-common/src/test/java/org | |
parent | 69714b41c96eb99271a21735f09ca1a17ff4eaef (diff) | |
download | sonarqube-ecbd530ab653001d01a64734ad2f29889e511680.tar.gz sonarqube-ecbd530ab653001d01a64734ad2f29889e511680.zip |
move issue workflow classes to server-common
Diffstat (limited to 'server/sonar-server-common/src/test/java/org')
10 files changed, 1253 insertions, 0 deletions
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueFieldsSetterTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueFieldsSetterTest.java new file mode 100644 index 00000000000..0be2e028f14 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueFieldsSetterTest.java @@ -0,0 +1,519 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue; + +import java.util.Calendar; +import java.util.Date; +import java.util.Map; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.Duration; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.FieldDiffs; +import org.sonar.core.issue.IssueChangeContext; +import org.sonar.db.user.UserDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.rules.ExpectedException.none; +import static org.sonar.db.user.UserTesting.newUserDto; +import static org.sonar.server.issue.IssueFieldsSetter.ASSIGNEE; +import static org.sonar.server.issue.IssueFieldsSetter.RESOLUTION; +import static org.sonar.server.issue.IssueFieldsSetter.SEVERITY; +import static org.sonar.server.issue.IssueFieldsSetter.STATUS; +import static org.sonar.server.issue.IssueFieldsSetter.TECHNICAL_DEBT; +import static org.sonar.server.issue.IssueFieldsSetter.UNUSED; + +public class IssueFieldsSetterTest { + + @Rule + public ExpectedException thrown = none(); + + private DefaultIssue issue = new DefaultIssue(); + private IssueChangeContext context = IssueChangeContext.createUser(new Date(), "user_uuid"); + private IssueFieldsSetter underTest = new IssueFieldsSetter(); + + @Test + public void assign() { + UserDto user = newUserDto().setLogin("emmerik").setName("Emmerik"); + + boolean updated = underTest.assign(issue, user, context); + assertThat(updated).isTrue(); + assertThat(issue.assignee()).isEqualTo(user.getUuid()); + assertThat(issue.mustSendNotifications()).isTrue(); + FieldDiffs.Diff diff = issue.currentChange().get(ASSIGNEE); + assertThat(diff.oldValue()).isEqualTo(UNUSED); + assertThat(diff.newValue()).isEqualTo(user.getName()); + } + + @Test + public void unassign() { + issue.setAssigneeUuid("user_uuid"); + boolean updated = underTest.assign(issue, null, context); + assertThat(updated).isTrue(); + assertThat(issue.assignee()).isNull(); + assertThat(issue.mustSendNotifications()).isTrue(); + FieldDiffs.Diff diff = issue.currentChange().get(ASSIGNEE); + assertThat(diff.oldValue()).isEqualTo(UNUSED); + assertThat(diff.newValue()).isNull(); + } + + @Test + public void change_assignee() { + UserDto user = newUserDto().setLogin("emmerik").setName("Emmerik"); + + issue.setAssigneeUuid("user_uuid"); + boolean updated = underTest.assign(issue, user, context); + assertThat(updated).isTrue(); + assertThat(issue.assignee()).isEqualTo(user.getUuid()); + assertThat(issue.mustSendNotifications()).isTrue(); + FieldDiffs.Diff diff = issue.currentChange().get(ASSIGNEE); + assertThat(diff.oldValue()).isEqualTo(UNUSED); + assertThat(diff.newValue()).isEqualTo(user.getName()); + } + + @Test + public void not_change_assignee() { + UserDto user = newUserDto().setLogin("morgan").setName("Morgan"); + + issue.setAssigneeUuid(user.getUuid()); + boolean updated = underTest.assign(issue, user, context); + assertThat(updated).isFalse(); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_new_assignee() { + boolean updated = underTest.setNewAssignee(issue, "user_uuid", context); + assertThat(updated).isTrue(); + assertThat(issue.assignee()).isEqualTo("user_uuid"); + assertThat(issue.mustSendNotifications()).isTrue(); + FieldDiffs.Diff diff = issue.currentChange().get(ASSIGNEE); + assertThat(diff.oldValue()).isEqualTo(UNUSED); + assertThat(diff.newValue()).isEqualTo("user_uuid"); + } + + @Test + public void not_set_new_assignee_if_new_assignee_is_null() { + boolean updated = underTest.setNewAssignee(issue, null, context); + assertThat(updated).isFalse(); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void fail_with_ISE_when_setting_new_assignee_on_already_assigned_issue() { + issue.setAssigneeUuid("user_uuid"); + + thrown.expect(IllegalStateException.class); + thrown.expectMessage("It's not possible to update the assignee with this method, please use assign()"); + underTest.setNewAssignee(issue, "another_user_uuid", context); + } + + @Test + public void set_severity() { + boolean updated = underTest.setSeverity(issue, "BLOCKER", context); + assertThat(updated).isTrue(); + assertThat(issue.severity()).isEqualTo("BLOCKER"); + assertThat(issue.manualSeverity()).isFalse(); + assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(SEVERITY); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo("BLOCKER"); + } + + @Test + public void set_past_severity() { + issue.setSeverity("BLOCKER"); + boolean updated = underTest.setPastSeverity(issue, "INFO", context); + assertThat(updated).isTrue(); + assertThat(issue.severity()).isEqualTo("BLOCKER"); + assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(SEVERITY); + assertThat(diff.oldValue()).isEqualTo("INFO"); + assertThat(diff.newValue()).isEqualTo("BLOCKER"); + } + + @Test + public void update_severity() { + issue.setSeverity("BLOCKER"); + boolean updated = underTest.setSeverity(issue, "MINOR", context); + + assertThat(updated).isTrue(); + assertThat(issue.severity()).isEqualTo("MINOR"); + assertThat(issue.mustSendNotifications()).isFalse(); + FieldDiffs.Diff diff = issue.currentChange().get(SEVERITY); + assertThat(diff.oldValue()).isEqualTo("BLOCKER"); + assertThat(diff.newValue()).isEqualTo("MINOR"); + } + + @Test + public void not_change_severity() { + issue.setSeverity("MINOR"); + boolean updated = underTest.setSeverity(issue, "MINOR", context); + assertThat(updated).isFalse(); + assertThat(issue.mustSendNotifications()).isFalse(); + assertThat(issue.currentChange()).isNull(); + } + + @Test + public void not_revert_manual_severity() { + issue.setSeverity("MINOR").setManualSeverity(true); + try { + underTest.setSeverity(issue, "MAJOR", context); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Severity can't be changed"); + } + } + + @Test + public void set_manual_severity() { + issue.setSeverity("BLOCKER"); + boolean updated = underTest.setManualSeverity(issue, "MINOR", context); + + assertThat(updated).isTrue(); + assertThat(issue.severity()).isEqualTo("MINOR"); + assertThat(issue.manualSeverity()).isTrue(); + assertThat(issue.mustSendNotifications()).isTrue(); + FieldDiffs.Diff diff = issue.currentChange().get(SEVERITY); + assertThat(diff.oldValue()).isEqualTo("BLOCKER"); + assertThat(diff.newValue()).isEqualTo("MINOR"); + } + + @Test + public void not_change_manual_severity() { + issue.setSeverity("MINOR").setManualSeverity(true); + boolean updated = underTest.setManualSeverity(issue, "MINOR", context); + assertThat(updated).isFalse(); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_line() { + boolean updated = underTest.setLine(issue, 123); + assertThat(updated).isTrue(); + assertThat(issue.line()).isEqualTo(123); + assertThat(issue.mustSendNotifications()).isFalse(); + // do not save change + assertThat(issue.currentChange()).isNull(); + } + + @Test + public void set_past_line() { + issue.setLine(42); + boolean updated = underTest.setPastLine(issue, 123); + assertThat(updated).isTrue(); + assertThat(issue.line()).isEqualTo(42); + assertThat(issue.mustSendNotifications()).isFalse(); + + // do not save change + assertThat(issue.currentChange()).isNull(); + } + + @Test + public void line_is_not_changed() { + issue.setLine(123); + boolean updated = underTest.setLine(issue, 123); + assertThat(updated).isFalse(); + assertThat(issue.line()).isEqualTo(123); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void change_locations() { + issue.setLocations("[1-3]"); + boolean updated = underTest.setLocations(issue, "[1-4]"); + assertThat(updated).isTrue(); + assertThat(issue.getLocations().toString()).isEqualTo("[1-4]"); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void do_not_change_locations() { + issue.setLocations("[1-3]"); + boolean updated = underTest.setLocations(issue, "[1-3]"); + assertThat(updated).isFalse(); + assertThat(issue.getLocations().toString()).isEqualTo("[1-3]"); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_locations_for_the_first_time() { + issue.setLocations(null); + boolean updated = underTest.setLocations(issue, "[1-4]"); + assertThat(updated).isTrue(); + assertThat(issue.getLocations().toString()).isEqualTo("[1-4]"); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_resolution() { + boolean updated = underTest.setResolution(issue, "OPEN", context); + assertThat(updated).isTrue(); + assertThat(issue.resolution()).isEqualTo("OPEN"); + + FieldDiffs.Diff diff = issue.currentChange().get(RESOLUTION); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo("OPEN"); + assertThat(issue.mustSendNotifications()).isTrue(); + } + + @Test + public void not_change_resolution() { + issue.setResolution("FIXED"); + boolean updated = underTest.setResolution(issue, "FIXED", context); + assertThat(updated).isFalse(); + assertThat(issue.resolution()).isEqualTo("FIXED"); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_status() { + boolean updated = underTest.setStatus(issue, "OPEN", context); + assertThat(updated).isTrue(); + assertThat(issue.status()).isEqualTo("OPEN"); + + FieldDiffs.Diff diff = issue.currentChange().get(STATUS); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo("OPEN"); + assertThat(issue.mustSendNotifications()).isTrue(); + } + + @Test + public void not_change_status() { + issue.setStatus("CLOSED"); + boolean updated = underTest.setStatus(issue, "CLOSED", context); + assertThat(updated).isFalse(); + assertThat(issue.status()).isEqualTo("CLOSED"); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_new_attribute_value() { + boolean updated = underTest.setAttribute(issue, "JIRA", "FOO-123", context); + assertThat(updated).isTrue(); + assertThat(issue.attribute("JIRA")).isEqualTo("FOO-123"); + assertThat(issue.currentChange().diffs()).hasSize(1); + assertThat(issue.currentChange().get("JIRA").oldValue()).isNull(); + assertThat(issue.currentChange().get("JIRA").newValue()).isEqualTo("FOO-123"); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void unset_attribute() { + issue.setAttribute("JIRA", "FOO-123"); + boolean updated = underTest.setAttribute(issue, "JIRA", null, context); + assertThat(updated).isTrue(); + assertThat(issue.attribute("JIRA")).isNull(); + assertThat(issue.currentChange().diffs()).hasSize(1); + assertThat(issue.currentChange().get("JIRA").oldValue()).isEqualTo("FOO-123"); + assertThat(issue.currentChange().get("JIRA").newValue()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void not_update_attribute() { + issue.setAttribute("JIRA", "FOO-123"); + boolean updated = underTest.setAttribute(issue, "JIRA", "FOO-123", context); + assertThat(updated).isFalse(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_gap_to_fix() { + boolean updated = underTest.setGap(issue, 3.14, context); + assertThat(updated).isTrue(); + assertThat(issue.isChanged()).isTrue(); + assertThat(issue.gap()).isEqualTo(3.14); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void not_set_gap_to_fix_if_unchanged() { + issue.setGap(3.14); + boolean updated = underTest.setGap(issue, 3.14, context); + assertThat(updated).isFalse(); + assertThat(issue.isChanged()).isFalse(); + assertThat(issue.gap()).isEqualTo(3.14); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_past_gap() { + issue.setGap(3.14); + boolean updated = underTest.setPastGap(issue, 1.0, context); + assertThat(updated).isTrue(); + assertThat(issue.gap()).isEqualTo(3.14); + + // do not save change + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_past_technical_debt() { + Duration newDebt = Duration.create(15 * 8 * 60); + Duration previousDebt = Duration.create(10 * 8 * 60); + issue.setEffort(newDebt); + boolean updated = underTest.setPastEffort(issue, previousDebt, context); + assertThat(updated).isTrue(); + assertThat(issue.effort()).isEqualTo(newDebt); + assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT); + assertThat(diff.oldValue()).isEqualTo(10L * 8 * 60); + assertThat(diff.newValue()).isEqualTo(15L * 8 * 60); + } + + @Test + public void set_past_technical_debt_without_previous_value() { + Duration newDebt = Duration.create(15 * 8 * 60); + issue.setEffort(newDebt); + boolean updated = underTest.setPastEffort(issue, null, context); + assertThat(updated).isTrue(); + assertThat(issue.effort()).isEqualTo(newDebt); + assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo(15L * 8 * 60); + } + + @Test + public void set_past_technical_debt_with_null_new_value() { + issue.setEffort(null); + Duration previousDebt = Duration.create(10 * 8 * 60); + boolean updated = underTest.setPastEffort(issue, previousDebt, context); + assertThat(updated).isTrue(); + assertThat(issue.effort()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + + FieldDiffs.Diff diff = issue.currentChange().get(TECHNICAL_DEBT); + assertThat(diff.oldValue()).isEqualTo(10L * 8 * 60); + assertThat(diff.newValue()).isNull(); + } + + @Test + public void set_message() { + boolean updated = underTest.setMessage(issue, "the message", context); + assertThat(updated).isTrue(); + assertThat(issue.isChanged()).isTrue(); + assertThat(issue.message()).isEqualTo("the message"); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_past_message() { + issue.setMessage("new message"); + boolean updated = underTest.setPastMessage(issue, "past message", context); + assertThat(updated).isTrue(); + assertThat(issue.message()).isEqualTo("new message"); + + // do not save change + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_author() { + boolean updated = underTest.setAuthorLogin(issue, "eric", context); + assertThat(updated).isTrue(); + assertThat(issue.authorLogin()).isEqualTo("eric"); + + FieldDiffs.Diff diff = issue.currentChange().get("author"); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo("eric"); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void set_new_author() { + boolean updated = underTest.setNewAuthor(issue, "simon", context); + assertThat(updated).isTrue(); + + FieldDiffs.Diff diff = issue.currentChange().get("author"); + assertThat(diff.oldValue()).isNull(); + assertThat(diff.newValue()).isEqualTo("simon"); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void not_set_new_author_if_new_author_is_null() { + boolean updated = underTest.setNewAuthor(issue, null, context); + assertThat(updated).isFalse(); + assertThat(issue.currentChange()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void fail_with_ISE_when_setting_new_author_on_issue() { + issue.setAuthorLogin("simon"); + + thrown.expect(IllegalStateException.class); + thrown.expectMessage("It's not possible to update the author with this method, please use setAuthorLogin()"); + underTest.setNewAuthor(issue, "julien", context); + } + + @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 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)); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IsBeingClosedTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IsBeingClosedTest.java new file mode 100644 index 00000000000..f20e35aab69 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IsBeingClosedTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; +import org.sonar.core.issue.DefaultIssue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.issue.workflow.IsBeingClosed.INSTANCE; + +public class IsBeingClosedTest { + + @Test + public void should_be_end_of_life() { + DefaultIssue issue = new DefaultIssue(); + assertThat(INSTANCE.matches(issue.setBeingClosed(true))).isTrue(); + assertThat(INSTANCE.matches(issue.setBeingClosed(false))).isFalse(); + } + +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IssueWorkflowTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IssueWorkflowTest.java new file mode 100644 index 00000000000..0580233ca31 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/IssueWorkflowTest.java @@ -0,0 +1,266 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import javax.annotation.Nullable; +import org.apache.commons.lang.time.DateUtils; +import org.junit.Test; +import org.sonar.api.issue.DefaultTransitions; +import org.sonar.api.rule.RuleKey; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueChangeContext; +import org.sonar.server.issue.IssueFieldsSetter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE; +import static org.sonar.api.issue.Issue.RESOLUTION_FIXED; +import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX; +import static org.sonar.api.issue.Issue.STATUS_CLOSED; +import static org.sonar.api.issue.Issue.STATUS_CONFIRMED; +import static org.sonar.api.issue.Issue.STATUS_OPEN; +import static org.sonar.api.issue.Issue.STATUS_REOPENED; +import static org.sonar.api.issue.Issue.STATUS_RESOLVED; + +public class IssueWorkflowTest { + + IssueFieldsSetter updater = new IssueFieldsSetter(); + IssueWorkflow workflow = new IssueWorkflow(new FunctionExecutor(updater), updater); + + @Test + public void init_state_machine() { + assertThat(workflow.machine()).isNull(); + workflow.start(); + assertThat(workflow.machine()).isNotNull(); + assertThat(workflow.machine().state(STATUS_OPEN)).isNotNull(); + assertThat(workflow.machine().state(STATUS_CONFIRMED)).isNotNull(); + assertThat(workflow.machine().state(STATUS_CLOSED)).isNotNull(); + assertThat(workflow.machine().state(STATUS_REOPENED)).isNotNull(); + assertThat(workflow.machine().state(STATUS_RESOLVED)).isNotNull(); + workflow.stop(); + } + + @Test + public void list_statuses() { + workflow.start(); + // order is important for UI + assertThat(workflow.statusKeys()).containsSubsequence(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED); + } + + @Test + public void list_out_transitions_from_status_open() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus(STATUS_OPEN); + List<Transition> transitions = workflow.outTransitions(issue); + assertThat(keys(transitions)).containsOnly("confirm", "falsepositive", "resolve", "wontfix"); + } + + @Test + public void list_out_transitions_from_status_confirmed() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus(STATUS_CONFIRMED); + List<Transition> transitions = workflow.outTransitions(issue); + assertThat(keys(transitions)).containsOnly("unconfirm", "falsepositive", "resolve", "wontfix"); + } + + @Test + public void list_out_transitions_from_status_resolved() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus(STATUS_RESOLVED); + List<Transition> transitions = workflow.outTransitions(issue); + assertThat(keys(transitions)).containsOnly("reopen"); + } + + @Test + public void list_out_transitions_from_status_reopen() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus(STATUS_REOPENED); + List<Transition> transitions = workflow.outTransitions(issue); + assertThat(keys(transitions)).containsOnly("confirm", "resolve", "falsepositive", "wontfix"); + } + + @Test + public void list_no_out_transition_from_status_closed() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus(STATUS_CLOSED).setRuleKey(RuleKey.of("java", "R1 ")); + List<Transition> transitions = workflow.outTransitions(issue); + assertThat(transitions).isEmpty(); + } + + @Test + public void fail_if_unknown_status_when_listing_transitions() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue().setStatus("xxx"); + try { + workflow.outTransitions(issue); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Unknown status: xxx"); + } + } + + @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)); + } + + @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 fail_if_unknown_status_on_automatic_trans() { + workflow.start(); + + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setResolution(RESOLUTION_FIXED) + .setStatus("xxx") + .setNew(false) + .setBeingClosed(true); + try { + workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(new Date())); + fail(); + } catch (IllegalStateException e) { + assertThat(e).hasMessage("Unknown status: xxx [issue=ABCDE]"); + } + } + + @Test + public void flag_as_false_positive() { + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setStatus(STATUS_OPEN) + .setRuleKey(RuleKey.of("squid", "AvoidCycle")) + .setAssigneeUuid("morgan"); + + workflow.start(); + workflow.doTransition(issue, DefaultTransitions.FALSE_POSITIVE, IssueChangeContext.createScan(new Date())); + + assertThat(issue.resolution()).isEqualTo(RESOLUTION_FALSE_POSITIVE); + assertThat(issue.status()).isEqualTo(STATUS_RESOLVED); + + // should remove assignee + assertThat(issue.assignee()).isNull(); + } + + @Test + public void wont_fix() { + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setStatus(STATUS_OPEN) + .setRuleKey(RuleKey.of("squid", "AvoidCycle")) + .setAssigneeUuid("morgan"); + + workflow.start(); + workflow.doTransition(issue, DefaultTransitions.WONT_FIX, IssueChangeContext.createScan(new Date())); + + assertThat(issue.resolution()).isEqualTo(RESOLUTION_WONT_FIX); + assertThat(issue.status()).isEqualTo(STATUS_RESOLVED); + + // should remove assignee + assertThat(issue.assignee()).isNull(); + } + + private Collection<String> keys(List<Transition> transitions) { + return Collections2.transform(transitions, new Function<Transition, String>() { + @Override + public String apply(@Nullable Transition transition) { + return transition.key(); + } + }); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetCloseDateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetCloseDateTest.java new file mode 100644 index 00000000000..ee139df8786 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetCloseDateTest.java @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class SetCloseDateTest { + @Test + public void should_set_close_date() { + SetCloseDate function = new SetCloseDate(true); + Function.Context context = mock(Function.Context.class); + function.execute(context); + verify(context, times(1)).setCloseDate(true); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetClosedTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetClosedTest.java new file mode 100644 index 00000000000..8c526c4b16b --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetClosedTest.java @@ -0,0 +1,59 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; +import org.sonar.api.issue.Issue; +import org.sonar.core.issue.DefaultIssue; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.sonar.server.issue.workflow.SetClosed.INSTANCE; + +public class SetClosedTest { + + Function.Context context = mock(Function.Context.class); + + @Test + public void should_resolve_as_fixed() { + Issue issue = new DefaultIssue().setBeingClosed(true).setOnDisabledRule(false); + when(context.issue()).thenReturn(issue); + INSTANCE.execute(context); + verify(context, times(1)).setResolution(Issue.RESOLUTION_FIXED); + } + + @Test + public void should_resolve_as_removed_when_rule_is_disabled() { + Issue issue = new DefaultIssue().setBeingClosed(true).setOnDisabledRule(true); + when(context.issue()).thenReturn(issue); + INSTANCE.execute(context); + verify(context, times(1)).setResolution(Issue.RESOLUTION_REMOVED); + } + + @Test + public void line_number_must_be_unset() { + Issue issue = new DefaultIssue().setBeingClosed(true).setLine(10); + when(context.issue()).thenReturn(issue); + INSTANCE.execute(context); + verify(context).setLine(null); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetResolutionTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetResolutionTest.java new file mode 100644 index 00000000000..d84e4d6f5d0 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/SetResolutionTest.java @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class SetResolutionTest { + @Test + public void execute() { + SetResolution function = new SetResolution("FIXED"); + Function.Context context = mock(Function.Context.class); + function.execute(context); + verify(context, times(1)).setResolution("FIXED"); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateMachineTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateMachineTest.java new file mode 100644 index 00000000000..92182ff6062 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateMachineTest.java @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class StateMachineTest { + @Test + public void keep_order_of_state_keys() { + StateMachine machine = StateMachine.builder().states("OPEN", "RESOLVED", "CLOSED").build(); + + assertThat(machine.stateKeys()).containsSubsequence("OPEN", "RESOLVED", "CLOSED"); + } + + @Test + public void stateKey() { + StateMachine machine = StateMachine.builder() + .states("OPEN", "RESOLVED", "CLOSED") + .transition(Transition.builder("resolve").from("OPEN").to("RESOLVED").build()) + .build(); + + assertThat(machine.state("OPEN")).isNotNull(); + assertThat(machine.state("OPEN").transition("resolve")).isNotNull(); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateTest.java new file mode 100644 index 00000000000..c432d210aad --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/StateTest.java @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class StateTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + Transition t1 = Transition.builder("close").from("OPEN").to("CLOSED").build(); + + @Test + public void key_should_be_set() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("State key must be set"); + + new State("", new Transition[0]); + } + + @Test + public void key_should_be_upper_case() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("State key must be upper-case"); + + new State("close", new Transition[0]); + } + + @Test + public void no_duplicated_out_transitions() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Transition 'close' is declared several times from the originating state 'CLOSE'"); + + new State("CLOSE", new Transition[] {t1, t1}); + } + + @Test + public void fail_when_transition_is_unknown() { + State state = new State("VALIDATED", new Transition[0]); + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Transition from state VALIDATED does not exist: Unknown Transition"); + + state.transition("Unknown Transition"); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/TransitionTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/TransitionTest.java new file mode 100644 index 00000000000..ede5b240413 --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/TransitionTest.java @@ -0,0 +1,153 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; +import org.sonar.api.issue.condition.Condition; +import org.sonar.api.web.UserRole; +import org.sonar.core.issue.DefaultIssue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class TransitionTest { + + Condition condition1 = mock(Condition.class); + Condition condition2 = mock(Condition.class); + Function function1 = mock(Function.class); + Function function2 = mock(Function.class); + + @Test + public void test_builder() { + Transition transition = Transition.builder("close") + .from("OPEN").to("CLOSED") + .conditions(condition1, condition2) + .functions(function1, function2) + .requiredProjectPermission(UserRole.ISSUE_ADMIN) + .build(); + assertThat(transition.key()).isEqualTo("close"); + assertThat(transition.from()).isEqualTo("OPEN"); + assertThat(transition.to()).isEqualTo("CLOSED"); + assertThat(transition.conditions()).containsOnly(condition1, condition2); + assertThat(transition.functions()).containsOnly(function1, function2); + assertThat(transition.automatic()).isFalse(); + assertThat(transition.requiredProjectPermission()).isEqualTo(UserRole.ISSUE_ADMIN); + } + + @Test + public void test_simplest_transition() { + Transition transition = Transition.builder("close") + .from("OPEN").to("CLOSED") + .build(); + assertThat(transition.key()).isEqualTo("close"); + assertThat(transition.from()).isEqualTo("OPEN"); + assertThat(transition.to()).isEqualTo("CLOSED"); + assertThat(transition.conditions()).isEmpty(); + assertThat(transition.functions()).isEmpty(); + assertThat(transition.requiredProjectPermission()).isNull(); + } + + @Test + public void key_should_be_set() { + try { + Transition.builder("").from("OPEN").to("CLOSED").build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Transition key must be set"); + } + } + + @Test + public void key_should_be_lower_case() { + try { + Transition.builder("CLOSE").from("OPEN").to("CLOSED").build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Transition key must be lower-case"); + } + } + + @Test + public void originating_status_should_be_set() { + try { + Transition.builder("close").from("").to("CLOSED").build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Originating status must be set"); + } + } + + @Test + public void destination_status_should_be_set() { + try { + Transition.builder("close").from("OPEN").to("").build(); + fail(); + } catch (Exception e) { + assertThat(e).hasMessage("Destination status must be set"); + } + } + + @Test + public void should_verify_conditions() { + DefaultIssue issue = new DefaultIssue(); + Transition transition = Transition.builder("close") + .from("OPEN").to("CLOSED") + .conditions(condition1, condition2) + .build(); + + when(condition1.matches(issue)).thenReturn(true); + when(condition2.matches(issue)).thenReturn(false); + assertThat(transition.supports(issue)).isFalse(); + + when(condition1.matches(issue)).thenReturn(true); + when(condition2.matches(issue)).thenReturn(true); + assertThat(transition.supports(issue)).isTrue(); + } + + @Test + public void test_equals_and_hashCode() { + Transition t1 = Transition.create("resolve", "OPEN", "RESOLVED"); + Transition t2 = Transition.create("resolve", "REOPENED", "RESOLVED"); + Transition t3 = Transition.create("confirm", "OPEN", "CONFIRMED"); + + assertThat(t1).isNotEqualTo(t2); + assertThat(t1).isNotEqualTo(t3); + assertThat(t1).isEqualTo(t1); + + assertThat(t1.hashCode()).isEqualTo(t1.hashCode()); + } + + @Test + public void test_toString() { + Transition t1 = Transition.create("resolve", "OPEN", "RESOLVED"); + assertThat(t1.toString()).isEqualTo("OPEN->resolve->RESOLVED"); + } + + @Test + public void test_automatic_transition() { + Transition transition = Transition.builder("close") + .from("OPEN").to("CLOSED") + .automatic() + .build(); + assertThat(transition.automatic()).isTrue(); + } +} diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/UnsetAssigneeTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/UnsetAssigneeTest.java new file mode 100644 index 00000000000..c4c88aa3aba --- /dev/null +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/workflow/UnsetAssigneeTest.java @@ -0,0 +1,37 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.issue.workflow; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.sonar.server.issue.workflow.UnsetAssignee.INSTANCE; + +public class UnsetAssigneeTest { + + @Test + public void unassign() { + Function.Context context = mock(Function.Context.class); + INSTANCE.execute(context); + verify(context, times(1)).setAssignee(null); + } +} |