import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
+import org.sonarqube.ws.Issues;
+import org.sonarqube.ws.client.issue.SearchWsRequest;
import util.ProjectAnalysis;
import util.ProjectAnalysisRule;
+import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static util.ItUtils.newAdminWsClient;
public class IssueWorkflowTest extends AbstractIssueTest {
assertThat(confirmed.creationDate()).isEqualTo(issue.creationDate());
// user unconfirm the issue
- assertThat(adminIssueClient().transitions(confirmed.key())).contains("unconfirm");
+ assertThat(transitions(confirmed.key())).contains("unconfirm");
adminIssueClient().doTransition(confirmed.key(), "unconfirm");
Issue unconfirmed = searchIssueByKey(issue.key());
assertThat(confirmed.creationDate()).isEqualTo(issue.creationDate());
// user mark the issue as false-positive
- assertThat(adminIssueClient().transitions(confirmed.key())).contains("falsepositive");
+ assertThat(transitions(confirmed.key())).contains("falsepositive");
adminIssueClient().doTransition(confirmed.key(), "falsepositive");
Issue falsePositive = searchIssueByKey(issue.key());
assertThat(resolved.creationDate()).isEqualTo(issue.creationDate());
// user reopens the issue
- assertThat(adminIssueClient().transitions(resolved.key())).contains("reopen");
+ assertThat(transitions(resolved.key())).contains("reopen");
adminIssueClient().doTransition(resolved.key(), "reopen");
Issue reopened = searchIssueByKey(resolved.key());
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
// user reopens the issue
- assertThat(adminIssueClient().transitions(falsePositive.key())).contains("reopen");
+ assertThat(transitions(falsePositive.key())).contains("reopen");
adminIssueClient().doTransition(falsePositive.key(), "reopen");
Issue reopened = searchIssueByKey(issue.key());
analysisWithoutIssues.run();
// user try to reopen the issue
- assertThat(adminIssueClient().transitions(issue.key())).isEmpty();
+ assertThat(transitions(issue.key())).isEmpty();
+ }
+
+ private List<String> transitions(String issueKey) {
+ Issues.SearchWsResponse response = searchIssues(new SearchWsRequest().setIssues(singletonList(issueKey)).setAdditionalFields(singletonList("transitions")));
+ assertThat(response.getTotal()).isEqualTo(1);
+ return response.getIssues(0).getTransitions().getTransitionsList();
+ }
+
+ private Issues.SearchWsResponse searchIssues(SearchWsRequest request) {
+ return newAdminWsClient(ORCHESTRATOR).issues().search(request);
}
}
package org.sonar.server.issue;
import com.google.common.annotations.VisibleForTesting;
-import java.util.List;
import java.util.Map;
import org.sonar.api.issue.IssueComment;
import org.sonar.api.server.ServerSide;
import org.sonar.server.es.SearchOptions;
-import org.sonar.server.issue.workflow.Transition;
import org.sonar.server.user.UserSession;
import org.sonar.server.util.RubyUtils;
import org.sonarqube.ws.client.issue.IssuesWsParameters;
@ServerSide
public class InternalRubyIssueService {
- private final IssueService issueService;
private final IssueCommentService commentService;
private final IssueChangelogService changelogService;
private final IssueBulkChangeService issueBulkChangeService;
private final UserSession userSession;
public InternalRubyIssueService(
- IssueService issueService,
IssueCommentService commentService,
IssueChangelogService changelogService,
IssueBulkChangeService issueBulkChangeService,
UserSession userSession) {
- this.issueService = issueService;
this.commentService = commentService;
this.changelogService = changelogService;
this.issueBulkChangeService = issueBulkChangeService;
this.userSession = userSession;
}
- public List<Transition> listTransitions(String issueKey) {
- return issueService.listTransitions(issueKey);
- }
-
public IssueChangelog changelog(String issueKey) {
return changelogService.changelog(issueKey);
}
this.userSession = userSession;
}
- /**
- * List of available transitions.
- * <p>
- * Never return null, but return an empty list if the issue does not exist.
- */
- public List<Transition> listTransitions(String issueKey) {
- DbSession session = dbClient.openSession(false);
- try {
- return listTransitions(getByKeyForUpdate(session, issueKey).toDefaultIssue());
- } finally {
- session.close();
- }
- }
-
/**
* Never return null, but an empty list if the issue does not exist.
* No security check is done since it should already have been done to get the issue
public static final String ADD_COMMENT_ACTION = "add_comment";
public static final String DELETE_COMMENT_ACTION = "delete_comment";
public static final String EDIT_COMMENT_ACTION = "edit_comment";
- public static final String TRANSITIONS_ACTION = "transitions";
public static final String BULK_CHANGE_ACTION = "bulk_change";
private final IssuesWsAction[] actions;
defineAddCommentAction(controller);
defineDeleteCommentAction(controller);
defineEditCommentAction(controller);
- defineTransitionsAction(controller);
defineBulkChangeAction(controller);
}
RailsHandler.addFormatParam(action);
}
- private static void defineTransitionsAction(NewController controller) {
- WebService.NewAction action = controller.createAction(TRANSITIONS_ACTION)
- .setDescription("Get Possible Workflow Transitions for an Issue. Requires Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setResponseExample(Resources.getResource(IssuesWs.class, "example-transitions.json"));
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- }
-
private static void defineBulkChangeAction(NewController controller) {
WebService.NewAction action = controller.createAction(BULK_CHANGE_ACTION)
.setDescription("Bulk change on issues. Requires authentication and User role on project(s)")
import com.google.common.collect.Maps;
import java.util.Collections;
import java.util.Map;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.user.User;
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();
- IssueService issueService;
+ IssueCommentService commentService = mock(IssueCommentService.class);
+ IssueChangelogService changelogService = mock(IssueChangelogService.class);
+ IssueBulkChangeService issueBulkChangeService = mock(IssueBulkChangeService.class);
- IssueCommentService commentService;
-
- IssueChangelogService changelogService;
-
- IssueBulkChangeService issueBulkChangeService;
-
- InternalRubyIssueService service;
-
- @Before
- public void setUp() {
- issueService = mock(IssueService.class);
- commentService = mock(IssueCommentService.class);
- changelogService = mock(IssueChangelogService.class);
- issueBulkChangeService = mock(IssueBulkChangeService.class);
- service = new InternalRubyIssueService(issueService, commentService, changelogService, issueBulkChangeService, userSessionRule);
- }
-
- @Test
- public void list_transitions_by_issue_key() {
- service.listTransitions("ABCD");
- verify(issueService).listTransitions(eq("ABCD"));
- }
+ InternalRubyIssueService underTest = new InternalRubyIssueService(commentService, changelogService, issueBulkChangeService, userSessionRule);
@Test
public void test_changelog_from_issue_key() throws Exception {
IssueChangelog changelog = new IssueChangelog(Collections.<FieldDiffs>emptyList(), Collections.<User>emptyList());
when(changelogService.changelog(eq("ABCDE"))).thenReturn(changelog);
- IssueChangelog result = service.changelog("ABCDE");
+ IssueChangelog result = underTest.changelog("ABCDE");
assertThat(result).isSameAs(changelog);
}
params.put("assign.assignee", "arthur");
params.put("set_severity.severity", "MINOR");
params.put("plan.plan", "3.7");
- service.bulkChange(params, "My comment", true);
+
+ underTest.bulkChange(params, "My comment", true);
+
verify(issueBulkChangeService).execute(any(IssueBulkChangeQuery.class), any(ThreadLocalUserSession.class));
}
ComponentDto file = newFile(project);
IssueDto issue = saveIssue(IssueTesting.newDto(rule, file, project).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE));
- List<Transition> result = service.listTransitions(issue.getKey());
+ List<Transition> result = service.listTransitions(issue.toDefaultIssue());
assertThat(result).hasSize(1);
assertThat(result.get(0).key()).isEqualTo("reopen");
}
end
end
- #
- # GET /api/issues/transitions?issue=<key>
- #
- # -- Example
- # curl -v -u admin:admin 'http://localhost:9000/api/issues/transitions?issue=9b6f89c0-3347-46f6-a6d1-dd6c761240e0'
- #
- def transitions
- require_parameters :issue
- issue_key = params[:issue]
- transitions = Internal.issues.listTransitions(issue_key)
- render :json => jsonp(
- {
- :transitions => transitions.map { |t| t.key() }
- }
- )
- end
-
#
# POST /api/issues/add_comment?issue=<key>&text=<text>
#