/* * SonarQube * Copyright (C) 2009-2017 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.projecttag.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.server.ws.WebService; import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; import org.sonar.server.component.ComponentFinder; import org.sonar.server.es.ProjectIndexer; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; 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.net.HttpURLConnection.HTTP_NO_CONTENT; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.sonar.core.util.Protobuf.setNullable; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.server.es.ProjectIndexer.Cause.PROJECT_TAGS_UPDATE; public class SetActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Rule public UserSessionRule userSession = UserSessionRule.standalone().logIn().setRoot(); @Rule public DbTester db = DbTester.create(); private DbClient dbClient = db.getDbClient(); private DbSession dbSession = db.getSession(); private ComponentDto project; private ProjectIndexer indexer = mock(ProjectIndexer.class); private WsActionTester ws = new WsActionTester(new SetAction(dbClient, new ComponentFinder(dbClient), userSession, singletonList(indexer))); @Before public void setUp() { project = db.components().insertPrivateProject(); } @Test public void set_tags_exclude_empty_and_blank_values() { TestResponse response = call(project.key(), "finance , offshore, platform, ,"); assertTags(project.key(), "finance", "offshore", "platform"); verify(indexer).indexProject(project.uuid(), PROJECT_TAGS_UPDATE); assertThat(response.getStatus()).isEqualTo(HTTP_NO_CONTENT); } @Test public void reset_tags() { project = db.components().insertPrivateProject(p -> p.setTagsString("platform,scanner")); call(project.key(), ""); assertNoTags(project.key()); } @Test public void override_existing_tags() { project = db.components().insertPrivateProject(p -> p.setTagsString("marketing,languages")); call(project.key(), "finance,offshore,platform"); assertTags(project.key(), "finance", "offshore", "platform"); } @Test public void set_tags_as_project_admin() { userSession.logIn().addProjectPermission(UserRole.ADMIN, project); call(project.key(), "platform, lambda"); assertTags(project.key(), "platform", "lambda"); } @Test public void do_not_duplicate_tags() { call(project.key(), "atlas, atlas, atlas"); assertTags(project.key(), "atlas"); } @Test public void fail_if_tag_does_not_respect_format() { expectedException.expect(BadRequestException.class); expectedException.expectMessage("_finance_' is invalid. Project tags accept only the characters: a-z, 0-9, '+', '-', '#', '.'"); call(project.key(), "_finance_"); } @Test public void fail_if_not_project_admin() { userSession.logIn().addProjectPermission(UserRole.USER, project); expectedException.expect(ForbiddenException.class); call(project.key(), "platform"); } @Test public void fail_if_no_project() { expectedException.expect(IllegalArgumentException.class); call(null, "platform"); } @Test public void fail_if_no_tags() { expectedException.expect(IllegalArgumentException.class); call(project.key(), null); } @Test public void fail_if_component_is_a_view() { ComponentDto view = db.components().insertView(v -> v.setKey("VIEW_KEY")); expectedException.expect(BadRequestException.class); expectedException.expectMessage("Component 'VIEW_KEY' is not a project"); call(view.key(), "point-of-view"); } @Test public void fail_if_component_is_a_module() { ComponentDto module = db.components().insertComponent(newModuleDto(project).setKey("MODULE_KEY")); expectedException.expect(BadRequestException.class); expectedException.expectMessage("Component 'MODULE_KEY' is not a project"); call(module.key(), "modz"); } @Test public void fail_if_component_is_a_file() { ComponentDto file = db.components().insertComponent(newFileDto(project).setKey("FILE_KEY")); expectedException.expect(BadRequestException.class); expectedException.expectMessage("Component 'FILE_KEY' is not a project"); call(file.getKey(), "secret"); } @Test public void definition() { WebService.Action definition = ws.getDef(); assertThat(definition.isPost()).isTrue(); assertThat(definition.isInternal()).isFalse(); assertThat(definition.params()).extracting(WebService.Param::key) .containsOnly("project", "tags"); assertThat(definition.description()).isNotEmpty(); assertThat(definition.since()).isEqualTo("6.4"); } private TestResponse call(@Nullable String projectKey, @Nullable String tags) { TestRequest request = ws.newRequest(); setNullable(projectKey, p -> request.setParam("project", p)); setNullable(tags, t -> request.setParam("tags", tags)); return request.execute(); } private void assertTags(String projectKey, String... tags) { assertThat(dbClient.componentDao().selectOrFailByKey(dbSession, projectKey).getTags()).containsExactlyInAnyOrder(tags); } private void assertNoTags(String projectKey) { assertThat(dbClient.componentDao().selectOrFailByKey(dbSession, projectKey).getTags()).isEmpty(); } }