Skip to content

Commit

Permalink
feat(core): FacetValue Collection filter can specify logical operator
Browse files Browse the repository at this point in the history
Relates to #112
  • Loading branch information
michaelbromley committed Jun 11, 2019
1 parent 16e7fc1 commit f136117
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 30 deletions.
10 changes: 10 additions & 0 deletions packages/core/e2e/__snapshots__/collection.e2e-spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ Object {
"type": "FACET_VALUE_IDS",
"value": "[\\"T_1\\"]",
},
Object {
"name": "containsAny",
"type": "BOOLEAN",
"value": "false",
},
],
"code": "facet-value-filter",
"description": "Filter by FacetValues",
Expand Down Expand Up @@ -97,6 +102,11 @@ Object {
"type": "FACET_VALUE_IDS",
"value": "[\\"T_3\\"]",
},
Object {
"name": "containsAny",
"type": "BOOLEAN",
"value": "false",
},
],
"code": "facet-value-filter",
"description": "Filter by FacetValues",
Expand Down
108 changes: 84 additions & 24 deletions packages/core/e2e/collection.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import gql from 'graphql-tag';
import path from 'path';

import { StringOperator } from '../src/common/configurable-operation';
import {
facetValueCollectionFilter,
variantNameCollectionFilter,
} from '../src/config/collection/default-collection-filters';
import { facetValueCollectionFilter, variantNameCollectionFilter } from '../src/config/collection/default-collection-filters';

import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
import { COLLECTION_FRAGMENT, FACET_VALUE_FRAGMENT } from './graphql/fragments';
Expand Down Expand Up @@ -107,6 +104,11 @@ describe('Collection resolver', () => {
value: `["${getFacetValueId('electronics')}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down Expand Up @@ -138,6 +140,11 @@ describe('Collection resolver', () => {
value: `["${getFacetValueId('computers')}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand All @@ -164,6 +171,11 @@ describe('Collection resolver', () => {
value: `["${getFacetValueId('pear')}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down Expand Up @@ -246,7 +258,7 @@ describe('Collection resolver', () => {
const { updateCollection } = await client.query<
UpdateCollection.Mutation,
UpdateCollection.Variables
>(UPDATE_COLLECTION, {
>(UPDATE_COLLECTION, {
input: {
id: pearCollection.id,
assetIds: [assets[1].id],
Expand Down Expand Up @@ -384,7 +396,7 @@ describe('Collection resolver', () => {
const result = await client.query<
CreateCollectionSelectVariants.Mutation,
CreateCollectionSelectVariants.Variables
>(CREATE_COLLECTION_SELECT_VARIANTS, {
>(CREATE_COLLECTION_SELECT_VARIANTS, {
input: {
translations: [{ languageCode: LanguageCode.en, name: 'Empty', description: '' }],
filters: [],
Expand All @@ -398,7 +410,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: electronicsCollection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
Expand Down Expand Up @@ -430,7 +442,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: computersCollection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
Expand All @@ -454,14 +466,14 @@ describe('Collection resolver', () => {
]);
});

it('photo and pear', async () => {
it('photo AND pear', async () => {
const result = await client.query<
CreateCollectionSelectVariants.Mutation,
CreateCollectionSelectVariants.Variables
>(CREATE_COLLECTION_SELECT_VARIANTS, {
>(CREATE_COLLECTION_SELECT_VARIANTS, {
input: {
translations: [
{ languageCode: LanguageCode.en, name: 'Photo Pear', description: '' },
{ languageCode: LanguageCode.en, name: 'Photo AND Pear', description: '' },
],
filters: [
{
Expand All @@ -474,6 +486,11 @@ describe('Collection resolver', () => {
)}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand All @@ -483,6 +500,48 @@ describe('Collection resolver', () => {
'Instant Camera',
]);
});

it('photo OR pear', async () => {
const result = await client.query<
CreateCollectionSelectVariants.Mutation,
CreateCollectionSelectVariants.Variables
>(CREATE_COLLECTION_SELECT_VARIANTS, {
input: {
translations: [
{ languageCode: LanguageCode.en, name: 'Photo OR Pear', description: '' },
],
filters: [
{
code: facetValueCollectionFilter.code,
arguments: [
{
name: 'facetValueIds',
value: `["${getFacetValueId('pear')}", "${getFacetValueId(
'photo',
)}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `true`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
} as CreateCollectionInput,
});
expect(result.createCollection.productVariants.items.map(i => i.name)).toEqual([
'Laptop 13 inch 8GB',
'Laptop 15 inch 8GB',
'Laptop 13 inch 16GB',
'Laptop 15 inch 16GB',
'Instant Camera',
'Camera Lens',
'Tripod',
'SLR Camera',
]);
});
});

describe('variantName filter', () => {
Expand All @@ -493,7 +552,7 @@ describe('Collection resolver', () => {
const { createCollection } = await client.query<
CreateCollection.Mutation,
CreateCollection.Variables
>(CREATE_COLLECTION, {
>(CREATE_COLLECTION, {
input: {
translations: [
{ languageCode: LanguageCode.en, name: `${operator} ${term}`, description: '' },
Expand Down Expand Up @@ -526,7 +585,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: collection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
Expand All @@ -542,7 +601,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: collection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual(['Camera Lens']);
Expand All @@ -554,7 +613,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: collection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
Expand All @@ -569,7 +628,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: collection.id,
});
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
Expand Down Expand Up @@ -630,7 +689,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
'Laptop 13 inch 8GB',
'Laptop 15 inch 8GB',
Expand Down Expand Up @@ -658,7 +717,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
'Laptop 13 inch 8GB',
'Laptop 15 inch 8GB',
Expand Down Expand Up @@ -687,7 +746,7 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
>(GET_COLLECTION_PRODUCT_VARIANTS, { id: pearCollection.id });
expect(result.collection!.productVariants.items.map(i => i.name)).toEqual([
'Laptop 13 inch 8GB',
'Laptop 15 inch 8GB',
Expand All @@ -707,13 +766,14 @@ describe('Collection resolver', () => {
const result = await client.query<
GetCollectionsForProducts.Query,
GetCollectionsForProducts.Variables
>(GET_COLLECTIONS_FOR_PRODUCTS, { term: 'camera' });
>(GET_COLLECTIONS_FOR_PRODUCTS, { term: 'camera' });
expect(result.products.items[0].collections).toEqual([
{ id: 'T_3', name: 'Electronics' },
{ id: 'T_5', name: 'Pear' },
{ id: 'T_7', name: 'Photo Pear' },
{ id: 'T_8', name: 'contains camera' },
{ id: 'T_10', name: 'endsWith camera' },
{ id: 'T_7', name: 'Photo AND Pear' },
{ id: 'T_8', name: 'Photo OR Pear' },
{ id: 'T_9', name: 'contains camera' },
{ id: 'T_11', name: 'endsWith camera' },
]);
});
});
Expand All @@ -725,7 +785,7 @@ describe('Collection resolver', () => {
const { collection } = await client.query<
GetCollectionProducts.Query,
GetCollectionProducts.Variables
>(GET_COLLECTION_PRODUCT_VARIANTS, {
>(GET_COLLECTION_PRODUCT_VARIANTS, {
id: pearCollection.id,
});
expect(collection!.productVariants.items.map(i => i.name)).toEqual([
Expand Down
10 changes: 10 additions & 0 deletions packages/core/e2e/default-search-plugin.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ describe('Default search plugin', () => {
value: `["T_4"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down Expand Up @@ -396,6 +401,11 @@ describe('Default search plugin', () => {
value: `["T_3"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down
5 changes: 5 additions & 0 deletions packages/core/e2e/shop-catalog.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ describe('Shop catalog', () => {
value: `["${category.values[3].id}"]`,
type: ConfigArgType.FACET_VALUE_IDS,
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/common/configurable-operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function configurableDefToOperation(def: ConfigurableOperationDef): Confi
export function argsArrayToHash<T>(args: ConfigArg[]): ConfigArgValues<T> {
const output: ConfigArgValues<T> = {} as any;
for (const arg of args) {
if (arg.value != null) {
if (arg && arg.value != null) {
output[arg.name as keyof ConfigArgValues<T>] = coerceValueToType<T>(arg);
}
}
Expand All @@ -81,7 +81,7 @@ function coerceValueToType<T>(arg: ConfigArg): ConfigArgValues<T>[keyof T] {
case ConfigArgType.DATETIME:
return Date.parse(arg.value || '') as any;
case ConfigArgType.BOOLEAN:
return !!arg.value as any;
return !!(arg.value && (arg.value.toLowerCase() === 'true' || arg.value === '1')) as any;
case ConfigArgType.FACET_VALUE_IDS:
try {
return JSON.parse(arg.value as any);
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/config/collection/collection-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '../../common/configurable-operation';
import { ProductVariant } from '../../entity/product-variant/product-variant.entity';

export type CollectionFilterArgType = ConfigArgType.FACET_VALUE_IDS | ConfigArgType.STRING | ConfigArgType.STRING_OPERATOR;
export type CollectionFilterArgType = ConfigArgType.FACET_VALUE_IDS | ConfigArgType.STRING | ConfigArgType.STRING_OPERATOR | ConfigArgType.BOOLEAN;
export type CollectionFilterArgs = ConfigArgs<CollectionFilterArgType>;

export type ApplyCollectionFilterFn<T extends CollectionFilterArgs> = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CollectionFilter } from './collection-filter';
export const facetValueCollectionFilter = new CollectionFilter({
args: {
facetValueIds: ConfigArgType.FACET_VALUE_IDS,
containsAny: ConfigArgType.BOOLEAN,
},
code: 'facet-value-filter',
description: 'Filter by FacetValues',
Expand All @@ -26,7 +27,7 @@ export const facetValueCollectionFilter = new CollectionFilter({
}),
)
.groupBy('productVariant.id')
.having(`COUNT(1) >= :count`, {count: args.facetValueIds.length});
.having(`COUNT(1) >= :count`, { count: args.containsAny ? 1 : args.facetValueIds.length });
} else {
// If no facetValueIds are specified, no ProductVariants will be matched.
qb.andWhere('1 = 0');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ export class Populator {
type: ConfigArgType.FACET_VALUE_IDS,
value: JSON.stringify(facetValueIds),
},
{
name: 'containsAny',
value: `false`,
type: ConfigArgType.BOOLEAN,
},
],
},
],
Expand Down

0 comments on commit f136117

Please sign in to comment.