Skip to content

Commit

Permalink
Merge branch 'master' into CIF-2188
Browse files Browse the repository at this point in the history
  • Loading branch information
laurentiumagureanu authored Jul 30, 2021
2 parents 2cad8b9 + 218d544 commit 9788641
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ public SearchAggregationOption apply(final AggregationOption aggregationOption)
searchAggregationOption.setDisplayLabel(aggregationOption.getLabel());
}

searchAggregationOption.setCount(aggregationOption.getCount());
searchAggregationOption.setCount(aggregationOption.getCount() != null ? aggregationOption.getCount() : 0);
searchAggregationOption.setFilterValue(aggregationOption.getValue());

// this is done for convenience sake so we have all filters available
// this is done for convenience sake, so we have all filters available
Map<String, String> newFilters = new HashMap<>(filters);
newFilters.put(attributeCode, aggregationOption.getValue());
searchAggregationOption.setAddFilterMap(newFilters.entrySet().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public SearchAggregation apply(final Aggregation aggregation) {

SearchAggregationImpl searchAggregation = new SearchAggregationImpl();
searchAggregation.setFilterable(filterable);
searchAggregation.setCount(aggregation == null ? 0 : aggregation.getCount());
searchAggregation.setCount(aggregation.getCount() != null ? aggregation.getCount() : 0);
searchAggregation.setOptions(getOptions(aggregation, appliedFilters));
searchAggregation.setDisplayLabel(aggregation.getLabel());
searchAggregation.setIdentifier(identifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.adobe.cq.commerce.core.search.internal.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -50,6 +51,7 @@
import com.adobe.cq.commerce.core.search.internal.models.SorterKeyImpl;
import com.adobe.cq.commerce.core.search.models.FilterAttributeMetadata;
import com.adobe.cq.commerce.core.search.models.SearchAggregation;
import com.adobe.cq.commerce.core.search.models.SearchAggregationOption;
import com.adobe.cq.commerce.core.search.models.SearchOptions;
import com.adobe.cq.commerce.core.search.models.SearchResultsSet;
import com.adobe.cq.commerce.core.search.models.Sorter;
Expand Down Expand Up @@ -83,6 +85,9 @@
@Component(service = SearchResultsService.class)
public class SearchResultsServiceImpl implements SearchResultsService {

private static final String CATEGORY_ID_FILTER = "category_id";
private static final String CATEGORY_UID_FILTER = "category_uid";

@Reference
private SearchFilterService searchFilterService;
@Reference
Expand Down Expand Up @@ -184,10 +189,9 @@ public Pair<CategoryInterface, SearchResultsSet> performSearch(
List<SearchAggregation> searchAggregations = extractSearchAggregationsFromResponse(products.getAggregations(),
mutableSearchOptions.getAllFilters(), availableFilters);

// Special treatment for category_id filter as this is always present and collides with category_uid filter (CIF-2206)
if (mutableSearchOptions.getCategoryUid().isPresent()) {
searchAggregations.removeIf(a -> "category_id".equals(a.getIdentifier()));
}
// special handling of category identifier(s)
removeCategoryIdAggregationIfNecessary(searchAggregations, mutableSearchOptions);
removeCategoryUidFilterEntriesIfPossible(searchAggregations, request);

searchResultsSet.setTotalResults(products.getTotalCount());
searchResultsSet.setProductListItems(productListItems);
Expand Down Expand Up @@ -357,8 +361,7 @@ private String generateProductsQueryString(

/**
* Generates a query string for the category specified in the retriever.
*
*
*
* @param categoryRetriever
* @return the query string
*/
Expand Down Expand Up @@ -468,4 +471,34 @@ private List<SearchAggregation> extractSearchAggregationsFromResponse(
.collect(Collectors.toList());
}

/**
* Removes the category_id filter from the search aggregations when category_uid filter is present because either cannot be combined
* with the other.
*
* @param aggs
* @param searchOptions
*/
private void removeCategoryIdAggregationIfNecessary(List<SearchAggregation> aggs, SearchOptionsImpl searchOptions) {
// Special treatment for category_id filter as this is always present and collides with category_uid filter (CIF-2206)
if (searchOptions.getCategoryUid().isPresent()) {
aggs.removeIf(agg -> CATEGORY_ID_FILTER.equals(agg.getIdentifier()));
}
}

/**
* Removes the category_uid filter from all filter options' filter maps when the category uid can be retrieved from the request already.
*
* @param aggs
* @param request
*/
private void removeCategoryUidFilterEntriesIfPossible(List<SearchAggregation> aggs, SlingHttpServletRequest request) {
String categoryUid = urlProvider.getCategoryIdentifier(request);
if (StringUtils.isNotBlank(categoryUid)) {
aggs.stream()
.map(SearchAggregation::getOptions)
.flatMap(Collection::stream)
.map(SearchAggregationOption::getAddFilterMap)
.forEach(filterMap -> filterMap.remove(CATEGORY_UID_FILTER, categoryUid));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
Expand All @@ -35,16 +39,18 @@
import org.mockito.runners.MockitoJUnitRunner;

import com.adobe.cq.commerce.core.components.client.MagentoGraphqlClient;
import com.adobe.cq.commerce.core.components.internal.services.MockUrlProviderConfiguration;
import com.adobe.cq.commerce.core.components.internal.services.UrlProviderImpl;
import com.adobe.cq.commerce.core.components.services.urls.UrlProvider;
import com.adobe.cq.commerce.core.search.internal.models.FilterAttributeMetadataImpl;
import com.adobe.cq.commerce.core.search.internal.models.SearchOptionsImpl;
import com.adobe.cq.commerce.core.search.models.FilterAttributeMetadata;
import com.adobe.cq.commerce.core.search.models.SearchAggregation;
import com.adobe.cq.commerce.core.search.models.SearchAggregationOption;
import com.adobe.cq.commerce.core.search.models.SearchResultsSet;
import com.adobe.cq.commerce.core.search.models.Sorter;
import com.adobe.cq.commerce.core.search.services.SearchFilterService;
import com.adobe.cq.commerce.graphql.client.GraphqlResponse;
import com.adobe.cq.commerce.magento.graphql.Aggregation;
import com.adobe.cq.commerce.magento.graphql.AggregationOption;
import com.adobe.cq.commerce.magento.graphql.FilterEqualTypeInput;
import com.adobe.cq.commerce.magento.graphql.FilterMatchTypeInput;
import com.adobe.cq.commerce.magento.graphql.FilterRangeTypeInput;
Expand Down Expand Up @@ -76,6 +82,8 @@ private static AemContext createContext(String contentPath) {
ResourceResolverType.JCR_MOCK);
}

@Mock
UrlProvider urlProvider;
@Mock
SearchFilterService searchFilterService;
@Mock
Expand Down Expand Up @@ -123,8 +131,8 @@ public void setup() {
createUnknownAttributeMetadata()));

when(products.getTotalCount()).thenReturn(0);
when(products.getItems()).thenReturn(new ArrayList<>());
when(products.getAggregations()).thenReturn(new ArrayList<>());
when(products.getItems()).thenReturn(Collections.emptyList());
when(products.getAggregations()).thenReturn(Collections.emptyList());
when(query.getProducts()).thenReturn(products);

GraphqlResponse<Query, Error> response = new GraphqlResponse<Query, Error>();
Expand All @@ -135,8 +143,6 @@ public void setup() {

context.registerService(SearchFilterService.class, searchFilterService);

UrlProviderImpl urlProvider = new UrlProviderImpl();
urlProvider.activate(new MockUrlProviderConfiguration());
context.registerService(UrlProvider.class, urlProvider);
context.registerAdapter(SlingHttpServletRequest.class, MagentoGraphqlClient.class, magentoGraphqlClient);

Expand Down Expand Up @@ -168,7 +174,6 @@ private void prepareSearchOptions() {

@Test
public void testPerformSearch() {

SearchResultsSet searchResultsSet = serviceUnderTest.performSearch(
searchOptions,
resource,
Expand Down Expand Up @@ -199,8 +204,107 @@ public void testPerformSearch() {
}

@Test
public void testSearchWithSortOrderParam() {
public void testSearchAggregations() {
when(products.getAggregations()).thenReturn(Collections.singletonList(new Aggregation()
.setLabel("Name")
.setAttributeCode("name")
.setOptions(Arrays.asList(
new AggregationOption().setLabel("Sport").setValue("sport").setCount(2),
new AggregationOption().setLabel("Lifestyle").setValue("lifestyle").setCount(3)))
.setCount(5)));

SearchResultsSet resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);

List<SearchAggregation> aggregations = resultsSet.getSearchAggregations();
assertThat(aggregations).isNotNull();
assertThat(aggregations.size()).isEqualTo(1);
SearchAggregation aggregation = aggregations.get(0);
assertThat(aggregation.getDisplayLabel()).isEqualTo("Name");
assertThat(aggregation.getIdentifier()).isEqualTo("name");
assertThat(aggregation.getOptionCount()).isEqualTo(5);

List<SearchAggregationOption> options = aggregation.getOptions();
assertThat(options).isNotNull();
assertThat(options.size()).isEqualTo(2);

SearchAggregationOption sportOption = options.get(0);
assertThat(sportOption.getDisplayLabel()).isEqualTo("Sport");
assertThat(sportOption.getFilterValue()).isEqualTo("sport");
assertThat(sportOption.getCount()).isEqualTo(2);

SearchAggregationOption lifestyleOption = options.get(1);
assertThat(lifestyleOption.getDisplayLabel()).isEqualTo("Lifestyle");
assertThat(lifestyleOption.getFilterValue()).isEqualTo("lifestyle");
assertThat(lifestyleOption.getCount()).isEqualTo(3);
}

@Test
public void testCategoryIdSearchAggregationRemoved() {
when(products.getAggregations()).thenReturn(Collections.singletonList(new Aggregation()
.setAttributeCode("category_id")
.setOptions(Collections.emptyList())));
when(searchFilterService.retrieveCurrentlyAvailableCommerceFilters(any())).thenReturn(Collections.singletonList(
createMatchFilterAttributeMetadata("category_id")));

// test without category_id
SearchResultsSet resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);
List<SearchAggregation> aggregations = resultsSet.getSearchAggregations();
assertThat(aggregations).isNotNull();
assertThat(aggregations.isEmpty()).isEqualTo(false);

// test with category uid present
searchOptions.setCategoryUid("foobar");
resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);
aggregations = resultsSet.getSearchAggregations();
assertThat(aggregations).isNotNull();
assertThat(aggregations.isEmpty()).isEqualTo(true);
}

@Test
public void testCategoryUidFilterEntriesRemoved() {
final Predicate<Map<String, String>> filterMapFilter = map -> map.containsKey("category_uid");

List<Aggregation> aggregationsList = new ArrayList<>();
aggregationsList.add(new Aggregation()
.setAttributeCode("name")
.setOptions(Arrays.asList(
new AggregationOption().setValue("1"),
new AggregationOption().setValue("2"))));

when(products.getAggregations()).thenReturn(aggregationsList);
when(searchFilterService.retrieveCurrentlyAvailableCommerceFilters(any())).thenReturn(Arrays.asList(
createStringEqualFilterAttributeMetadata("category_uid"),
createStringEqualFilterAttributeMetadata("name")));

searchOptions.setAttributeFilters(Collections.emptyMap());

// test without category_uid
SearchResultsSet resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);
List<SearchAggregation> aggregations = resultsSet.getSearchAggregations();
assertThat(getFilterMapsOfAllOptions(aggregations, filterMapFilter)).isEmpty();

// test with category_uid filter
searchOptions.setCategoryUid("foobar");
resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);
aggregations = resultsSet.getSearchAggregations();
assertThat(getFilterMapsOfAllOptions(aggregations, filterMapFilter).count()).isEqualTo(2);

// test with category_uid filter from request
when(urlProvider.getCategoryIdentifier(request)).thenReturn("foobar");
resultsSet = serviceUnderTest.performSearch(searchOptions, resource, productPage, request);
aggregations = resultsSet.getSearchAggregations();
assertThat(getFilterMapsOfAllOptions(aggregations, filterMapFilter)).isEmpty();
}

private static Stream<Map<String, String>> getFilterMapsOfAllOptions(List<SearchAggregation> aggregations,
Predicate<Map<String, String>> filter) {
return aggregations.stream()
.map(SearchAggregation::getOptions).flatMap(Collection::stream).map(SearchAggregationOption::getAddFilterMap)
.filter(filter);
}

@Test
public void testSearchWithSortOrderParam() {
searchOptions.addSorterKey("name", "Name", Sorter.Order.DESC);
searchOptions.getAttributeFilters().put(Sorter.PARAMETER_SORT_KEY, "name");
searchOptions.getAttributeFilters().put(Sorter.PARAMETER_SORT_ORDER, Sorter.Order.ASC.name());
Expand Down Expand Up @@ -245,7 +349,6 @@ public void testSearchWithInvalidSortOrderParam() {

@Test
public void testSearchWithInvalidSortKey() {

searchOptions.addSorterKey("invalid", "Invalid", null);
searchOptions.getAttributeFilters().put(Sorter.PARAMETER_SORT_KEY, "invalid");
searchOptions.getAttributeFilters().put(Sorter.PARAMETER_SORT_ORDER, Sorter.Order.ASC.name());
Expand All @@ -268,7 +371,6 @@ public void testSearchWithInvalidSortKey() {

@Test
public void testNullMagentoClient() {

GraphqlResponse<Query, Error> response = new GraphqlResponse<Query, Error>();
response.setData(query);
Error error = new Error();
Expand All @@ -290,7 +392,6 @@ public void testNullMagentoClient() {

@Test
public void testExtendProductQuery() {

SearchOptionsImpl searchOptions = new SearchOptionsImpl();
searchOptions.setPageSize(6);
searchOptions.setSearchQuery(SEARCH_QUERY);
Expand Down

0 comments on commit 9788641

Please sign in to comment.