diff --git a/datahub-web-react/src/app/sharedV2/queryBuilder/builder/__tests__/utils.test.tsx b/datahub-web-react/src/app/sharedV2/queryBuilder/builder/__tests__/utils.test.tsx index d3ae32b6d1..197b87a302 100644 --- a/datahub-web-react/src/app/sharedV2/queryBuilder/builder/__tests__/utils.test.tsx +++ b/datahub-web-react/src/app/sharedV2/queryBuilder/builder/__tests__/utils.test.tsx @@ -182,6 +182,34 @@ describe('utils', () => { }, ]; + const EMPTY_PROPERTY_PREDICATE = { + operator: LogicalOperatorType.AND, + operands: [ + { + property: 'test', + operator: 'equals', + values: ['dataset1'], + }, + { + property: '', + operator: 'equals', + values: ['dataset2'], + }, + ], + }; + + const EMPTY_PROPERTY_OR_FILTERS = [ + { + and: [{ field: 'test', condition: 'EQUAL', values: ['dataset1'] }], + }, + ]; + + const EMPTY_LOGICAL_PREDICATE = {}; + + const LOGICAL_PREDICATE_WITH_UNKNOWN_OPERATION = { + operator: 'UNKNOWN', + }; + describe('convertLogicalPredicateToOrFilters', () => { it('convert a basic AND predicate to orFilters', () => { expect(convertLogicalPredicateToOrFilters(BASIC_AND_LOGICAL_PREDICATE)).toEqual(BASIC_AND_OR_FILTERS); @@ -197,5 +225,14 @@ describe('utils', () => { it('convert a nested predicate to orFilters', () => { expect(convertLogicalPredicateToOrFilters(NESTED_LOGICAL_PREDICATE)).toEqual(NESTED_OR_FILTERS); }); + it('should ignore predicate with empty property', () => { + expect(convertLogicalPredicateToOrFilters(EMPTY_PROPERTY_PREDICATE)).toEqual(EMPTY_PROPERTY_OR_FILTERS); + }); + it('should ignore empty logical predicate', () => { + expect(convertLogicalPredicateToOrFilters(EMPTY_LOGICAL_PREDICATE)).toEqual(undefined); + }); + it('should ignore logical predicate with unknown operator', () => { + expect(convertLogicalPredicateToOrFilters(LOGICAL_PREDICATE_WITH_UNKNOWN_OPERATION)).toEqual(undefined); + }); }); }); diff --git a/datahub-web-react/src/app/sharedV2/queryBuilder/builder/utils.ts b/datahub-web-react/src/app/sharedV2/queryBuilder/builder/utils.ts index 67747846b0..52bfafb294 100644 --- a/datahub-web-react/src/app/sharedV2/queryBuilder/builder/utils.ts +++ b/datahub-web-react/src/app/sharedV2/queryBuilder/builder/utils.ts @@ -52,14 +52,16 @@ function mapOperator(operator: string): FilterOperator { export function convertLogicalPredicateToOrFilters( pred: LogicalPredicate | PropertyPredicate, isNegated = false, -): AndFilterInput[] { +): AndFilterInput[] | undefined { if (pred && 'property' in pred) { + if (!pred.property) return undefined; + // it's a PropertyPredicate return [ { and: [ { - field: pred.property || '', + field: pred.property, values: pred.values || [], condition: pred.operator ? mapOperator(pred.operator) : undefined, ...(isNegated && { negated: true }), @@ -68,27 +70,32 @@ export function convertLogicalPredicateToOrFilters( }, ]; } - // it's a LogicalPredicate - switch (pred.operator) { - case LogicalOperatorType.AND: { - const andResults = (pred as LogicalPredicate).operands.map((op) => - convertLogicalPredicateToOrFilters(op, isNegated), - ); - return andResults.reduce((acc, curr) => combineOrFilters(acc, curr), [{ and: [] }]); + if (pred && pred.operator) { + // it's a LogicalPredicate + switch (pred.operator) { + case LogicalOperatorType.AND: { + const andResults = (pred as LogicalPredicate).operands + .map((op) => convertLogicalPredicateToOrFilters(op, isNegated)) + .filter((filters): filters is AndFilterInput[] => !!filters); + return andResults.reduce((acc, curr) => combineOrFilters(acc, curr), [{ and: [] }]); + } + case LogicalOperatorType.OR: + return (pred as LogicalPredicate).operands + .flatMap((op) => convertLogicalPredicateToOrFilters(op, isNegated)) + .filter((andFilter): andFilter is AndFilterInput => !!andFilter); + case LogicalOperatorType.NOT: { + const notResults = (pred as LogicalPredicate).operands + .map((op) => convertLogicalPredicateToOrFilters(op, !isNegated)) + .filter((filters): filters is AndFilterInput[] => !!filters); + return notResults.reduce((acc, curr) => combineOrFilters(acc, curr), [{ and: [] }]); + } + default: + console.error(`Unknown operator: ${pred.operator}`); + return undefined; } - case LogicalOperatorType.OR: - return (pred as LogicalPredicate).operands.flatMap((op) => - convertLogicalPredicateToOrFilters(op, isNegated), - ); - case LogicalOperatorType.NOT: { - const notResults = (pred as LogicalPredicate).operands.map((op) => - convertLogicalPredicateToOrFilters(op, !isNegated), - ); - return notResults.reduce((acc, curr) => combineOrFilters(acc, curr), [{ and: [] }]); - } - default: - throw new Error(`Unknown operator: ${pred.operator}`); } + + return undefined; } export const convertToLogicalPredicate = (predicate: LogicalPredicate | PropertyPredicate): LogicalPredicate => {