From d31d560e6b4515a5c04f8e5681cad4c691534c7a Mon Sep 17 00:00:00 2001 From: Homa Wong Date: Sun, 2 Dec 2018 17:29:22 -0800 Subject: [PATCH] chore: misc clean up --- package-lock.json | 32 +--- src/createSatisfier.exec.spec.ts | 170 --------------------- src/createSatisfier.spec.ts | 254 ++++++++++++++++++++++++++++++- src/createSatisfier.test.spec.ts | 79 ---------- src/createSatisfier.ts | 5 + src/exact.spec.ts | 10 ++ src/exact.ts | 19 +++ src/index.ts | 22 +-- src/isInInterval.ts | 4 +- 9 files changed, 305 insertions(+), 290 deletions(-) delete mode 100644 src/createSatisfier.exec.spec.ts delete mode 100644 src/createSatisfier.test.spec.ts create mode 100644 src/exact.spec.ts create mode 100644 src/exact.ts diff --git a/package-lock.json b/package-lock.json index 6ea9044..2b0c90a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -361,7 +361,6 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -2993,14 +2992,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3015,20 +3012,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -3145,8 +3139,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -3158,7 +3151,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3173,7 +3165,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -3181,14 +3172,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -3207,7 +3196,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3288,8 +3276,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3301,7 +3288,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3423,7 +3409,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5152,8 +5137,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true, - "optional": true + "dev": true }, "loose-envify": { "version": "1.4.0", diff --git a/src/createSatisfier.exec.spec.ts b/src/createSatisfier.exec.spec.ts deleted file mode 100644 index a6c4b77..0000000 --- a/src/createSatisfier.exec.spec.ts +++ /dev/null @@ -1,170 +0,0 @@ -import t from 'assert' - -import { createSatisfier } from './index' -import { assertExec, assertRegExp } from './testUtil' - -test('undefined should match anything', () => { - t.strictEqual(createSatisfier(undefined).exec(undefined), undefined) - t.strictEqual(createSatisfier(undefined).exec({}), undefined) - t.strictEqual(createSatisfier({ a: undefined }).exec({}), undefined) - t.strictEqual(createSatisfier([undefined]).exec([]), undefined) -}) - -test('primitive types without specifing generic will work without issue.', () => { - t.strictEqual(createSatisfier(1).exec(1), undefined) - t.strictEqual(createSatisfier(true).exec(true), undefined) - t.strictEqual(createSatisfier('a').exec('a'), undefined) -}) - -test('can use generic to specify the data structure', () => { - t.strictEqual(createSatisfier(1).exec(1), undefined) - t.strictEqual(createSatisfier<{ a: number }>({ a: /1/ }).exec({ a: 1 }), undefined) -}) - -test('empty object expectation passes all objects', () => { - t.strictEqual(createSatisfier({}).exec({}), undefined) - t.strictEqual(createSatisfier({}).exec({ a: 1 }), undefined) - t.strictEqual(createSatisfier({}).exec({ a: { b: 'a' } }), undefined) - t.strictEqual(createSatisfier({}).exec({ a: true }), undefined) - t.strictEqual(createSatisfier({}).exec({ a: [1] }), undefined) -}) - -test('empty object expectation fails primitive', () => { - assertExec(createSatisfier({}).exec(1)![0], [], {}, 1) - assertExec(createSatisfier({}).exec(true)![0], [], {}, true) - assertExec(createSatisfier({}).exec('a')![0], [], {}, 'a') -}) - -test('mismatch value gets path, expected, and actual', () => { - const actual = createSatisfier({ a: 1 }).exec({ a: 2 })! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a'], 1, 2) -}) - -test('missing property get actual as undefined', () => { - const actual = createSatisfier({ a: 1 }).exec({})! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a'], 1, undefined) -}) - -test('missing property get deeper level', () => { - const actual = createSatisfier({ a: { b: 1 } }).exec({ a: {} })! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a', 'b'], 1, undefined) -}) - -test('passing regex gets undefined', () => { - t.strictEqual(createSatisfier({ foo: /foo/ }).exec({ foo: 'foo' }), undefined) -}) - -test('failed regex will be in expected property', () => { - const actual = createSatisfier({ foo: /foo/ }).exec({ foo: 'boo' })! - assertRegExp(actual, ['foo'], /foo/, 'boo') -}) - -test('regex on missing property gets actual as undefined', () => { - const actual = createSatisfier({ foo: /foo/ }).exec({})! - assertRegExp(actual, ['foo'], /foo/, undefined) -}) - -test('regex on non-string will fail as normal', () => { - let actual = createSatisfier({ foo: /foo/ }).exec({ foo: 1 })! - assertRegExp(actual, ['foo'], /foo/, 1) - - actual = createSatisfier({ foo: /foo/ }).exec({ foo: true })! - assertRegExp(actual, ['foo'], /foo/, true) - - actual = createSatisfier({ foo: /foo/ }).exec({ foo: [1, true, 'a'] })! - assertRegExp(actual, ['foo'], /foo/, [1, true, 'a']) - - actual = createSatisfier({ foo: /foo/ }).exec({ foo: { a: 1 } })! - assertRegExp(actual, ['foo'], /foo/, { a: 1 }) -}) - -test('predicate receives actual value', () => { - t.strictEqual(createSatisfier({ a: a => a === 1 }).exec({ a: 1 }), undefined) -}) - -test('passing predicate gets undefined', () => { - t.strictEqual(createSatisfier({ a: () => true }).exec({}), undefined) - t.strictEqual(createSatisfier({ a: () => true }).exec({ a: 1 }), undefined) -}) - -test('failing predicate', () => { - const actual = createSatisfier({ a: /*istanbul ignore next*/function () { return false } }).exec({ a: 1 })! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a'], /*istanbul ignore next*/function () { return false; }, 1) -}) - -test('against each element in array', () => { - t.strictEqual(createSatisfier({ a: 1 }).exec([{ a: 1 }, { b: 1, a: 1 }]), undefined) -}) - -test('against each element in array in deep level', () => { - const actual = createSatisfier({ a: { b: { c: /foo/ } } }).exec([{ a: {} }, { a: { b: {} } }, { a: { b: { c: 'boo' } } }])! - t.strictEqual(actual.length, 3) - assertExec(actual[0], ['[0]', 'a', 'b'], { c: /foo/ }, undefined) - assertExec(actual[1], ['[1]', 'a', 'b', 'c'], /foo/, undefined) - assertExec(actual[2], ['[2]', 'a', 'b', 'c'], /foo/, 'boo') -}) - -test('when apply against array, will have indices in the path', () => { - const actual = createSatisfier({ a: 1 }).exec([{ a: 1 }, {}])! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['[1]', 'a'], 1, undefined) -}) - -test('when expectation is an array, apply to each entry in the actual array', () => { - t.strictEqual(createSatisfier([{ a: 1 }, { b: 2 }]).exec([{ a: 1 }, { b: 2 }, { c: 3 }]), undefined) - const actual = createSatisfier([{ a: 1 }, { b: 2 }]).exec([{ a: true }, { b: 'b' }, { c: 3 }])! - t.strictEqual(actual.length, 2) - assertExec(actual[0], ['[0]', 'a'], 1, true) - assertExec(actual[1], ['[1]', 'b'], 2, 'b') -}) - -test.skip('when expectation is an array and actual is not, the behavior is not defined yet', () => { - const actual = createSatisfier([{ a: 1 }, { b: 2 }]).exec({ a: 1 })! - t.strictEqual(actual.length, 1) -}) - -test('deep object checking', () => { - const actual = createSatisfier({ a: { b: 1 } }).exec({ a: { b: 2 } })! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a', 'b'], 1, 2) -}) - -test('can check parent property', () => { - class Foo { - foo = 'foo' - } - class Boo extends Foo { - boo = 'boo' - } - const boo = new Boo() - t.strictEqual(createSatisfier({ foo: 'foo' }).exec(boo), undefined) -}) - -test('actual of type any should not have type checking error', () => { - let actual: any = { a: 1 } - t.strictEqual(createSatisfier({ a: 1 }).exec(actual), undefined) -}) - -test('expect array in hash', () => { - t.strictEqual(createSatisfier({ a: [1, true, 'a'] }).exec({ a: [1, true, 'a'] }), undefined) -}) - -test('failing array in hash', () => { - const actual = createSatisfier({ a: [1, true, 'a'] }).exec({ a: [1, true, 'b'] })! - t.strictEqual(actual.length, 1) - assertExec(actual[0], ['a', '[2]'], 'a', 'b') -}) - -test('apply property predicate to array', () => { - const satisfier = createSatisfier({ - data: e => e && e.every(x => x.login) - }); - - t.strictEqual(satisfier.exec({ data: [{ login: 'a' }] }), undefined) - t.notStrictEqual(satisfier.exec([{ data: [{ foo: 'a' }] }]), undefined) - t.notStrictEqual(satisfier.exec([{ foo: 'b' }]), undefined) -}) diff --git a/src/createSatisfier.spec.ts b/src/createSatisfier.spec.ts index 557b816..90b230d 100644 --- a/src/createSatisfier.spec.ts +++ b/src/createSatisfier.spec.ts @@ -1,8 +1,8 @@ -import t from 'assert' -import a from 'assertron' +import t from 'assert'; +import a from 'assertron'; +import { createSatisfier } from './index'; +import { assertExec, assertRegExp } from './testUtil'; -import { createSatisfier } from './index' -import { assertExec } from './testUtil' test('support generics', () => { const s = createSatisfier<{ a: number }>({ a: 1 }) @@ -49,3 +49,249 @@ test('array with null', () => { t(createSatisfier([null]).test([null])) a.false(createSatisfier([null]).test([1])) }) + +describe('exec', () => { + + test('undefined should match anything', () => { + t.strictEqual(createSatisfier(undefined).exec(undefined), undefined) + t.strictEqual(createSatisfier(undefined).exec({}), undefined) + t.strictEqual(createSatisfier({ a: undefined }).exec({}), undefined) + t.strictEqual(createSatisfier([undefined]).exec([]), undefined) + }) + + test('primitive types without specifing generic will work without issue.', () => { + t.strictEqual(createSatisfier(1).exec(1), undefined) + t.strictEqual(createSatisfier(true).exec(true), undefined) + t.strictEqual(createSatisfier('a').exec('a'), undefined) + }) + + test('can use generic to specify the data structure', () => { + t.strictEqual(createSatisfier(1).exec(1), undefined) + t.strictEqual(createSatisfier<{ a: number }>({ a: /1/ }).exec({ a: 1 }), undefined) + }) + + test('empty object expectation passes all objects', () => { + t.strictEqual(createSatisfier({}).exec({}), undefined) + t.strictEqual(createSatisfier({}).exec({ a: 1 }), undefined) + t.strictEqual(createSatisfier({}).exec({ a: { b: 'a' } }), undefined) + t.strictEqual(createSatisfier({}).exec({ a: true }), undefined) + t.strictEqual(createSatisfier({}).exec({ a: [1] }), undefined) + }) + + test('empty object expectation fails primitive', () => { + assertExec(createSatisfier({}).exec(1)![0], [], {}, 1) + assertExec(createSatisfier({}).exec(true)![0], [], {}, true) + assertExec(createSatisfier({}).exec('a')![0], [], {}, 'a') + }) + + test('mismatch value gets path, expected, and actual', () => { + const actual = createSatisfier({ a: 1 }).exec({ a: 2 })! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a'], 1, 2) + }) + + test('missing property get actual as undefined', () => { + const actual = createSatisfier({ a: 1 }).exec({})! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a'], 1, undefined) + }) + + test('missing property get deeper level', () => { + const actual = createSatisfier({ a: { b: 1 } }).exec({ a: {} })! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a', 'b'], 1, undefined) + }) + + test('passing regex gets undefined', () => { + t.strictEqual(createSatisfier({ foo: /foo/ }).exec({ foo: 'foo' }), undefined) + }) + + test('failed regex will be in expected property', () => { + const actual = createSatisfier({ foo: /foo/ }).exec({ foo: 'boo' })! + assertRegExp(actual, ['foo'], /foo/, 'boo') + }) + + test('regex on missing property gets actual as undefined', () => { + const actual = createSatisfier({ foo: /foo/ }).exec({})! + assertRegExp(actual, ['foo'], /foo/, undefined) + }) + + test('regex on non-string will fail as normal', () => { + let actual = createSatisfier({ foo: /foo/ }).exec({ foo: 1 })! + assertRegExp(actual, ['foo'], /foo/, 1) + + actual = createSatisfier({ foo: /foo/ }).exec({ foo: true })! + assertRegExp(actual, ['foo'], /foo/, true) + + actual = createSatisfier({ foo: /foo/ }).exec({ foo: [1, true, 'a'] })! + assertRegExp(actual, ['foo'], /foo/, [1, true, 'a']) + + actual = createSatisfier({ foo: /foo/ }).exec({ foo: { a: 1 } })! + assertRegExp(actual, ['foo'], /foo/, { a: 1 }) + }) + + test('predicate receives actual value', () => { + t.strictEqual(createSatisfier({ a: a => a === 1 }).exec({ a: 1 }), undefined) + }) + + test('passing predicate gets undefined', () => { + t.strictEqual(createSatisfier({ a: () => true }).exec({}), undefined) + t.strictEqual(createSatisfier({ a: () => true }).exec({ a: 1 }), undefined) + }) + + test('failing predicate', () => { + const actual = createSatisfier({ a: /*istanbul ignore next*/function () { return false } }).exec({ a: 1 })! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a'], /*istanbul ignore next*/function () { return false; }, 1) + }) + + test('against each element in array', () => { + t.strictEqual(createSatisfier({ a: 1 }).exec([{ a: 1 }, { b: 1, a: 1 }]), undefined) + }) + + test('against each element in array in deep level', () => { + const actual = createSatisfier({ a: { b: { c: /foo/ } } }).exec([{ a: {} }, { a: { b: {} } }, { a: { b: { c: 'boo' } } }])! + t.strictEqual(actual.length, 3) + assertExec(actual[0], ['[0]', 'a', 'b'], { c: /foo/ }, undefined) + assertExec(actual[1], ['[1]', 'a', 'b', 'c'], /foo/, undefined) + assertExec(actual[2], ['[2]', 'a', 'b', 'c'], /foo/, 'boo') + }) + + test('when apply against array, will have indices in the path', () => { + const actual = createSatisfier({ a: 1 }).exec([{ a: 1 }, {}])! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['[1]', 'a'], 1, undefined) + }) + + test('when expectation is an array, apply to each entry in the actual array', () => { + t.strictEqual(createSatisfier([{ a: 1 }, { b: 2 }]).exec([{ a: 1 }, { b: 2 }, { c: 3 }]), undefined) + const actual = createSatisfier([{ a: 1 }, { b: 2 }]).exec([{ a: true }, { b: 'b' }, { c: 3 }])! + t.strictEqual(actual.length, 2) + assertExec(actual[0], ['[0]', 'a'], 1, true) + assertExec(actual[1], ['[1]', 'b'], 2, 'b') + }) + + test.skip('when expectation is an array and actual is not, the behavior is not defined yet', () => { + const actual = createSatisfier([{ a: 1 }, { b: 2 }]).exec({ a: 1 })! + t.strictEqual(actual.length, 1) + }) + + test('deep object checking', () => { + const actual = createSatisfier({ a: { b: 1 } }).exec({ a: { b: 2 } })! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a', 'b'], 1, 2) + }) + + test('can check parent property', () => { + class Foo { + foo = 'foo' + } + class Boo extends Foo { + boo = 'boo' + } + const boo = new Boo() + t.strictEqual(createSatisfier({ foo: 'foo' }).exec(boo), undefined) + }) + + test('actual of type any should not have type checking error', () => { + let actual: any = { a: 1 } + t.strictEqual(createSatisfier({ a: 1 }).exec(actual), undefined) + }) + + test('expect array in hash', () => { + t.strictEqual(createSatisfier({ a: [1, true, 'a'] }).exec({ a: [1, true, 'a'] }), undefined) + }) + + test('failing array in hash', () => { + const actual = createSatisfier({ a: [1, true, 'a'] }).exec({ a: [1, true, 'b'] })! + t.strictEqual(actual.length, 1) + assertExec(actual[0], ['a', '[2]'], 'a', 'b') + }) + + test('apply property predicate to array', () => { + const satisfier = createSatisfier({ + data: e => e && e.every(x => x.login) + }); + + t.strictEqual(satisfier.exec({ data: [{ login: 'a' }] }), undefined) + t.notStrictEqual(satisfier.exec([{ data: [{ foo: 'a' }] }]), undefined) + t.notStrictEqual(satisfier.exec([{ foo: 'b' }]), undefined) + }) +}) + +describe('test', () => { + test('empty expecter passes everything but not null or undefined', () => { + t(createSatisfier({}).test({})) + t(createSatisfier({}).test({ a: 1 })) + t(createSatisfier({}).test({ a: true })) + t(createSatisfier({}).test({ a: 'a' })) + t(createSatisfier({}).test({ a: [1, true, 'a'] })) + t(createSatisfier({}).test({ a: { b: 'a' } })) + t(createSatisfier({}).test([{}, { a: 1 }])) + a.false(createSatisfier({}).test(null)) + a.false(createSatisfier({}).test(undefined as any)) + }) + + test('expect null to pass only null', () => { + t(createSatisfier(null).test(null)) + a.false(createSatisfier(null).test(undefined as any)) + a.false(createSatisfier(null).test(0)) + a.false(createSatisfier(null).test(false)) + a.false(createSatisfier(null).test('')) + }) + + test('mismatch value fails', () => { + a.false(createSatisfier({ a: 1 }).test({ a: 2 })) + a.false(createSatisfier({ a: true }).test({ a: false })) + a.false(createSatisfier({ a: 'a' }).test({ a: 'b' })) + a.false(createSatisfier({ a: /foo/ }).test({ a: 'b' })) + a.false(createSatisfier({ a: () => false }).test({ a: 'b' })) + a.false(createSatisfier([{ a: 1 }, { b: 2 }]).test([{ a: true }, { b: 'b' }, { c: 3 }])) + a.false(createSatisfier({ a: [1, true, 'a'] }).test({ a: [1, true, 'b'] })) + a.false(createSatisfier({ a: { b: 1 } }).test({ a: { b: 2 } })) + }) + + test('undefined expectation are ignored', () => { + const s = createSatisfier([undefined, 1]) + t(s.test([undefined, 1])) + t(s.test([null, 1])) + t(s.test([1, 1])) + t(s.test(['a', 1])) + t(s.test([true, 1])) + t(s.test([{ a: 1 }, 1])) + t(s.test([[1, 2], 1])) + }) + + test('undefined expectation are ignored', () => { + const s = createSatisfier({ a: [undefined, 1] }) + t(s.test({ a: [undefined, 1] })) + t(s.test({ a: [null, 1] })) + t(s.test({ a: [1, 1] })) + t(s.test({ a: ['a', 1] })) + t(s.test({ a: [true, 1] })) + t(s.test({ a: [{ a: 1 }, 1] })) + t(s.test({ a: [[1, 2], 1] })) + }) + + test('predicate receives array', () => { + t(createSatisfier(e => { + return e[0] === 'a' && e[1] === 'b' + }).test(['a', 'b'])) + }) + + test('primitive predicate will check against element in array', () => { + t(createSatisfier(1).test([1, 1])) + a.false(createSatisfier(1).test([1, 2])) + t(createSatisfier(false).test([false, false])) + a.false(createSatisfier(false).test([false, true])) + t(createSatisfier('a').test(['a', 'a'])) + a.false(createSatisfier('a').test(['a', 'b'])) + }) + + + test('object predicate will check against element in array', () => { + t(createSatisfier({ a: 1 }).test([{ a: 1 }, { a: 1 }])) + t(createSatisfier({ a: e => typeof e === 'string' }) + .test([{ a: 'a' }, { a: 'b' }])) + }) +}) diff --git a/src/createSatisfier.test.spec.ts b/src/createSatisfier.test.spec.ts deleted file mode 100644 index 6a47333..0000000 --- a/src/createSatisfier.test.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import t from 'assert' -import a from 'assertron' - -import { createSatisfier } from './index' - -test('empty expecter passes everything but not null or undefined', () => { - t(createSatisfier({}).test({})) - t(createSatisfier({}).test({ a: 1 })) - t(createSatisfier({}).test({ a: true })) - t(createSatisfier({}).test({ a: 'a' })) - t(createSatisfier({}).test({ a: [1, true, 'a'] })) - t(createSatisfier({}).test({ a: { b: 'a' } })) - t(createSatisfier({}).test([{}, { a: 1 }])) - a.false(createSatisfier({}).test(null)) - a.false(createSatisfier({}).test(undefined as any)) -}) - -test('expect null to pass only null', () => { - t(createSatisfier(null).test(null)) - a.false(createSatisfier(null).test(undefined as any)) - a.false(createSatisfier(null).test(0)) - a.false(createSatisfier(null).test(false)) - a.false(createSatisfier(null).test('')) -}) - -test('mismatch value fails', () => { - a.false(createSatisfier({ a: 1 }).test({ a: 2 })) - a.false(createSatisfier({ a: true }).test({ a: false })) - a.false(createSatisfier({ a: 'a' }).test({ a: 'b' })) - a.false(createSatisfier({ a: /foo/ }).test({ a: 'b' })) - a.false(createSatisfier({ a: () => false }).test({ a: 'b' })) - a.false(createSatisfier([{ a: 1 }, { b: 2 }]).test([{ a: true }, { b: 'b' }, { c: 3 }])) - a.false(createSatisfier({ a: [1, true, 'a'] }).test({ a: [1, true, 'b'] })) - a.false(createSatisfier({ a: { b: 1 } }).test({ a: { b: 2 } })) -}) - -test('undefined expectation are ignored', () => { - const s = createSatisfier([undefined, 1]) - t(s.test([undefined, 1])) - t(s.test([null, 1])) - t(s.test([1, 1])) - t(s.test(['a', 1])) - t(s.test([true, 1])) - t(s.test([{ a: 1 }, 1])) - t(s.test([[1, 2], 1])) -}) - -test('undefined expectation are ignored', () => { - const s = createSatisfier({ a: [undefined, 1] }) - t(s.test({ a: [undefined, 1] })) - t(s.test({ a: [null, 1] })) - t(s.test({ a: [1, 1] })) - t(s.test({ a: ['a', 1] })) - t(s.test({ a: [true, 1] })) - t(s.test({ a: [{ a: 1 }, 1] })) - t(s.test({ a: [[1, 2], 1] })) -}) - -test('predicate receives array', () => { - t(createSatisfier(e => { - return e[0] === 'a' && e[1] === 'b' - }).test(['a', 'b'])) -}) - -test('primitive predicate will check against element in array', () => { - t(createSatisfier(1).test([1, 1])) - a.false(createSatisfier(1).test([1, 2])) - t(createSatisfier(false).test([false, false])) - a.false(createSatisfier(false).test([false, true])) - t(createSatisfier('a').test(['a', 'a'])) - a.false(createSatisfier('a').test(['a', 'b'])) -}) - - -test('object predicate will check against element in array', () => { - t(createSatisfier({ a: 1 }).test([{ a: 1 }, { a: 1 }])) - t(createSatisfier({ a: e => typeof e === 'string' }) - .test([{ a: 'a' }, { a: 'b' }])) -}) diff --git a/src/createSatisfier.ts b/src/createSatisfier.ts index a6f83dd..9875685 100644 --- a/src/createSatisfier.ts +++ b/src/createSatisfier.ts @@ -37,6 +37,11 @@ export function createSatisfier(expectation: any): Satisfier { diff.push(...detectDiff(actual[a], e, [`[${a}]`], a)) a = a + 1 }) + // if (actual.length > exp.length) { + // for (let i = exp.length; i < actual.length; i++) { + // diff.push({ path: [`[${i}]`], expected: undefined, actual: actual[i] }) + // } + // } } else if (typeof expectation === 'function') { diff.push(...detectDiff(actual, expectation)) diff --git a/src/exact.spec.ts b/src/exact.spec.ts new file mode 100644 index 0000000..ac31432 --- /dev/null +++ b/src/exact.spec.ts @@ -0,0 +1,10 @@ +// import t from 'assert'; +// import a from 'assertron'; +// import { createSatisfier } from '.'; + +test.skip('extra entry in array should fail', () => { + // const diff = createSatisfier(exact([1])).exec([1, 2]) + // t.strictEqual(diff!.length, 1) + // a.satisfy(diff![0], { path: ['[1]'], expected: undefined, actual: 2 }) +}) + diff --git a/src/exact.ts b/src/exact.ts new file mode 100644 index 0000000..6c4d087 --- /dev/null +++ b/src/exact.ts @@ -0,0 +1,19 @@ +// import { SatisfierExec } from './interfaces'; + + +// export function exact(expected: any) { +// if (Array.isArray(expected)) { +// return exactArray(expected) +// } + +// return function (value) { +// return false +// } +// } + +// function exactArray(expectation: any[]) { +// const diff: SatisfierExec[] = [] +// return function (actual: any) { +// // diff.push(...detectDiff(actual, expectation, [`[${i}]`], i)) +// } +// } diff --git a/src/index.ts b/src/index.ts index f2a2500..95b6f94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ -export * from './AtLeastOnce' -export * from './ArrayEntryExpectation' -export * from './createSatisfier' -export * from './every' -export * from './has' -export * from './interfaces' -export * from './isInRange' -export * from './isInInterval' -export * from './isTypeOf' -export * from './none' -export * from './some' +export * from './ArrayEntryExpectation'; +export * from './AtLeastOnce'; +export * from './createSatisfier'; +export * from './every'; +export * from './has'; +export * from './interfaces'; +export * from './isInInterval'; +export * from './isInRange'; +export * from './isTypeOf'; +export * from './none'; +export * from './some'; diff --git a/src/isInInterval.ts b/src/isInInterval.ts index 131e61a..0e4b674 100644 --- a/src/isInInterval.ts +++ b/src/isInInterval.ts @@ -7,14 +7,14 @@ import { } from 'tersify' export function isInOpenInterval(start: number, end: number) { - return tersible(a => a > start && a < end, () => `(${start}...${end})`) + return tersible(a => a > start && (a < end), () => `(${start}...${end})`) } export function isInClosedInterval(start: number, end: number) { return tersible(a => a >= start && a <= end, () => `[${start}...${end}]`) } export function isInLeftClosedInterval(start: number, end: number) { - return tersible(a => a >= start && a < end, () => `[${start}...${end})`) + return tersible(a => a >= start && (a < end), () => `[${start}...${end})`) } export function isInRightClosedInterval(start: number, end: number) {