From 6ca0f01995b1741a6a7e80df2f0808da8d134700 Mon Sep 17 00:00:00 2001 From: Claudiu Andrei Date: Mon, 17 May 2021 17:04:22 -0700 Subject: [PATCH] Remove FIND (*) from the defaults Update the EVERY (&) and SOME (|) options in the defaults to incorporate that logic for consistency --- package.json | 2 +- src/compar.ts | 34 +++++++--- test/compar.test.ts | 157 ++++++++++++++++++++++++++------------------ 3 files changed, 117 insertions(+), 76 deletions(-) diff --git a/package.json b/package.json index 1e62381..4354bc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "compar", - "version": "4.0.0", + "version": "5.0.0", "description": "Extensible declarative rule matching engine", "keywords": [ "rule engine", diff --git a/src/compar.ts b/src/compar.ts index a7f74bb..fc33abf 100644 --- a/src/compar.ts +++ b/src/compar.ts @@ -25,12 +25,6 @@ export const defaultMatchers: { [type: string]: Matcher } = { // Regex match '~': (match, context, [value]) => [new RegExp(value, 'i').test(context)], - // Match every condition - '&': (match, context, payload) => [payload.every(value => match(context, value)[0])], - - // Match any condition - '|': (match, context, payload) => [payload.some(value => match(context, value)[0])], - // Match opposite condition '!': (match, context, [value]) => [!match(context, value)[0]], @@ -53,12 +47,32 @@ export const defaultMatchers: { [type: string]: Matcher } = { '?': (match, context, [condition, value]) => match(context, condition)[0] ? match(context, value) : [false], - // Find - '*': (match, context, payload) => { + // Match every condition + '&': (match, context, payload) => { + // Keep the value so we can return it + let success, value + + // Find the value + for (let current of payload) { + // Look for a value + ;[success, value] = match(context, current) + + // Return only + if (!success) { + return [false] + } + } + + // Everything was succesful + return [true, value] + }, + + // Match any condition + '|': (match, context, payload) => { // Find the value - for (let index = 0; index < payload.length; index += 1) { + for (let current of payload) { // Look for a value - const [success, value] = match(context, payload[index]) + const [success, value] = match(context, current) // Return only if (success) { diff --git a/test/compar.test.ts b/test/compar.test.ts index 5f96ada..40f0ea3 100644 --- a/test/compar.test.ts +++ b/test/compar.test.ts @@ -102,64 +102,6 @@ describe('REGEXP', () => { }) }) -describe('EVERY', () => { - // Test equality - test('EVERY should match if all values match', () => { - // Setup the match - const [ct] = match(25, ['&', ['>', 20], ['<', 40]]) - - // Match result should be true - expect(ct).toEqual(true) - }) - - // Test equality - test('EVERY should not match if any values match', () => { - // Setup the match - const [ct] = match(25, ['&', ['>', 20], ['<', 20]]) - - // Match result should be true - expect(ct).toEqual(false) - }) - - // Test equality - test('EVERY should not match if none of the values match', () => { - // Setup the match - const [ct] = match(25, ['&', ['>', 40], ['<', 20]]) - - // Match result should be true - expect(ct).toEqual(false) - }) -}) - -describe('SOME', () => { - // Test equality - test('SOME should match if all values match', () => { - // Setup the match - const [ct] = match(25, ['|', ['>', 20], ['<', 40]]) - - // Match result should be true - expect(ct).toEqual(true) - }) - - // Test equality - test('SOME should match if any values match', () => { - // Setup the match - const [ct] = match(25, ['|', ['>', 40], ['<', 30]]) - - // Match result should be true - expect(ct).toEqual(true) - }) - - // Test equality - test('SOME should not match if none of the values match', () => { - // Setup the match - const [ct] = match(25, ['|', ['>', 40], ['<', 20]]) - - // Match result should be true - expect(ct).toEqual(false) - }) -}) - describe('NOT', () => { // Test equality test('NOT should match an the oposite value', () => { @@ -284,12 +226,97 @@ describe('CONDITIONAL', () => { }) }) -describe('FIND', () => { +describe('EVERY', () => { + // Test equality + test('EVERY should match if all values match', () => { + // Setup the match + const [ct] = match(25, ['&', ['>', 20], ['<', 40]]) + + // Match result should be true + expect(ct).toEqual(true) + }) + + // Test equality + test('EVERY should not match if any values match', () => { + // Setup the match + const [ct] = match(25, ['&', ['>', 20], ['<', 20]]) + + // Match result should be true + expect(ct).toEqual(false) + }) + + // Test equality + test('EVERY should not match if none of the values match', () => { + // Setup the match + const [ct] = match(25, ['&', ['>', 40], ['<', 20]]) + + // Match result should be true + expect(ct).toEqual(false) + }) + + // Test equality + test('EVERY should not retrieve value if not all conditions match', () => { + // Setup the match + const [ct, v] = match('John Doe', [ + '&', + ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']], + ['?', ['=', 'John Doe'], ['@', 'John Doe']], + ['@', 'No one'] + ]) + + // Match result should be true + expect(ct).toEqual(false) + expect(v).toBeUndefined() + }) + + // Test equality + test('EVERY should retrieve last value if all conditions match and there is a default', () => { + // Setup the match + const [ct, v] = match('Jane Doe', [ + '&', + ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']], + ['@', 'Everyone'] + ]) + + // Match result should be true + expect(ct).toEqual(true) + expect(v).toEqual('Everyone') + }) +}) + +describe('SOME', () => { + // Test equality + test('SOME should match if all values match', () => { + // Setup the match + const [ct] = match(25, ['|', ['>', 20], ['<', 40]]) + + // Match result should be true + expect(ct).toEqual(true) + }) + + // Test equality + test('SOME should match if any values match', () => { + // Setup the match + const [ct] = match(25, ['|', ['>', 40], ['<', 30]]) + + // Match result should be true + expect(ct).toEqual(true) + }) + + // Test equality + test('SOME should not match if none of the values match', () => { + // Setup the match + const [ct] = match(25, ['|', ['>', 40], ['<', 20]]) + + // Match result should be true + expect(ct).toEqual(false) + }) + // Test equality - test('FIND should not retrieve value if no condition matches', () => { + test('SOME should retrieve the first when condition matches', () => { // Setup the match const [ct, v] = match('John Doe', [ - '*', + '|', ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']], ['?', ['=', 'John Doe'], ['@', 'John Doe']], ['@', 'No one'] @@ -301,10 +328,10 @@ describe('FIND', () => { }) // Test equality - test('FIND should retrieve default value if no condition matches and there is a default', () => { + test('SOME should retrieve default value if no condition matches and there is a default', () => { // Setup the match const [ct, v] = match('John Doe', [ - '*', + '|', ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']], ['@', 'No one'] ]) @@ -315,9 +342,9 @@ describe('FIND', () => { }) // Test equality - test('FIND should not retrieve any value if no condition matches', () => { + test('SOME should not retrieve any value if no condition matches', () => { // Setup the match - const [ct, v] = match('John Doe', ['*', ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']]]) + const [ct, v] = match('John Doe', ['|', ['?', ['=', 'Jane Doe'], ['@', 'Jane Doe']]]) // Match result should be true expect(ct).toEqual(false)