diff --git a/package-lock.json b/package-lock.json index 0487ba0..2c50b48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@airgrid/edgekit", - "version": "0.0.0-dev.41", + "version": "0.0.0-dev.42", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@airgrid/edgekit", - "version": "0.0.0-dev.41", + "version": "0.0.0-dev.42", "license": "MIT", "devDependencies": { "@types/jest": "^26.0.3", diff --git a/package.json b/package.json index faca5ab..bd20c9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@airgrid/edgekit", - "version": "0.0.0-dev.41", + "version": "0.0.0-dev.42", "homepage": "https://edgekit.org/", "author": "AirGrid ", "license": "MIT", diff --git a/src/engine/evaluate.ts b/src/engine/evaluate.ts index 22df7b9..41e7368 100644 --- a/src/engine/evaluate.ts +++ b/src/engine/evaluate.ts @@ -15,45 +15,49 @@ export const evaluateCondition = ( condition: Readonly>, pageViews: Readonly ): boolean => { - const { filter, rules } = condition; + try { + const { filter, rules } = condition; - // if no queries, do not match at all - if (pageViews.length === 0 || filter.queries.length === 0) { - return false; - } + // if no queries, do not match at all + if (pageViews.length === 0 || filter.queries.length === 0) { + return false; + } - /* Checks each pageView once for any matching queries - * and returns the filtered array containing the matched - * pageViews - * - * TODO Here, also, we have an opportunity to implement the - * internal AND logic, swapping some for every - * according to the value of filter.any - * - * NOTE: there is actually a semantic problem here. - * The filter definition specifies an 'any' switch, - * which defaults to false. However, the current - * filtering uses `some` to check the query conditions. - * The complete implementation here would be: - * ``` - * filter.queries[filter.any ? 'some' : 'every']((query) => ... - * ``` - * Yet, there is too much (testing) code depending on - * this defaulting to `some` and the refactor would take - * some time. - */ - const filteredPageViews = pageViews.filter((pageView) => - filter.queries.some((query) => { - const pageFeatures = pageView.features[query.queryProperty]; - return queryMatches(query, pageFeatures); - }) - ); + /* Checks each pageView once for any matching queries + * and returns the filtered array containing the matched + * pageViews + * + * TODO Here, also, we have an opportunity to implement the + * internal AND logic, swapping some for every + * according to the value of filter.any + * + * NOTE: there is actually a semantic problem here. + * The filter definition specifies an 'any' switch, + * which defaults to false. However, the current + * filtering uses `some` to check the query conditions. + * The complete implementation here would be: + * ``` + * filter.queries[filter.any ? 'some' : 'every']((query) => ... + * ``` + * Yet, there is too much (testing) code depending on + * this defaulting to `some` and the refactor would take + * some time. + */ + const filteredPageViews = pageViews.filter((pageView) => + filter.queries.some((query) => { + const pageFeatures = pageView.features[query.queryProperty]; + return queryMatches(query, pageFeatures); + }) + ); - return rules.every((rule) => { - const reducer = reducers[rule.reducer.name](); - const value = reducer(filteredPageViews); - const matches = matchers[rule.matcher.name](rule.matcher.args); + return rules.every((rule) => { + const reducer = reducers[rule.reducer.name](); + const value = reducer(filteredPageViews); + const matches = matchers[rule.matcher.name](rule.matcher.args); - return matches(value); - }); + return matches(value); + }); + } catch (error) { + return false; + } }; diff --git a/test/unit/run.test.ts b/test/unit/run.test.ts index f7494f8..97a14d7 100644 --- a/test/unit/run.test.ts +++ b/test/unit/run.test.ts @@ -117,6 +117,31 @@ describe('edkt run method', () => { expect(edkt.getMatchedAudiences()).toHaveLength(0); }); + + it('does not break execution if there is a malformed audience definition', async () => { + setUpLocalStorage(TWO_PAGE_VIEW); + + const malformedAudience = { + id: 'test_id', + version: 7, + ttl: 1209600, + lookBack: 0, + occurrences: 0, + }; + + await edkt.run({ + pageFeatures, + audienceDefinitions: [ + audienceDefinition, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + malformedAudience, + ], + omitGdprConsent: true, + }); + + expect(edkt.getMatchedAudiences()).toHaveLength(1); + }); }); describe('look back edkt run behaviour', () => {