diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-12-14 11:27:15 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2016-12-15 14:44:17 +0100 |
commit | 154e542a066ba371691c569a9921a5a6d9e5fa58 (patch) | |
tree | 8eb6d516a8d3e48b70763616dc3f7ff38316498a /server/sonar-server | |
parent | 4377c049eab9efbf8ecb56caf1fd3c0c779a0731 (diff) | |
download | sonarqube-154e542a066ba371691c569a9921a5a6d9e5fa58.tar.gz sonarqube-154e542a066ba371691c569a9921a5a6d9e5fa58.zip |
SONAR-7292 Replace Ruby WS api/issues/add_comment
Diffstat (limited to 'server/sonar-server')
10 files changed, 310 insertions, 327 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java index 3473dd669cf..34c516b4f69 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java @@ -51,16 +51,6 @@ public class InternalRubyIssueService { this.userSession = userSession; } - public Result<IssueComment> addComment(String issueKey, String text) { - Result<IssueComment> result = Result.of(); - try { - result.set(commentService.addComment(issueKey, text)); - } catch (Exception e) { - result.addError(e.getMessage()); - } - return result; - } - public IssueComment deleteComment(String commentKey) { return commentService.deleteComment(commentKey); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueCommentService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueCommentService.java index ddb97357d3f..1cb5dbefd60 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueCommentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueCommentService.java @@ -20,91 +20,30 @@ package org.sonar.server.issue; import com.google.common.base.Strings; -import java.util.Collection; -import java.util.Date; -import java.util.List; import java.util.Objects; import org.apache.commons.lang.StringUtils; import org.sonar.api.issue.IssueComment; import org.sonar.api.utils.System2; -import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.DefaultIssueComment; -import org.sonar.core.issue.IssueChangeContext; import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.issue.IssueChangeDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.user.UserSession; -import static com.google.common.collect.Lists.newArrayList; - public class IssueCommentService { private final DbClient dbClient; private final IssueService issueService; - private final IssueFieldsSetter updater; private final UserSession userSession; - public IssueCommentService(DbClient dbClient, IssueService issueService, IssueFieldsSetter updater, UserSession userSession) { + public IssueCommentService(DbClient dbClient, IssueService issueService, UserSession userSession) { this.dbClient = dbClient; this.issueService = issueService; - this.updater = updater; this.userSession = userSession; } - public List<DefaultIssueComment> findComments(String issueKey) { - return findComments(newArrayList(issueKey)); - } - - public List<DefaultIssueComment> findComments(DbSession dbSession, String issueKey) { - return findComments(dbSession, newArrayList(issueKey)); - } - - public List<DefaultIssueComment> findComments(Collection<String> issueKeys) { - DbSession session = dbClient.openSession(false); - try { - return findComments(session, issueKeys); - } finally { - session.close(); - } - } - - public List<DefaultIssueComment> findComments(DbSession session, Collection<String> issueKeys) { - return dbClient.issueChangeDao().selectCommentsByIssues(session, issueKeys); - } - - public IssueComment findComment(String commentKey) { - return dbClient.issueChangeDao().selectCommentByKey(commentKey); - } - - public IssueComment addComment(String issueKey, String text) { - verifyLoggedIn(userSession); - if (StringUtils.isBlank(text)) { - throw new BadRequestException("Cannot add empty comments to an issue"); - } - - DbSession session = dbClient.openSession(false); - try { - DefaultIssue issue = issueService.getByKeyForUpdate(session, issueKey).toDefaultIssue(); - IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.getLogin()); - updater.addComment(issue, text, context); - - issueService.saveIssue(session, issue, context, text); - session.commit(); - - List<DefaultIssueComment> comments = findComments(issueKey); - if (comments.isEmpty()) { - throw new BadRequestException(String.format("Fail to add a comment on issue %s", issueKey)); - } - return comments.get(comments.size() - 1); - } finally { - session.close(); - } - } - public IssueComment deleteComment(String commentKey) { DefaultIssueComment comment = dbClient.issueChangeDao().selectCommentByKey(commentKey); if (comment == null) { @@ -143,10 +82,4 @@ public class IssueCommentService { return comment; } - - private void verifyLoggedIn(UserSession userSession) { - if (!userSession.isLoggedIn()) { - throw new UnauthorizedException("User is not logged in"); - } - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java new file mode 100644 index 00000000000..be614172d06 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java @@ -0,0 +1,101 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.ws; + +import java.util.Date; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.System2; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueChangeContext; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.issue.IssueDto; +import org.sonar.server.issue.IssueFieldsSetter; +import org.sonar.server.issue.IssueFinder; +import org.sonar.server.issue.IssueUpdater; +import org.sonar.server.user.UserSession; +import org.sonarqube.ws.client.issue.IssuesWsParameters; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; +import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE; +import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TEXT; + +public class AddCommentAction implements IssuesWsAction { + + private final System2 system2; + private final UserSession userSession; + private final DbClient dbClient; + private final IssueFinder issueFinder; + private final IssueUpdater issueUpdater; + private final IssueFieldsSetter issueFieldsSetter; + private final OperationResponseWriter responseWriter; + + public AddCommentAction(System2 system2, UserSession userSession, DbClient dbClient, IssueFinder issueFinder, IssueUpdater issueUpdater, IssueFieldsSetter issueFieldsSetter, + OperationResponseWriter responseWriter) { + this.system2 = system2; + this.userSession = userSession; + this.dbClient = dbClient; + this.issueFinder = issueFinder; + this.issueUpdater = issueUpdater; + this.issueFieldsSetter = issueFieldsSetter; + this.responseWriter = responseWriter; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context.createAction(IssuesWsParameters.ACTION_ADD_COMMENT) + .setDescription("Add a comment.<br/>" + + "Requires authentication and the following permission: 'Browse' on the project of the specified issue.<br/>" + + "Since 6.3, the response contains the issue with all details, not only the added comment") + .setSince("3.6") + .setHandler(this) + .setPost(true); + + action.createParam(PARAM_ISSUE) + .setDescription("Issue key") + .setRequired(true) + .setExampleValue(UUID_EXAMPLE_01); + action.createParam(PARAM_TEXT) + .setDescription("Comment text") + .setRequired(true) + .setExampleValue("Won't fix because it doesn't apply to the context"); + } + + @Override + public void handle(Request request, Response response) { + userSession.checkLoggedIn(); + String issueKey = request.mandatoryParam(PARAM_ISSUE); + String commentText = request.mandatoryParam(PARAM_TEXT); + checkArgument(!isNullOrEmpty(commentText), "Cannot add empty comment to an issue"); + try (DbSession dbSession = dbClient.openSession(false)) { + IssueDto issueDto = issueFinder.getByKey(dbSession, issueKey); + IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getLogin()); + DefaultIssue defaultIssue = issueDto.toDefaultIssue(); + issueFieldsSetter.addComment(defaultIssue, commentText, context); + issueUpdater.saveIssue(dbSession, defaultIssue, context, commentText); + responseWriter.write(issueKey, request, response); + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java index 0fe6a4bf934..da32cb2a920 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java @@ -75,7 +75,7 @@ public class DoTransitionAction implements IssuesWsAction { } @Override - public void handle(Request request, Response response) throws Exception { + public void handle(Request request, Response response) { userSession.checkLoggedIn(); String issue = request.mandatoryParam("issue"); try (DbSession dbSession = dbClient.openSession(false)) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java index 5e4050afc5c..981c162e3ff 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueWsModule.java @@ -57,6 +57,7 @@ public class IssueWsModule extends Module { SearchResponseFormat.class, OperationResponseWriter.class, WsResponseCommonFormat.class, + AddCommentAction.class, AssignAction.class, DoTransitionAction.class, SearchAction.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java index 2df191f77eb..6a79ea19c69 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java @@ -29,7 +29,6 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.CONTROLLER_ISSUES public class IssuesWs implements WebService { - 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 BULK_CHANGE_ACTION = "bulk_change"; @@ -53,29 +52,11 @@ public class IssuesWs implements WebService { } private static void defineRailsActions(NewController controller) { - defineAddCommentAction(controller); defineDeleteCommentAction(controller); defineEditCommentAction(controller); defineBulkChangeAction(controller); } - private static void defineAddCommentAction(NewController controller) { - WebService.NewAction action = controller.createAction(ADD_COMMENT_ACTION) - .setDescription("Add a comment. Requires authentication and Browse permission on project") - .setSince("3.6") - .setHandler(RailsHandler.INSTANCE) - .setPost(true); - - action.createParam("issue") - .setDescription("Key of the issue") - .setRequired(true) - .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef"); - action.createParam("text") - .setDescription("Comment") - .setExampleValue("blabla..."); - RailsHandler.addFormatParam(action); - } - private static void defineDeleteCommentAction(NewController controller) { WebService.NewAction action = controller.createAction(DELETE_COMMENT_ACTION) .setDescription("Delete a comment. Requires authentication and Browse permission on project") diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceMediumTest.java deleted file mode 100644 index 40272299207..00000000000 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceMediumTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact 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.List; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.web.UserRole; -import org.sonar.core.issue.DefaultIssueComment; -import org.sonar.core.permission.GlobalPermissions; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentDao; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ComponentTesting; -import org.sonar.db.component.SnapshotDao; -import org.sonar.db.component.SnapshotDto; -import org.sonar.db.component.SnapshotTesting; -import org.sonar.db.issue.IssueDao; -import org.sonar.db.issue.IssueDto; -import org.sonar.db.rule.RuleDao; -import org.sonar.db.rule.RuleDto; -import org.sonar.db.rule.RuleTesting; -import org.sonar.server.issue.index.IssueIndexer; -import org.sonar.server.permission.GroupPermissionChange; -import org.sonar.server.permission.PermissionChange; -import org.sonar.server.permission.PermissionUpdater; -import org.sonar.server.permission.ProjectId; -import org.sonar.server.tester.ServerTester; -import org.sonar.server.tester.UserSessionRule; -import org.sonar.server.usergroups.ws.GroupIdOrAnyone; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; - -public class IssueCommentServiceMediumTest { - - @ClassRule - public static ServerTester tester = new ServerTester().withStartupTasks().withEsIndexes(); - - @Rule - public UserSessionRule userSessionRule = UserSessionRule.forServerTester(tester); - - DbClient db; - DbSession session; - IssueCommentService service; - - RuleDto rule; - ComponentDto project; - ComponentDto file; - - @Before - public void setUp() { - tester.clearDbAndIndexes(); - db = tester.get(DbClient.class); - session = db.openSession(false); - service = tester.get(IssueCommentService.class); - - rule = RuleTesting.newXooX1(); - tester.get(RuleDao.class).insert(session, rule); - - project = ComponentTesting.newProjectDto(); - tester.get(ComponentDao.class).insert(session, project); - SnapshotDto projectSnapshot = SnapshotTesting.newAnalysis(project); - tester.get(SnapshotDao.class).insert(session, projectSnapshot); - - file = ComponentTesting.newFileDto(project, null); - tester.get(ComponentDao.class).insert(session, file); - - // project can be seen by anyone - session.commit(); - userSessionRule.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); - // TODO correctly feed default organization. Not a problem as long as issues search does not support "anyone" - // for each organization - GroupPermissionChange permissionChange = new GroupPermissionChange(PermissionChange.Operation.ADD, UserRole.USER, new ProjectId(project), GroupIdOrAnyone.forAnyone("TODO")); - tester.get(PermissionUpdater.class).apply(session, asList(permissionChange)); - - userSessionRule.login("gandalf"); - - session.commit(); - } - - @After - public void after() { - session.close(); - } - - @Test - public void add_comment() { - IssueDto issue = IssueTesting.newDto(rule, file, project); - tester.get(IssueDao.class).insert(session, issue); - session.commit(); - tester.get(IssueIndexer.class).indexAll(); - - service.addComment(issue.getKey(), "my comment"); - - List<DefaultIssueComment> comments = service.findComments(issue.getKey()); - assertThat(comments).hasSize(1); - assertThat(comments.get(0).markdownText()).isEqualTo("my comment"); - } - - @Test - public void add_comment_on_removed_issue() { - RuleDto removedRule = RuleTesting.newDto(RuleKey.of("removed", "rule")).setStatus(RuleStatus.REMOVED); - tester.get(RuleDao.class).insert(session, removedRule); - - IssueDto issue = IssueTesting.newDto(removedRule, file, project).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_REMOVED); - tester.get(IssueDao.class).insert(session, issue); - session.commit(); - tester.get(IssueIndexer.class).indexAll(); - - service.addComment(issue.getKey(), "my comment"); - - List<DefaultIssueComment> comments = service.findComments(issue.getKey()); - assertThat(comments).hasSize(1); - assertThat(comments.get(0).markdownText()).isEqualTo("my comment"); - } - -} diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceTest.java index cc84fb71ed1..fd6ccb153af 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueCommentServiceTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.issue; -import java.util.Collections; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -27,32 +26,21 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.DefaultIssueComment; -import org.sonar.core.issue.IssueChangeContext; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.component.ComponentTesting; import org.sonar.db.issue.IssueChangeDao; import org.sonar.db.issue.IssueChangeDto; -import org.sonar.db.issue.IssueDto; -import org.sonar.db.rule.RuleTesting; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; -import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.tester.UserSessionRule; -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -68,9 +56,6 @@ public class IssueCommentServiceTest { private IssueService issueService; @Mock - private IssueFieldsSetter updater; - - @Mock private IssueChangeDao changeDao; @Mock @@ -86,77 +71,7 @@ public class IssueCommentServiceTest { when(dbClient.openSession(false)).thenReturn(session); when(dbClient.issueChangeDao()).thenReturn(changeDao); - issueCommentService = new IssueCommentService(dbClient, issueService, updater, userSessionRule); - } - - @Test - public void find_comments() { - issueCommentService.findComments("ABCD"); - verify(changeDao).selectCommentsByIssues(session, newArrayList("ABCD")); - } - - @Test - public void should_find_comment() { - issueCommentService.findComment("ABCD"); - verify(changeDao).selectCommentByKey("ABCD"); - } - - @Test - public void should_add_comment() { - IssueDto issueDto = IssueTesting.newDto(RuleTesting.newXooX1().setId(500), ComponentTesting.newFileDto(ComponentTesting.newProjectDto(), null), ComponentTesting.newProjectDto()); - when(issueService.getByKeyForUpdate(session, "ABCD")).thenReturn(issueDto); - when(issueCommentService.findComments(session, "ABCD")).thenReturn(newArrayList(new DefaultIssueComment())); - - issueCommentService.addComment("ABCD", "my comment"); - - verify(updater).addComment(eq(issueDto.toDefaultIssue()), eq("my comment"), any(IssueChangeContext.class)); - verify(issueService).saveIssue(eq(session), eq(issueDto.toDefaultIssue()), any(IssueChangeContext.class), eq("my comment")); - } - - @Test - public void should_be_logged_when_adding_comment() { - throwable.expect(UnauthorizedException.class); - userSessionRule.anonymous(); - - issueCommentService.addComment("myIssue", "my comment"); - - verify(updater, never()).addComment(any(DefaultIssue.class), anyString(), any(IssueChangeContext.class)); - verifyZeroInteractions(issueService); - } - - @Test - public void should_prevent_adding_empty_comment() { - throwable.expect(BadRequestException.class); - - issueCommentService.addComment("myIssue", " "); - - verify(updater, never()).addComment(any(DefaultIssue.class), anyString(), any(IssueChangeContext.class)); - verifyZeroInteractions(issueService); - } - - @Test - public void should_prevent_adding_null_comment() { - throwable.expect(BadRequestException.class); - - issueCommentService.addComment("myIssue", null); - - verify(updater, never()).addComment(any(DefaultIssue.class), anyString(), any(IssueChangeContext.class)); - verifyZeroInteractions(issueService); - } - - @Test - public void fail_if_comment_not_inserted_in_db() { - IssueDto issueDto = IssueTesting.newDto(RuleTesting.newXooX1().setId(500), ComponentTesting.newFileDto(ComponentTesting.newProjectDto(), null), ComponentTesting.newProjectDto()); - when(issueService.getByKeyForUpdate(session, "ABCD")).thenReturn(issueDto); - // Comment has not be inserted in db - when(issueCommentService.findComments(session, "ABCD")).thenReturn(Collections.<DefaultIssueComment>emptyList()); - - try { - issueCommentService.addComment("ABCD", "my comment"); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(BadRequestException.class).hasMessage("Fail to add a comment on issue ABCD"); - } + issueCommentService = new IssueCommentService(dbClient, issueService, userSessionRule); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/AddCommentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/AddCommentActionTest.java new file mode 100644 index 00000000000..ab6198e3452 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/AddCommentActionTest.java @@ -0,0 +1,204 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.ws; + +import javax.annotation.Nullable; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.MapSettings; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.issue.IssueChangeDto; +import org.sonar.db.issue.IssueDbTester; +import org.sonar.db.issue.IssueDto; +import org.sonar.db.rule.RuleDbTester; +import org.sonar.db.rule.RuleDto; +import org.sonar.server.es.EsTester; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.exceptions.UnauthorizedException; +import org.sonar.server.issue.IssueFieldsSetter; +import org.sonar.server.issue.IssueFinder; +import org.sonar.server.issue.IssueUpdater; +import org.sonar.server.issue.ServerIssueStorage; +import org.sonar.server.issue.index.IssueIndexDefinition; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.notification.NotificationManager; +import org.sonar.server.rule.DefaultRuleFinder; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.TestResponse; +import org.sonar.server.ws.WsActionTester; + +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.sonar.api.issue.Issue.STATUS_OPEN; +import static org.sonar.api.web.UserRole.CODEVIEWER; +import static org.sonar.api.web.UserRole.USER; +import static org.sonar.core.util.Protobuf.setNullable; +import static org.sonar.db.component.ComponentTesting.newFileDto; +import static org.sonar.db.issue.IssueChangeDto.TYPE_COMMENT; +import static org.sonar.db.rule.RuleTesting.newRuleDto; +import static org.sonar.server.issue.IssueTesting.newDto; + +public class AddCommentActionTest { + + private static final long NOW = 10_000_000_000L; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public DbTester dbTester = DbTester.create(); + + @Rule + public EsTester esTester = new EsTester(new IssueIndexDefinition(new MapSettings())); + + @Rule + public UserSessionRule userSession = UserSessionRule.standalone(); + + private System2 system2 = mock(System2.class); + + private DbClient dbClient = dbTester.getDbClient(); + + private RuleDbTester ruleDbTester = new RuleDbTester(dbTester); + private IssueDbTester issueDbTester = new IssueDbTester(dbTester); + private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester); + + private IssueUpdater issueUpdater = new IssueUpdater(dbClient, + new ServerIssueStorage(new DefaultRuleFinder(dbClient), dbClient, new IssueIndexer(system2, dbClient, esTester.client())), mock(NotificationManager.class)); + private OperationResponseWriter responseWriter = mock(OperationResponseWriter.class); + + private WsActionTester tester = new WsActionTester( + new AddCommentAction(system2, userSession, dbClient, new IssueFinder(dbClient, userSession), issueUpdater, new IssueFieldsSetter(), responseWriter)); + + @Before + public void setUp() throws Exception { + when(system2.now()).thenReturn(NOW); + } + + @Test + public void add_comment() throws Exception { + IssueDto issueDto = issueDbTester.insertIssue(newIssue().setStatus(STATUS_OPEN).setResolution(null)); + userSession.login("john").addProjectUuidPermissions(USER, issueDto.getProjectUuid()); + + call(issueDto.getKey(), "please fix it"); + + verify(responseWriter).write(eq(issueDto.getKey()), any(Request.class), any(Response.class)); + IssueChangeDto issueComment = dbClient.issueChangeDao().selectByTypeAndIssueKeys(dbTester.getSession(), singletonList(issueDto.getKey()), TYPE_COMMENT).get(0); + assertThat(issueComment.getKey()).isNotNull(); + assertThat(issueComment.getUserLogin()).isEqualTo("john"); + assertThat(issueComment.getChangeType()).isEqualTo(TYPE_COMMENT); + assertThat(issueComment.getChangeData()).isEqualTo("please fix it"); + assertThat(issueComment.getCreatedAt()).isNotNull(); + assertThat(issueComment.getUpdatedAt()).isNotNull(); + assertThat(issueComment.getIssueKey()).isEqualTo(issueDto.getKey()); + assertThat(issueComment.getIssueChangeCreationDate()).isNotNull(); + + IssueDto issueReloaded = dbClient.issueDao().selectByKey(dbTester.getSession(), issueDto.getKey()).get(); + assertThat(issueReloaded.getIssueUpdateTime()).isEqualTo(NOW); + } + + @Test + public void fail_when_missing_issue_key() throws Exception { + userSession.login("john"); + + expectedException.expect(IllegalArgumentException.class); + call(null, "please fix it"); + } + + @Test + public void fail_when_issue_does_not_exist() throws Exception { + userSession.login("john"); + + expectedException.expect(NotFoundException.class); + call("ABCD", "please fix it"); + } + + @Test + public void fail_when_missing_comment_text() throws Exception { + userSession.login("john"); + + expectedException.expect(IllegalArgumentException.class); + call("ABCD", null); + } + + @Test + public void fail_when_empty_comment_text() throws Exception { + IssueDto issueDto = issueDbTester.insertIssue(newIssue().setStatus(STATUS_OPEN).setResolution(null)); + userSession.login("john").addProjectUuidPermissions(USER, issueDto.getProjectUuid()); + + expectedException.expect(IllegalArgumentException.class); + call(issueDto.getKey(), ""); + } + + @Test + public void fail_when_not_authenticated() throws Exception { + expectedException.expect(UnauthorizedException.class); + call("ABCD", "please fix it"); + } + + @Test + public void fail_when_not_enough_permission() throws Exception { + IssueDto issueDto = issueDbTester.insertIssue(newIssue().setStatus(STATUS_OPEN).setResolution(null)); + userSession.login("john").addProjectUuidPermissions(CODEVIEWER, issueDto.getProjectUuid()); + + expectedException.expect(ForbiddenException.class); + call(issueDto.getKey(), "please fix it"); + } + + @Test + public void test_definition() { + WebService.Action action = tester.getDef(); + assertThat(action.key()).isEqualTo("add_comment"); + assertThat(action.isPost()).isTrue(); + assertThat(action.isInternal()).isFalse(); + assertThat(action.params()).hasSize(2); + assertThat(action.responseExample()).isNull(); + } + + private TestResponse call(@Nullable String issueKey, @Nullable String commentText) { + TestRequest request = tester.newRequest(); + setNullable(issueKey, issue -> request.setParam("issue", issue)); + setNullable(commentText, text -> request.setParam("text", text)); + return request.execute(); + } + + private IssueDto newIssue() { + RuleDto rule = ruleDbTester.insertRule(newRuleDto()); + ComponentDto project = componentDbTester.insertProject(); + ComponentDto file = componentDbTester.insertComponent(newFileDto(project)); + return newDto(rule, file, project); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java index 6ae3ed69b16..b873b4be48c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueWsModuleTest.java @@ -29,6 +29,6 @@ public class IssueWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new IssueWsModule().configure(container); - assertThat(container.size()).isEqualTo(2 + 28); + assertThat(container.size()).isEqualTo(2 + 29); } } |