Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Graphql verbatim search terms #1174

Merged
2 changes: 1 addition & 1 deletion packages/common/src/enums/searchTerm.type.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type SearchTerm = string | number | boolean | Date;
export type SearchTerm = string | number | boolean | Date | null;
2 changes: 1 addition & 1 deletion packages/common/src/filters/sliderFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export class SliderFilter implements Filter {
sliderVals = (term1 as string).split('..');
this._currentValue = +(sliderVals?.[0] ?? 0);
} else if (hasData(term1) || term1 === '') {
this._currentValue = +term1;
this._currentValue = term1 === null ? undefined : +term1;
sliderVals = [term1 as string | number];
}
}
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/interfaces/currentFilter.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ export interface CurrentFilter {

/** Target element selector from which the filter was triggered from. */
targetSelector?: string;

/** If true, stringifies the search terms as is without modification */
ghiscoding marked this conversation as resolved.
Show resolved Hide resolved
verbatimSearchTerms?: boolean;
}
38 changes: 38 additions & 0 deletions packages/graphql/src/services/__tests__/graphql.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,44 @@ describe('GraphqlService', () => {
expect(removeSpaces(query)).toBe(removeSpaces(expectation));
expect(currentFilters).toEqual([]);
});

describe("Verbatim ColumnFilters", () => {
describe.each`
description | verbatim | operator | searchTerms | expectation
${"Verbatim false, Filter for null"} | ${false} | ${'EQ'} | ${null} | ${'query{users(first:10, offset:0) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Filter for null"} | ${true} | ${'EQ'} | ${null} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:EQ, value:"null"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Empty string"} | ${false} | ${'EQ'} | ${''} | ${'query{users(first:10, offset:0) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Empty string"} | ${true} | ${'EQ'} | ${''} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:EQ, value:"\\"\\""}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Empty list"} | ${false} | ${'IN'} | ${[]} | ${'query{users(first:10, offset:0) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Empty list"} | ${true} | ${'IN'} | ${[]} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"[]"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Filter for null (in list)"} | ${false} | ${'IN'} | ${[null]} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:""}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Filter for null (in list)"} | ${true} | ${'IN'} | ${[null]} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"[null]"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Filter for empty string (in list)"} | ${false} | ${'IN'} | ${['']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:""}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Filter for empty string (in list)"} | ${true} | ${'IN'} | ${['']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"[\\"\\"]"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Filter for female"} | ${false} | ${'IN'} | ${['female']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"female"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Filter for female"} | ${true} | ${'IN'} | ${['female']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"[\\"female\\"]"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim false, Filter for female/male"} | ${false} | ${'IN'} | ${['female', 'male']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"female, male"}]) { totalCount,nodes{ id,company,gender,name } }}'}
${"Verbatim true, Filter for female/male"} | ${true} | ${'IN'} | ${['female', 'male']} | ${'query{users(first:10, offset:0, filterBy:[{field:gender, operator:IN, value:"[\\"female\\", \\"male\\"]"}]) { totalCount,nodes{ id,company,gender,name } }}'}
`(`$description`, ({ description, verbatim, operator, searchTerms, expectation }) => {

const mockColumn = { id: 'gender', field: 'gender' } as Column;
let mockColumnFilters: ColumnFilters;

beforeEach(() => {
mockColumnFilters = {
gender: { columnId: 'gender', columnDef: mockColumn, searchTerms, operator, type: FieldType.string, verbatimSearchTerms: verbatim },
} as ColumnFilters;

service.init(serviceOptions, paginationOptions, gridStub);
service.updateFilters(mockColumnFilters, false);
});

test(`buildQuery output matches ${expectation}`, () => {
const query = service.buildQuery();
expect(removeSpaces(query)).toBe(removeSpaces(expectation));
});
});
});
});

describe('presets', () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/graphql/src/services/graphql.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,11 @@ export class GraphqlService implements BackendService {
throw new Error(`GraphQL filter could not find the field name to query the search, your column definition must include a valid "field" or "name" (optionally you can also use the "queryfield").`);
}

if (columnFilter.verbatimSearchTerms) {
searchByArray.push({ field: fieldName, operator: columnFilter.operator, value: JSON.stringify(columnFilter.searchTerms) });
continue;
}

fieldSearchValue = (fieldSearchValue === undefined || fieldSearchValue === null) ? '' : `${fieldSearchValue}`; // make sure it's a string

// run regex to find possible filter operators unless the user disabled the feature
Expand Down