import org.sonar.server.view.index.ViewIndexDefinition;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
+import static java.util.Collections.emptyList;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
*/
public class IssueIndex {
- private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";
-
public static final List<String> SUPPORTED_FACETS = ImmutableList.of(
PARAM_SEVERITIES,
PARAM_STATUSES,
PARAM_TAGS,
PARAM_TYPES,
PARAM_CREATED_AT);
-
+ public static final String AGGREGATION_NAME_FOR_TAGS = "tags__issues";
+ private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";
// TODO to be documented
// TODO move to Facets ?
private static final String FACET_SUFFIX_MISSING = "_missing";
-
private static final String IS_ASSIGNED_FILTER = "__isAssigned";
-
private static final SumBuilder EFFORT_AGGREGATION = AggregationBuilders.sum(FACET_MODE_EFFORT).field(IssueIndexDefinition.FIELD_ISSUE_EFFORT);
private static final Order EFFORT_AGGREGATION_ORDER = Order.aggregation(FACET_MODE_EFFORT, false);
-
private static final int DEFAULT_FACET_SIZE = 15;
private static final Duration TWENTY_DAYS = Duration.standardDays(20L);
private static final Duration TWENTY_WEEKS = Duration.standardDays(20L * 7L);
private static final Duration TWENTY_MONTHS = Duration.standardDays(20L * 30L);
-
- public static final String AGGREGATION_NAME_FOR_TAGS = "tags__issues";
-
private final Sorting sorting;
private final EsClient client;
private final System2 system;
this.sorting.addDefault(IssueIndexDefinition.FIELD_ISSUE_KEY);
}
+ /**
+ * Optimization - do not send ES request to all shards when scope is restricted
+ * to a set of projects. Because project UUID is used for routing, the request
+ * can be sent to only the shards containing the specified projects.
+ * Note that sticky facets may involve all projects, so this optimization must be
+ * disabled when facets are enabled.
+ */
+ private static void configureRouting(IssueQuery query, SearchOptions options, SearchRequestBuilder requestBuilder) {
+ Collection<String> uuids = query.projectUuids();
+ if (!uuids.isEmpty() && options.getFacets().isEmpty()) {
+ requestBuilder.setRouting(uuids.toArray(new String[uuids.size()]));
+ }
+ }
+
+ private static void configurePagination(SearchOptions options, SearchRequestBuilder esSearch) {
+ esSearch.setFrom(options.getOffset()).setSize(options.getLimit());
+ }
+
+ private static void addComponentRelatedFilters(IssueQuery query, Map<String, QueryBuilder> filters) {
+ QueryBuilder viewFilter = createViewFilter(query.viewUuids());
+ QueryBuilder componentFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
+ QueryBuilder projectFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids());
+ QueryBuilder moduleRootFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, query.moduleRootUuids());
+ QueryBuilder moduleFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids());
+ QueryBuilder directoryFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories());
+ QueryBuilder fileFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());
+
+ if (BooleanUtils.isTrue(query.onComponentOnly())) {
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
+ } else {
+ filters.put("__view", viewFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter);
+ filters.put("__module", moduleRootFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
+ if (fileFilter != null) {
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
+ } else {
+ filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
+ }
+ }
+ }
+
+ @CheckForNull
+ private static QueryBuilder createViewFilter(Collection<String> viewUuids) {
+ if (viewUuids.isEmpty()) {
+ return null;
+ }
+
+ BoolQueryBuilder viewsFilter = boolQuery();
+ for (String viewUuid : viewUuids) {
+ viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)
+ .lookupIndex(ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex())
+ .lookupType(ViewIndexDefinition.INDEX_TYPE_VIEW.getType())
+ .lookupId(viewUuid)
+ .lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
+ }
+ return viewsFilter;
+ }
+
+ private static StickyFacetBuilder newStickyFacetBuilder(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
+ if (hasQueryEffortFacet(query)) {
+ return new StickyFacetBuilder(esQuery, filters, EFFORT_AGGREGATION, EFFORT_AGGREGATION_ORDER);
+ }
+ return new StickyFacetBuilder(esQuery, filters);
+ }
+
+ private static void addSimpleStickyFacetIfNeeded(SearchOptions options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch,
+ String facetName, String fieldName, Object... selectedValues) {
+ if (options.getFacets().contains(facetName)) {
+ esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_FACET_SIZE, selectedValues));
+ }
+ }
+
+ private static AggregationBuilder addEffortAggregationIfNeeded(IssueQuery query, AggregationBuilder aggregation) {
+ if (hasQueryEffortFacet(query)) {
+ aggregation.subAggregation(EFFORT_AGGREGATION);
+ }
+ return aggregation;
+ }
+
+ private static boolean hasQueryEffortFacet(IssueQuery query) {
+ return FACET_MODE_EFFORT.equals(query.facetMode()) || DEPRECATED_FACET_MODE_DEBT.equals(query.facetMode());
+ }
+
+ private static AggregationBuilder createAssigneesFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
+ String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
+ String facetName = PARAM_ASSIGNEES;
+
+ // Same as in super.stickyFacetBuilder
+ Map<String, QueryBuilder> assigneeFilters = Maps.newHashMap(filters);
+ assigneeFilters.remove(IS_ASSIGNED_FILTER);
+ assigneeFilters.remove(fieldName);
+ StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, assigneeFilters, queryBuilder);
+ BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
+ FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
+
+ Collection<String> assigneesEscaped = escapeValuesForFacetInclusion(query.assignees());
+ if (!assigneesEscaped.isEmpty()) {
+ facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t, assigneesEscaped.toArray());
+ }
+
+ // Add missing facet for unassigned issues
+ facetTopAggregation.subAggregation(
+ addEffortAggregationIfNeeded(query, AggregationBuilders
+ .missing(facetName + FACET_SUFFIX_MISSING)
+ .field(fieldName)));
+
+ return AggregationBuilders
+ .global(facetName)
+ .subAggregation(facetTopAggregation);
+ }
+
+ private static Collection<String> escapeValuesForFacetInclusion(@Nullable Collection<String> values) {
+ if (values == null) {
+ return Collections.emptyList();
+ }
+ return values.stream().map(Pattern::quote).collect(MoreCollectors.toArrayList(values.size()));
+ }
+
+ private static AggregationBuilder createResolutionFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
+ String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
+ String facetName = PARAM_RESOLUTIONS;
+
+ // Same as in super.stickyFacetBuilder
+ Map<String, QueryBuilder> resolutionFilters = Maps.newHashMap(filters);
+ resolutionFilters.remove("__isResolved");
+ resolutionFilters.remove(fieldName);
+ StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, resolutionFilters, esQuery);
+ BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
+ FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
+ facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t);
+
+ // Add missing facet for unresolved issues
+ facetTopAggregation.subAggregation(
+ addEffortAggregationIfNeeded(query, AggregationBuilders
+ .missing(facetName + FACET_SUFFIX_MISSING)
+ .field(fieldName)));
+
+ return AggregationBuilders
+ .global(facetName)
+ .subAggregation(facetTopAggregation);
+ }
+
+ @CheckForNull
+ private static QueryBuilder createTermsFilter(String field, Collection<?> values) {
+ return values.isEmpty() ? null : termsQuery(field, values);
+ }
+
+ @CheckForNull
+ private static QueryBuilder createTermFilter(String field, @Nullable String value) {
+ return value == null ? null : termQuery(field, value);
+ }
+
public SearchResponse search(IssueQuery query, SearchOptions options) {
SearchRequestBuilder requestBuilder = client.prepareSearch(INDEX_TYPE_ISSUE);
return requestBuilder.get();
}
- /**
- * Optimization - do not send ES request to all shards when scope is restricted
- * to a set of projects. Because project UUID is used for routing, the request
- * can be sent to only the shards containing the specified projects.
- * Note that sticky facets may involve all projects, so this optimization must be
- * disabled when facets are enabled.
- */
- private static void configureRouting(IssueQuery query, SearchOptions options, SearchRequestBuilder requestBuilder) {
- Collection<String> uuids = query.projectUuids();
- if (!uuids.isEmpty() && options.getFacets().isEmpty()) {
- requestBuilder.setRouting(uuids.toArray(new String[uuids.size()]));
- }
- }
-
private void configureSorting(IssueQuery query, SearchRequestBuilder esRequest) {
String sortField = query.sort();
if (sortField != null) {
}
}
- private static void configurePagination(SearchOptions options, SearchRequestBuilder esSearch) {
- esSearch.setFrom(options.getOffset()).setSize(options.getLimit());
- }
-
private Map<String, QueryBuilder> createFilters(IssueQuery query) {
Map<String, QueryBuilder> filters = new HashMap<>();
filters.put("__authorization", createAuthorizationFilter(query.checkAuthorization()));
return filters;
}
- private static void addComponentRelatedFilters(IssueQuery query, Map<String, QueryBuilder> filters) {
- QueryBuilder viewFilter = createViewFilter(query.viewUuids());
- QueryBuilder componentFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
- QueryBuilder projectFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids());
- QueryBuilder moduleRootFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, query.moduleRootUuids());
- QueryBuilder moduleFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids());
- QueryBuilder directoryFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories());
- QueryBuilder fileFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());
-
- if (BooleanUtils.isTrue(query.onComponentOnly())) {
- filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
- } else {
- filters.put("__view", viewFilter);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter);
- filters.put("__module", moduleRootFilter);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
- filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
- if (fileFilter != null) {
- filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
- } else {
- filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
- }
- }
- }
-
- @CheckForNull
- private static QueryBuilder createViewFilter(Collection<String> viewUuids) {
- if (viewUuids.isEmpty()) {
- return null;
- }
-
- BoolQueryBuilder viewsFilter = boolQuery();
- for (String viewUuid : viewUuids) {
- viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)
- .lookupIndex(ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex())
- .lookupType(ViewIndexDefinition.INDEX_TYPE_VIEW.getType())
- .lookupId(viewUuid)
- .lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
- }
- return viewsFilter;
- }
-
private QueryBuilder createAuthorizationFilter(boolean checkAuthorization) {
if (checkAuthorization) {
return authorizationTypeSupport.createQueryFilter();
}
}
- private static StickyFacetBuilder newStickyFacetBuilder(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
- if (hasQueryEffortFacet(query)) {
- return new StickyFacetBuilder(esQuery, filters, EFFORT_AGGREGATION, EFFORT_AGGREGATION_ORDER);
- }
- return new StickyFacetBuilder(esQuery, filters);
- }
-
- private static void addSimpleStickyFacetIfNeeded(SearchOptions options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch,
- String facetName, String fieldName, Object... selectedValues) {
- if (options.getFacets().contains(facetName)) {
- esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_FACET_SIZE, selectedValues));
- }
- }
-
- private static AggregationBuilder addEffortAggregationIfNeeded(IssueQuery query, AggregationBuilder aggregation) {
- if (hasQueryEffortFacet(query)) {
- aggregation.subAggregation(EFFORT_AGGREGATION);
- }
- return aggregation;
- }
-
- private static boolean hasQueryEffortFacet(IssueQuery query) {
- return FACET_MODE_EFFORT.equals(query.facetMode()) || DEPRECATED_FACET_MODE_DEBT.equals(query.facetMode());
- }
-
private Optional<AggregationBuilder> getCreatedAtFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
long startTime;
Date createdAfter = query.createdAfter();
return Optional.of(actualValue.longValue());
}
- private static AggregationBuilder createAssigneesFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
- String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
- String facetName = PARAM_ASSIGNEES;
-
- // Same as in super.stickyFacetBuilder
- Map<String, QueryBuilder> assigneeFilters = Maps.newHashMap(filters);
- assigneeFilters.remove(IS_ASSIGNED_FILTER);
- assigneeFilters.remove(fieldName);
- StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, assigneeFilters, queryBuilder);
- BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
- FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
-
- Collection<String> assigneesEscaped = escapeValuesForFacetInclusion(query.assignees());
- if (!assigneesEscaped.isEmpty()) {
- facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t, assigneesEscaped.toArray());
- }
-
- // Add missing facet for unassigned issues
- facetTopAggregation.subAggregation(
- addEffortAggregationIfNeeded(query, AggregationBuilders
- .missing(facetName + FACET_SUFFIX_MISSING)
- .field(fieldName)));
-
- return AggregationBuilders
- .global(facetName)
- .subAggregation(facetTopAggregation);
- }
-
- private static Collection<String> escapeValuesForFacetInclusion(@Nullable Collection<String> values) {
- if (values == null) {
- return Collections.emptyList();
- }
- return values.stream().map(Pattern::quote).collect(MoreCollectors.toArrayList(values.size()));
- }
-
private void addAssignedToMeFacetIfNeeded(SearchRequestBuilder builder, SearchOptions options, IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
String login = userSession.getLogin();
.subAggregation(facetTopAggregation));
}
- private static AggregationBuilder createResolutionFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
- String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
- String facetName = PARAM_RESOLUTIONS;
-
- // Same as in super.stickyFacetBuilder
- Map<String, QueryBuilder> resolutionFilters = Maps.newHashMap(filters);
- resolutionFilters.remove("__isResolved");
- resolutionFilters.remove(fieldName);
- StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, resolutionFilters, esQuery);
- BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
- FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
- facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t);
-
- // Add missing facet for unresolved issues
- facetTopAggregation.subAggregation(
- addEffortAggregationIfNeeded(query, AggregationBuilders
- .missing(facetName + FACET_SUFFIX_MISSING)
- .field(fieldName)));
-
- return AggregationBuilders
- .global(facetName)
- .subAggregation(facetTopAggregation);
- }
-
- @CheckForNull
- private static QueryBuilder createTermsFilter(String field, Collection<?> values) {
- return values.isEmpty() ? null : termsQuery(field, values);
- }
-
- @CheckForNull
- private static QueryBuilder createTermFilter(String field, @Nullable String value) {
- return value == null ? null : termQuery(field, value);
- }
+ public List<String> listTags(OrganizationDto organization, @Nullable String textQuery, int size) {
+ int maxPageSize = 500;
+ checkArgument(size <= maxPageSize, "Page size must be lower than or equals to " + maxPageSize);
+ if (size <= 0) {
+ return emptyList();
+ }
- public List<String> listTags(OrganizationDto organization, @Nullable String textQuery, int maxNumberOfTags) {
SearchRequestBuilder requestBuilder = client
.prepareSearch(INDEX_TYPE_ISSUE)
.setQuery(boolQuery()
TermsBuilder termsAggregation = AggregationBuilders.terms(AGGREGATION_NAME_FOR_TAGS)
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
- .size(maxNumberOfTags)
+ .size(size)
.order(Terms.Order.term(true))
.minDocCount(1L);
if (textQuery != null) {
private IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSession, new AuthorizationTypeSupport(userSession));
private RuleIndex ruleIndex = new RuleIndex(esTester.client());
- private WsActionTester tester = new WsActionTester(new TagsAction(issueIndex, ruleIndex, dbTester.getDbClient(), TestDefaultOrganizationProvider.from(dbTester)));
+ private WsActionTester ws = new WsActionTester(new TagsAction(issueIndex, ruleIndex, dbTester.getDbClient(), TestDefaultOrganizationProvider.from(dbTester)));
private OrganizationDto organization;
@Before
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4", "tag5");
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]}");
dbTester.rules().insertOrUpdateMetadata(r2, organization, setTags("tag4", "tag5"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r2.getKey(), organization);
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]}");
dbTester.rules().insertOrUpdateMetadata(r, organization, setTags("tag7"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r.getKey(), organization);
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\", \"tag6\", \"tag7\"]}");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4", "tag5");
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("ps", "2")
.setParam("organization", organization.getKey())
.execute().getInput();
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag12", "tag4", "tag5");
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("q", "ag1")
.setParam("organization", organization.getKey())
.execute().getInput();
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithoutBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4");
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\"]}");
}
@Test
- public void return_empty_list() throws Exception {
+ public void empty_list() throws Exception {
userSession.logIn();
- String result = tester.newRequest().execute().getInput();
+ String result = ws.newRequest().execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[]}");
}
@Test
- public void test_example() throws Exception {
+ public void json_example() throws Exception {
userSession.logIn();
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "convention");
dbTester.rules().insertOrUpdateMetadata(r, organization, setTags("security"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r.getKey(), organization);
- String result = tester.newRequest()
+ String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
- assertJson(result).isSimilarTo(tester.getDef().responseExampleAsString());
+
+ assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
}
@Test
- public void test_definition() {
+ public void definition() {
userSession.logIn();
- Action action = tester.getDef();
+ Action action = ws.getDef();
assertThat(action.description()).isNotEmpty();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.isPost()).isFalse();
assertThat(action.params()).extracting(Param::key).containsExactlyInAnyOrder("q", "ps", "organization");
Param query = action.param("q");
- assertThat(query).isNotNull();
assertThat(query.isRequired()).isFalse();
assertThat(query.description()).isNotEmpty();
assertThat(query.exampleValue()).isNotEmpty();
Param pageSize = action.param("ps");
- assertThat(pageSize).isNotNull();
assertThat(pageSize.isRequired()).isFalse();
assertThat(pageSize.defaultValue()).isEqualTo("10");
assertThat(pageSize.description()).isNotEmpty();