Procházet zdrojové kódy

SONAR-10134 Bringing Organization to Search Action

tags/7.0-RC1
Guillaume Jambet před 6 roky
rodič
revize
6c46890139

+ 11
- 12
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QgateProjectFinder.java Zobrazit soubor

@@ -27,6 +27,7 @@ import org.sonar.api.web.UserRole;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
import org.sonar.db.qualitygate.ProjectQgateAssociationDao;
import org.sonar.db.qualitygate.ProjectQgateAssociationDto;
@@ -52,21 +53,19 @@ public class QgateProjectFinder {
this.associationDao = dbClient.projectQgateAssociationDao();
}

public Association find(ProjectQgateAssociationQuery query) {
try (DbSession dbSession = dbClient.openSession(false)) {
getQualityGateId(dbSession, query.gateId());
List<ProjectQgateAssociationDto> projects = associationDao.selectProjects(dbSession, query);
List<ProjectQgateAssociationDto> authorizedProjects = keepAuthorizedProjects(dbSession, projects);
public Association find(DbSession dbSession, OrganizationDto organization, ProjectQgateAssociationQuery query) {
getQualityGateId(dbSession, organization, query.gateId());
List<ProjectQgateAssociationDto> projects = associationDao.selectProjects(dbSession, query);
List<ProjectQgateAssociationDto> authorizedProjects = keepAuthorizedProjects(dbSession, projects);

Paging paging = forPageIndex(query.pageIndex())
.withPageSize(query.pageSize())
.andTotal(authorizedProjects.size());
return new Association(toProjectAssociations(getPaginatedProjects(authorizedProjects, paging)), paging.hasNextPage());
}
Paging paging = forPageIndex(query.pageIndex())
.withPageSize(query.pageSize())
.andTotal(authorizedProjects.size());
return new Association(toProjectAssociations(getPaginatedProjects(authorizedProjects, paging)), paging.hasNextPage());
}

private Long getQualityGateId(DbSession dbSession, String gateId) {
return checkFound(qualitygateDao.selectById(dbSession, Long.valueOf(gateId)), "Quality gate '" + gateId + "' does not exists.").getId();
private Long getQualityGateId(DbSession dbSession, OrganizationDto organization, String gateId) {
return checkFound(qualitygateDao.selectByOrganizationAndId(dbSession, organization, Long.valueOf(gateId)), "Quality gate '" + gateId + "' does not exists.").getId();
}

private static List<ProjectQgateAssociationDto> getPaginatedProjects(List<ProjectQgateAssociationDto> projects, Paging paging) {

+ 48
- 21
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java Zobrazit soubor

@@ -23,18 +23,32 @@ import com.google.common.io.Resources;
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.server.ws.WebService.Param;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonarqube.ws.Qualitygates;

import static org.sonar.api.server.ws.WebService.Param.SELECTED;
import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.ANY;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_ID;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PAGE;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PAGE_SIZE;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_QUERY;
import static org.sonar.server.ws.WsUtils.writeProtobuf;

public class SearchAction implements QualityGatesWsAction {

private final DbClient dbClient;
private final QgateProjectFinder projectFinder;
private final QualityGatesWsSupport wsSupport;

public SearchAction(QgateProjectFinder projectFinder) {
public SearchAction(DbClient dbClient, QgateProjectFinder projectFinder, QualityGatesWsSupport wsSupport) {
this.dbClient = dbClient;
this.projectFinder = projectFinder;
this.wsSupport = wsSupport;
}

@Override
@@ -43,47 +57,60 @@ public class SearchAction implements QualityGatesWsAction {
.setDescription("Search for projects associated (or not) to a quality gate.<br/>" +
"Only authorized projects for current user will be returned.")
.setSince("4.3")
.setResponseExample(Resources.getResource(this.getClass(), "example-search.json"))
.setResponseExample(Resources.getResource(this.getClass(), "search-example.json"))
.setHandler(this);

action.createParam(QualityGatesWsParameters.PARAM_GATE_ID)
action.createParam(PARAM_GATE_ID)
.setDescription("Quality Gate ID")
.setRequired(true)
.setExampleValue("1");

action.createParam(QualityGatesWsParameters.PARAM_QUERY)
action.createParam(PARAM_QUERY)
.setDescription("To search for projects containing this string. If this parameter is set, \"selected\" is set to \"all\".")
.setExampleValue("abc");

action.addSelectionModeParam();

action.createParam(QualityGatesWsParameters.PARAM_PAGE)
action.createParam(PARAM_PAGE)
.setDescription("Page number")
.setDefaultValue("1")
.setExampleValue("2");

action.createParam(QualityGatesWsParameters.PARAM_PAGE_SIZE)
action.createParam(PARAM_PAGE_SIZE)
.setDescription("Page size")
.setExampleValue("10");

wsSupport.createOrganizationParam(action);
}

@Override
public void handle(Request request, Response response) {
QgateProjectFinder.Association associations = projectFinder.find(ProjectQgateAssociationQuery.builder()
.gateId(request.mandatoryParam(QualityGatesWsParameters.PARAM_GATE_ID))
.membership(request.param(QualityGatesWsParameters.PARAM_QUERY) == null ? request.param(Param.SELECTED) : ProjectQgateAssociationQuery.ANY)
.projectSearch(request.param(QualityGatesWsParameters.PARAM_QUERY))
.pageIndex(request.paramAsInt(QualityGatesWsParameters.PARAM_PAGE))
.pageSize(request.paramAsInt(QualityGatesWsParameters.PARAM_PAGE_SIZE))
.build());
try (JsonWriter writer = response.newJsonWriter()) {
writer.beginObject().prop("more", associations.hasMoreResults());
writer.name("results").beginArray();

try (DbSession dbSession = dbClient.openSession(false)) {

OrganizationDto organization = wsSupport.getOrganization(dbSession, request);

QgateProjectFinder.Association associations = projectFinder.find(dbSession, organization,
ProjectQgateAssociationQuery.builder()
.gateId(request.mandatoryParam(PARAM_GATE_ID))
.membership(request.param(PARAM_QUERY) == null ? request.param(SELECTED) : ANY)
.projectSearch(request.param(PARAM_QUERY))
.pageIndex(request.paramAsInt(PARAM_PAGE))
.pageSize(request.paramAsInt(PARAM_PAGE_SIZE))
.build());

Qualitygates.SearchResponse.Builder createResponse = Qualitygates.SearchResponse.newBuilder()
.setMore(associations.hasMoreResults());

for (ProjectQgateAssociation project : associations.projects()) {
writer.beginObject().prop("id", project.id()).prop("name", project.name()).prop(Param.SELECTED, project.isMember()).endObject();
createResponse.addResultsBuilder()
.setId(project.id())
.setName(project.name())
.setSelected(project.isMember());
}
writer.endArray().endObject().close();

writeProtobuf(createResponse.build(), request, response);

}
}

}

server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/example-search.json → server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/search-example.json Zobrazit soubor


+ 77
- 57
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java Zobrazit soubor

@@ -23,19 +23,16 @@ import com.google.common.base.Function;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
@@ -48,6 +45,9 @@ import org.sonar.server.tester.UserSessionRule;

import static com.google.common.collect.FluentIterable.from;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.db.component.ComponentTesting.newPublicProjectDto;
import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.IN;
import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.OUT;
import static org.sonar.db.qualitygate.ProjectQgateAssociationQuery.builder;
@@ -67,19 +67,16 @@ public class QgateProjectFinderTest {
private DbClient dbClient = dbTester.getDbClient();
private DbSession dbSession = dbTester.getSession();
private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
private QualityGateDto qGate;
private QgateProjectFinder underTest = new QgateProjectFinder(dbClient, userSession);

@Before
public void setUp() throws Exception {
qGate = new QualityGateDto().setName("Default Quality Gate").setUuid(Uuids.createFast());
dbClient.qualityGateDao().insert(dbSession, qGate);
dbTester.commit();
}

@Test
public void return_empty_association() {
Association result = underTest.find(
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();

Association result = underTest.find(dbSession, organization,
builder()
.gateId(Long.toString(qGate.getId()))
.build());
@@ -89,12 +86,17 @@ public class QgateProjectFinderTest {

@Test
public void return_all_projects() {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto associatedProject = insertProject(ComponentTesting.newPublicProjectDto(org));
ComponentDto unassociatedProject = insertProject(ComponentTesting.newPublicProjectDto(org));
associateProjectToQualitGate(associatedProject.getId());
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
ComponentDto unassociatedProject = newPublicProjectDto(organization);
dbTester.components().insertComponent(unassociatedProject);
ComponentDto associatedProject = newPublicProjectDto(organization);
dbTester.components().insertComponent(associatedProject);
associateProjectToQualitGate(associatedProject, qGate);

Association result = underTest.find(
Association result = underTest.find(dbSession, organization,
builder()
.gateId(Long.toString(qGate.getId()))
.build());
@@ -108,12 +110,18 @@ public class QgateProjectFinderTest {

@Test
public void return_only_associated_project() {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto associatedProject = insertProject(ComponentTesting.newPublicProjectDto(org));
insertProject(ComponentTesting.newPublicProjectDto(org));
associateProjectToQualitGate(associatedProject.getId());
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
ComponentDto project1 = newPublicProjectDto(organization);
dbTester.components().insertComponent(project1);
ComponentDto associatedProject = project1;
ComponentDto project = newPublicProjectDto(organization);
dbTester.components().insertComponent(project);
associateProjectToQualitGate(associatedProject, qGate);

Association result = underTest.find(
Association result = underTest.find(dbSession, organization,
builder()
.membership(IN)
.gateId(Long.toString(qGate.getId()))
@@ -126,12 +134,17 @@ public class QgateProjectFinderTest {

@Test
public void return_only_unassociated_project() {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto associatedProject = insertProject(ComponentTesting.newPublicProjectDto(org));
ComponentDto unassociatedProject = insertProject(ComponentTesting.newPublicProjectDto(org));
associateProjectToQualitGate(associatedProject.getId());
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
ComponentDto unAssociatedProject = newPublicProjectDto(organization);
dbTester.components().insertComponent(unAssociatedProject);
ComponentDto associatedProject = newPublicProjectDto(organization);
dbTester.components().insertComponent(associatedProject);
associateProjectToQualitGate(associatedProject, qGate);

Association result = underTest.find(
Association result = underTest.find(dbSession, organization,
builder()
.membership(OUT)
.gateId(Long.toString(qGate.getId()))
@@ -139,53 +152,65 @@ public class QgateProjectFinderTest {

Map<Long, ProjectQgateAssociation> projectsById = projectsById(result.projects());
assertThat(projectsById).hasSize(1);
verifyProject(projectsById.get(unassociatedProject.getId()), false, unassociatedProject.name());
verifyProject(projectsById.get(unAssociatedProject.getId()), false, unAssociatedProject.name());
}

@Test
public void return_only_authorized_projects() {
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
UserDto user = dbTester.users().insertUser("a_login");
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto project1 = componentDbTester.insertComponent(ComponentTesting.newPrivateProjectDto(organizationDto));
componentDbTester.insertComponent(ComponentTesting.newPrivateProjectDto(organizationDto));
ComponentDto project = componentDbTester.insertComponent(newPrivateProjectDto(organization));
componentDbTester.insertComponent(newPrivateProjectDto(organization));

// User can only see project 1
dbTester.users().insertProjectPermissionOnUser(user, UserRole.USER, project1);
dbTester.users().insertProjectPermissionOnUser(user, USER, project);

userSession.logIn(user.getLogin()).setUserId(user.getId());
Association result = underTest.find(
Association result = underTest.find(dbSession, organization,
builder()
.gateId(Long.toString(qGate.getId()))
.build());

verifyProjects(result, project1.getId());
verifyProjects(result, project.getId());
}

@Test
public void do_not_verify_permissions_if_user_is_root() {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto project = componentDbTester.insertPrivateProject(org);
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
ComponentDto project = componentDbTester.insertPrivateProject(organization);
ProjectQgateAssociationQuery query = builder()
.gateId(Long.toString(qGate.getId()))
.build();

userSession.logIn().setNonRoot();
verifyProjects(underTest.find(query));
verifyProjects(underTest.find(dbSession, organization, query));

userSession.logIn().setRoot();
verifyProjects(underTest.find(query), project.getId());
verifyProjects(underTest.find(dbSession, organization, query), project.getId());
}

@Test
public void test_paging() throws Exception {
OrganizationDto org = dbTester.organizations().insert();
ComponentDto project1 = insertProject(ComponentTesting.newPublicProjectDto(org).setName("Project 1"));
ComponentDto project2 = insertProject(ComponentTesting.newPublicProjectDto(org).setName("Project 2"));
ComponentDto project3 = insertProject(ComponentTesting.newPublicProjectDto(org).setName("Project 3"));
associateProjectToQualitGate(project1.getId());
OrganizationDto organization = dbTester.organizations().insert();
QualityGateDto qGate = dbTester.qualityGates().insertQualityGate(organization,
qualityGateDto -> qualityGateDto.setName("Default Quality Gate").setUuid(Uuids.createFast()));
dbTester.commit();
ComponentDto project1 = newPublicProjectDto(organization).setName("Project 1");
dbTester.components().insertComponent(project1);
associateProjectToQualitGate(project1, qGate);
ComponentDto project2 = newPublicProjectDto(organization).setName("Project 2");
dbTester.components().insertComponent(project2);
ComponentDto project3 = newPublicProjectDto(organization).setName("Project 3");
dbTester.components().insertComponent(project3);

// Return partial result on first page
verifyPaging(underTest.find(
verifyPaging(underTest.find(dbSession, organization,
builder().gateId(Long.toString(qGate.getId()))
.pageIndex(1)
.pageSize(1)
@@ -193,7 +218,7 @@ public class QgateProjectFinderTest {
true, project1.getId());

// Return partial result on second page
verifyPaging(underTest.find(
verifyPaging(underTest.find(dbSession, organization,
builder().gateId(Long.toString(qGate.getId()))
.pageIndex(2)
.pageSize(1)
@@ -201,7 +226,7 @@ public class QgateProjectFinderTest {
true, project2.getId());

// Return partial result on first page
verifyPaging(underTest.find(
verifyPaging(underTest.find(dbSession, organization,
builder().gateId(Long.toString(qGate.getId()))
.pageIndex(1)
.pageSize(2)
@@ -209,7 +234,7 @@ public class QgateProjectFinderTest {
true, project1.getId(), project2.getId());

// Return all result on first page
verifyPaging(underTest.find(
verifyPaging(underTest.find(dbSession, organization,
builder().gateId(Long.toString(qGate.getId()))
.pageIndex(1)
.pageSize(3)
@@ -217,7 +242,7 @@ public class QgateProjectFinderTest {
false, project1.getId(), project2.getId(), project3.getId());

// Return no result as page index is off limit
verifyPaging(underTest.find(
verifyPaging(underTest.find(dbSession, organization,
builder().gateId(Long.toString(qGate.getId()))
.pageIndex(3)
.pageSize(3)
@@ -228,7 +253,7 @@ public class QgateProjectFinderTest {
@Test
public void fail_on_unknown_quality_gate() {
expectedException.expect(NotFoundException.class);
underTest.find(builder().gateId("123").build());
underTest.find(dbSession, dbTester.organizations().insert(), builder().gateId("123").build());
}

private void verifyProject(ProjectQgateAssociation project, boolean expectedMembership, String expectedName) {
@@ -245,19 +270,14 @@ public class QgateProjectFinderTest {
assertThat(association.projects()).extracting("id").containsOnly(expectedProjectIds);
}

private void associateProjectToQualitGate(long projectId) {
private void associateProjectToQualitGate(ComponentDto component, QualityGateDto qualityGate) {
dbClient.propertiesDao().saveProperty(
new PropertyDto().setKey(SONAR_QUALITYGATE_PROPERTY)
.setResourceId(projectId)
.setValue(Long.toString(qGate.getId())));
.setResourceId(component.getId())
.setValue(Long.toString(qualityGate.getId())));
dbTester.commit();
}

private ComponentDto insertProject(ComponentDto project) {
dbTester.components().insertComponent(project);
return project;
}

private static Map<Long, ProjectQgateAssociation> projectsById(List<ProjectQgateAssociation> projects) {
return from(projects).uniqueIndex(ProjectToId.INSTANCE);
}

+ 0
- 148
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java Zobrazit soubor

@@ -1,148 +0,0 @@
/*
* 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.qualitygate.ws;

import com.google.common.collect.ImmutableList;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.WebService.Action;
import org.sonar.api.server.ws.WebService.Controller;
import org.sonar.db.qualitygate.ProjectQgateAssociation;
import org.sonar.db.qualitygate.ProjectQgateAssociationQuery;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QgateProjectFinder.Association;
import org.sonar.server.qualitygate.QualityGates;
import org.sonar.server.ws.RemovedWebServiceHandler;
import org.sonar.server.ws.WsTester;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

// TODO split testcases in action tests
// TODO restore
@RunWith(MockitoJUnitRunner.class)
@Ignore
public class QualityGatesWsTest {

@Mock
private QualityGates qGates;

@Mock
private QgateProjectFinder projectFinder;

WsTester tester;

@Before
public void setUp() {
tester = new WsTester(new QualityGatesWs(
new SearchAction(projectFinder),
new CreateAction(null, null, null, null),
new SetAsDefaultAction(qGates)));
}

@Test
public void define_ws() {
Controller controller = tester.controller("api/qualitygates");
assertThat(controller).isNotNull();
assertThat(controller.path()).isEqualTo("api/qualitygates");
assertThat(controller.description()).isNotEmpty();
assertThat(controller.actions()).hasSize(6);

Action setDefault = controller.action("set_as_default");
assertThat(setDefault).isNotNull();
assertThat(setDefault.handler()).isNotNull();
assertThat(setDefault.since()).isEqualTo("4.3");
assertThat(setDefault.isPost()).isTrue();
assertThat(setDefault.param("id")).isNotNull();
assertThat(setDefault.isInternal()).isFalse();

Action unsetDefault = controller.action("unset_default");
assertThat(unsetDefault).isNotNull();
assertThat(unsetDefault.handler()).isNotNull();
assertThat(unsetDefault.since()).isEqualTo("4.3");
assertThat(unsetDefault.deprecatedSince()).isEqualTo("7.0");
assertThat(unsetDefault.changelog())
.extracting(Change::getVersion, Change::getDescription)
.containsOnly(
tuple("7.0", "Unset a quality gate is no more authorized"));
assertThat(unsetDefault.isPost()).isTrue();
assertThat(unsetDefault.handler()).isEqualTo(RemovedWebServiceHandler.INSTANCE);
assertThat(unsetDefault.responseExample()).isEqualTo(RemovedWebServiceHandler.INSTANCE.getResponseExample());
assertThat(unsetDefault.isInternal()).isFalse();
}

@Test
public void search_with_query() throws Exception {
long gateId = 12345L;
Association assoc = mock(Association.class);
when(assoc.hasMoreResults()).thenReturn(true);
List<ProjectQgateAssociation> projects = ImmutableList.of(
new ProjectQgateAssociation().setId(42L).setName("Project One").setMember(false),
new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true));
when(assoc.projects()).thenReturn(projects);
when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);

tester.newGetRequest("api/qualitygates", "search")
.setParam("gateId", Long.toString(gateId))
.setParam("query", "Project")
.execute()
.assertJson("{\"more\":true,\"results\":["
+ "{\"id\":42,\"name\":\"Project One\",\"selected\":false},"
+ "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
+ "]}");
ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
verify(projectFinder).find(queryCaptor.capture());
ProjectQgateAssociationQuery query = queryCaptor.getValue();
assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.ANY);
}

@Test
public void search_nominal() throws Exception {
long gateId = 12345L;
Association assoc = mock(Association.class);
when(assoc.hasMoreResults()).thenReturn(true);
List<ProjectQgateAssociation> projects = ImmutableList.of(
new ProjectQgateAssociation().setId(24L).setName("Project Two").setMember(true));
when(assoc.projects()).thenReturn(projects);
when(projectFinder.find(any(ProjectQgateAssociationQuery.class))).thenReturn(assoc);

tester.newGetRequest("api/qualitygates", "search")
.setParam("gateId", Long.toString(gateId))
.execute()
.assertJson("{\"more\":true,\"results\":["
+ "{\"id\":24,\"name\":\"Project Two\",\"selected\":true}"
+ "]}");
ArgumentCaptor<ProjectQgateAssociationQuery> queryCaptor = ArgumentCaptor.forClass(ProjectQgateAssociationQuery.class);
verify(projectFinder).find(queryCaptor.capture());
ProjectQgateAssociationQuery query = queryCaptor.getValue();
assertThat(query.membership()).isEqualTo(ProjectQgateAssociationQuery.IN);
}
}

+ 177
- 0
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SearchActionTest.java Zobrazit soubor

@@ -0,0 +1,177 @@
/*
* 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.qualitygate.ws;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.server.ws.WebService;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.Qualitygates.SearchResponse;

import static java.lang.String.format;
import static java.lang.String.valueOf;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.tuple;
import static org.sonar.api.utils.System2.INSTANCE;
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_GATES;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_GATE_ID;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_ORGANIZATION;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PAGE;
import static org.sonar.server.qualitygate.ws.QualityGatesWsParameters.PARAM_PAGE_SIZE;

public class SearchActionTest {

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Rule
public UserSessionRule userSession = UserSessionRule.standalone();

@Rule
public DbTester db = DbTester.create(INSTANCE);

private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);

private QgateProjectFinder projectFinder = new QgateProjectFinder(dbClient, userSession);
private QualityGatesWsSupport wsSupport = new QualityGatesWsSupport(dbClient, userSession, defaultOrganizationProvider);

private SearchAction underTest = new SearchAction(dbClient, projectFinder, wsSupport);
private WsActionTester ws = new WsActionTester(underTest);

@Test
public void definition() {
WebService.Action action = ws.getDef();

assertThat(action).isNotNull();
assertThat(action.isInternal()).isFalse();
assertThat(action.isPost()).isFalse();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.params())
.extracting(WebService.Param::key, WebService.Param::isRequired)
.containsExactlyInAnyOrder(
tuple("gateId", true),
tuple("query", false),
tuple("organization", false),
tuple("selected", false),
tuple("page", false),
tuple("pageSize", false));
}

@Test
public void search_projects_of_a_quality_gate_from_an_organization() {
OrganizationDto organization = db.organizations().insert();
ComponentDto project = db.components().insertPublicProject(organization);
QualityGateDto qualityGate = db.qualityGates().insertQualityGate(organization);
associateProjectToQualityGate(project, qualityGate);
userSession.addPermission(ADMINISTER_QUALITY_GATES, organization);

SearchResponse response = ws.newRequest()
.setParam(PARAM_GATE_ID, valueOf(qualityGate.getId()))
.setParam(PARAM_ORGANIZATION, valueOf(organization.getKey()))
.executeProtobuf(SearchResponse.class);

assertThat(response).isNotNull();
assertThat(response.getMore()).isFalse();
assertThat(response.getResultsCount()).isEqualTo(1);
assertThat(response.getResults(0).getId()).isEqualTo(project.getId());
assertThat(response.getResults(0).getName().substring(4)).isEqualTo(project.getKey().substring(3));
}

@Test
public void search_on_default_organization_when_none_is_provided() {
OrganizationDto defaultOrganization = db.getDefaultOrganization();

ComponentDto project = db.components().insertPublicProject(defaultOrganization);
QualityGateDto qualityGate = db.qualityGates().insertQualityGate(defaultOrganization);
associateProjectToQualityGate(project, qualityGate);
userSession.addPermission(ADMINISTER_QUALITY_GATES, defaultOrganization);

SearchResponse response = ws.newRequest()
.setParam(PARAM_GATE_ID, valueOf(qualityGate.getId()))
.executeProtobuf(SearchResponse.class);

assertThat(response).isNotNull();
assertThat(response.getMore()).isFalse();
assertThat(response.getResultsCount()).isEqualTo(1);
assertThat(response.getResults(0).getId()).isEqualTo(project.getId());
assertThat(response.getResults(0).getName().substring(4)).isEqualTo(project.getKey().substring(3));
}

@Test
public void fail_when_quality_gates_does_not_belong_to_organization() {
OrganizationDto organization = db.organizations().insert();
OrganizationDto otherOrganization = db.organizations().insert();
QualityGateDto qualityGate = db.qualityGates().insertQualityGate(otherOrganization);

expectedException.expect(NotFoundException.class);
expectedException.expectMessage(format("Quality gate '%s' does not exists.", qualityGate.getId()));

ws.newRequest()
.setParam(PARAM_GATE_ID, valueOf(qualityGate.getId()))
.setParam(PARAM_ORGANIZATION, valueOf(organization.getKey()))
.executeProtobuf(SearchResponse.class);

}

@Test
public void more_is_true_when_not_all_project_fit_in_page_size() {
OrganizationDto organization = db.organizations().insert();
QualityGateDto qualityGate = db.qualityGates().insertQualityGate(organization);
for (int i = 0; i < 20; i++) {
ComponentDto project1 = db.components().insertPublicProject();
associateProjectToQualityGate(project1, qualityGate);
}

userSession.addPermission(ADMINISTER_QUALITY_GATES, organization);

SearchResponse response = ws.newRequest()
.setParam(PARAM_GATE_ID, valueOf(qualityGate.getId()))
.setParam(PARAM_ORGANIZATION, valueOf(organization.getKey()))
.setParam(PARAM_PAGE_SIZE, valueOf(10))
.setParam(PARAM_PAGE, valueOf(1))
.executeProtobuf(SearchResponse.class);

assertThat(response).isNotNull();
assertThat(response.getMore()).isTrue();
assertThat(response.getResultsCount()).isEqualTo(10);
}

private void associateProjectToQualityGate(ComponentDto componentDto, QualityGateDto qualityGateDto) {
dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
.setKey("sonar.qualitygate")
.setResourceId(componentDto.getId())
.setValue(valueOf(qualityGateDto.getId())));
db.commit();
}
}

+ 12
- 0
sonar-ws/src/main/protobuf/ws-qualitygates.proto Zobrazit soubor

@@ -136,6 +136,18 @@ message ShowWsResponse {
}
}

// GET api/qualitygates/search
message SearchResponse {
optional bool more = 1;
repeated Result results = 2;

message Result {
optional int64 id = 1;
optional string name = 2;
optional bool selected = 3;
}
}

// GET api/qualitygates/list
message ListWsResponse {
repeated QualityGate qualitygates = 1;

Načítá se…
Zrušit
Uložit