From f5b9e3d485dbb9ff903758ab3afc1a2ebb749ffb Mon Sep 17 00:00:00 2001 From: unional Date: Sat, 23 Apr 2022 21:38:05 -0700 Subject: [PATCH] fix: clarify return types of predefined predicates --- package.json | 1 - ts/anything.spec.ts | 20 ++++++++++++++++++++ ts/createSatisfier.spec.ts | 29 +++++------------------------ ts/createSatisfier.ts | 4 +--- ts/every.ts | 5 +++-- ts/formatDiffs.spec.ts | 2 +- ts/formatDiffs.ts | 4 ++-- ts/has.spec.ts | 6 +++--- ts/has.ts | 5 +++-- ts/index.ts | 26 +++++++++++++------------- ts/isInInterval.spec.ts | 6 +++--- ts/isInInterval.ts | 11 ++++++----- ts/isInRange.ts | 5 +++-- ts/isTypeOf.ts | 5 +++-- ts/none.spec.ts | 6 +++--- ts/none.ts | 5 +++-- ts/satisfies.spec.ts | 2 +- ts/satisfies.ts | 4 ++-- ts/some.spec.ts | 4 ++-- ts/some.ts | 5 +++-- ts/startsWith.spec.ts | 3 +-- ts/startsWith.ts | 4 ++-- ts/testPredicates.ts | 7 +++++++ yarn.lock | 7 ------- 24 files changed, 90 insertions(+), 86 deletions(-) create mode 100644 ts/anything.spec.ts create mode 100644 ts/testPredicates.ts diff --git a/package.json b/package.json index ff39c11..86001cd 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,6 @@ "eslint": "8.14.0", "eslint-plugin-harmony": "^6.0.3", "husky": "^7.0.4", - "is-ci": "^3.0.1", "jest": "27.5.1", "jest-validate": "27.5.1", "jest-watch-suspend": "^1.1.2", diff --git a/ts/anything.spec.ts b/ts/anything.spec.ts new file mode 100644 index 0000000..5a51a69 --- /dev/null +++ b/ts/anything.spec.ts @@ -0,0 +1,20 @@ +import { anything } from './anything' +import { createSatisfier } from './createSatisfier' +import { testArrow, testFn, testSymbol } from './testPredicates' + + +test('matches against anything', () => { + const s = createSatisfier(anything) + expect(s.exec(undefined)).toBeUndefined() + expect(s.exec(null)).toBeUndefined() + expect(s.exec(false)).toBeUndefined() + expect(s.exec(1)).toBeUndefined() + expect(s.exec(1n)).toBeUndefined() + expect(s.exec('a')).toBeUndefined() + expect(s.exec(Symbol())).toBeUndefined() + expect(s.exec({})).toBeUndefined() + expect(s.exec([])).toBeUndefined() + expect(s.exec(testSymbol)).toBeUndefined() + expect(s.exec(testFn)).toBeUndefined() + expect(s.exec(testArrow)).toBeUndefined() +}) diff --git a/ts/createSatisfier.spec.ts b/ts/createSatisfier.spec.ts index 4d705d8..6c55ffd 100644 --- a/ts/createSatisfier.spec.ts +++ b/ts/createSatisfier.spec.ts @@ -1,25 +1,6 @@ -import { assertType } from 'type-plus' +import { isType } from 'type-plus' import { anything, createSatisfier } from '.' - -const testSymbol = Symbol() -const testArrow = () => true -const testFn = function () { return true } -describe('anything', () => { - test('matches against anything', () => { - const s = createSatisfier(anything) - expect(s.exec(undefined)).toBeUndefined() - expect(s.exec(null)).toBeUndefined() - expect(s.exec(false)).toBeUndefined() - expect(s.exec(1)).toBeUndefined() - expect(s.exec(1n)).toBeUndefined() - expect(s.exec('a')).toBeUndefined() - expect(s.exec(Symbol())).toBeUndefined() - expect(s.exec({})).toBeUndefined() - expect(s.exec([])).toBeUndefined() - expect(s.exec(testFn)).toBeUndefined() - expect(s.exec(testArrow)).toBeUndefined() - }) -}) +import { testArrow, testFn, testSymbol } from './testPredicates' describe('undefined', () => { test('matches only undefined', () => { @@ -306,7 +287,7 @@ describe('object', () => { const predicate = (e: any) => e && e.every((x: any) => x.login) const s = createSatisfier({ data: predicate - }); + }) expect(s.exec({ data: [{ login: 'a' }] })).toBeUndefined() expect(s.exec({ data: [{ login: 'a' }, { login: 'b' }] })).toBeUndefined() @@ -375,7 +356,7 @@ describe('predicate function', () => { }) test('apply property predicate', () => { - const s = createSatisfier({ data: v => v === 1 }); + const s = createSatisfier({ data: v => v === 1 }) expect(s.exec({ data: 1 })).toBeUndefined() expect(s.exec({ data: 2 })).toEqual([{ path: ['data'], expected: s.expected.data, actual: 2 }]) @@ -386,7 +367,7 @@ describe('predicate function', () => { test('use generic to lock in the type of the input', () => { const s = createSatisfier<{ a: number }>(undefined) const y: Parameters = {} as any - assertType<{ a: number }>(y[0]) + isType.equal() }) describe('test()', () => { diff --git a/ts/createSatisfier.ts b/ts/createSatisfier.ts index eed999c..1f2b101 100644 --- a/ts/createSatisfier.ts +++ b/ts/createSatisfier.ts @@ -1,10 +1,8 @@ import { anything } from './anything' import { Diff, Predicate, Satisfier } from './interfaces' -export interface ExpectionArray extends Array { } - export type Expectation = symbol | undefined | null | boolean | number | bigint | - string | RegExp | ExpectionArray | { [key: string]: Expectation } | Predicate + string | RegExp | Array | { [key: string]: Expectation } | Predicate export function createSatisfier(expected: Expectation): Satisfier { return { diff --git a/ts/every.ts b/ts/every.ts index 932f805..86ccae1 100644 --- a/ts/every.ts +++ b/ts/every.ts @@ -1,11 +1,12 @@ -import { tersible, tersify } from 'tersify' +import { Tersible, tersible, tersify } from 'tersify' import { createSatisfier } from './createSatisfier' +import { Predicate } from './interfaces' /** * Check if every entry in the array satisfies the expectation. * @param expectation expectation */ -export function every(expectation: any) { +export function every(expectation: any): Tersible { const s = createSatisfier(expectation) return tersible((e: any) => e && Array.isArray(e) && e.reduce((p, v, i) => { const d = s.exec(v) diff --git a/ts/formatDiffs.spec.ts b/ts/formatDiffs.spec.ts index 39b2718..e27a52e 100644 --- a/ts/formatDiffs.spec.ts +++ b/ts/formatDiffs.spec.ts @@ -1,4 +1,4 @@ -import { createSatisfier, every, formatDiffs, has } from '.'; +import { createSatisfier, every, formatDiffs, has } from '.' test('index is wrapped with []', () => { const diffs = createSatisfier(every({ a: { b: { c: /foo/ } } })).exec([{ a: {} }, { a: { b: {} } }, { a: { b: { c: 'boo' } } }]) diff --git a/ts/formatDiffs.ts b/ts/formatDiffs.ts index 9c0762d..0306ecd 100644 --- a/ts/formatDiffs.ts +++ b/ts/formatDiffs.ts @@ -1,5 +1,5 @@ -import { tersify } from 'tersify'; -import { Diff } from './interfaces'; +import { tersify } from 'tersify' +import { Diff } from './interfaces' export function formatDiffs(diffs: Diff[] | undefined) { if (!diffs) return '' diff --git a/ts/has.spec.ts b/ts/has.spec.ts index 7804696..f3dfe2d 100644 --- a/ts/has.spec.ts +++ b/ts/has.spec.ts @@ -1,6 +1,6 @@ -import t from 'assert'; -import a from 'assertron'; -import { createSatisfier, has } from '.'; +import t from 'assert' +import a from 'assertron' +import { createSatisfier, has } from '.' test('non array returns false', () => { a.false(createSatisfier(has(1)).test(undefined)) diff --git a/ts/has.ts b/ts/has.ts index e49c78a..99770fb 100644 --- a/ts/has.ts +++ b/ts/has.ts @@ -1,10 +1,11 @@ -import { tersible, tersify } from 'tersify' +import { Tersible, tersible, tersify } from 'tersify' import { createSatisfier } from './createSatisfier' +import { Predicate } from './interfaces' /** * Check if an array has entries satisfy the expectations in order. */ -export function has(...expectations: any[]) { +export function has(...expectations: any[]): Tersible { return tersible((arr: any) => { if (!Array.isArray(arr)) return false let index = 0 diff --git a/ts/index.ts b/ts/index.ts index 037f2e0..ff77aeb 100644 --- a/ts/index.ts +++ b/ts/index.ts @@ -1,13 +1,13 @@ -export * from './anything'; -export * from './createSatisfier'; -export * from './every'; -export * from './formatDiffs'; -export * from './has'; -export * from './interfaces'; -export * from './isInInterval'; -export * from './isInRange'; -export * from './isTypeOf'; -export * from './none'; -export * from './satisfies'; -export * from './some'; -export * from './startsWith'; +export * from './anything' +export * from './createSatisfier' +export * from './every' +export * from './formatDiffs' +export * from './has' +export * from './interfaces' +export * from './isInInterval' +export * from './isInRange' +export * from './isTypeOf' +export * from './none' +export * from './satisfies' +export * from './some' +export * from './startsWith' diff --git a/ts/isInInterval.spec.ts b/ts/isInInterval.spec.ts index 7c75e30..7ae5b15 100644 --- a/ts/isInInterval.spec.ts +++ b/ts/isInInterval.spec.ts @@ -1,6 +1,6 @@ -import t from 'assert'; -import a from 'assertron'; -import { createSatisfier, isInClosedInterval, isInLeftClosedInterval, isInOpenInterval, isInRightClosedInterval } from '.'; +import t from 'assert' +import a from 'assertron' +import { createSatisfier, isInClosedInterval, isInLeftClosedInterval, isInOpenInterval, isInRightClosedInterval } from '.' test('open interval', () => { a.false(createSatisfier(isInOpenInterval(1, 3)).test(1)) diff --git a/ts/isInInterval.ts b/ts/isInInterval.ts index ac75a56..5062812 100644 --- a/ts/isInInterval.ts +++ b/ts/isInInterval.ts @@ -1,16 +1,17 @@ -import { tersible } from 'tersify' +import { Tersible, tersible } from 'tersify' +import { Predicate } from './interfaces' -export function isInOpenInterval(start: number, end: number) { +export function isInOpenInterval(start: number, end: number): Tersible { return tersible((a: any) => a > start && (a < end), () => `(${start}...${end})`) } -export function isInClosedInterval(start: number, end: number) { +export function isInClosedInterval(start: number, end: number): Tersible { return tersible((a: any) => a >= start && a <= end, () => `[${start}...${end}]`) } -export function isInLeftClosedInterval(start: number, end: number) { +export function isInLeftClosedInterval(start: number, end: number): Tersible { return tersible((a: any) => a >= start && (a < end), () => `[${start}...${end})`) } -export function isInRightClosedInterval(start: number, end: number) { +export function isInRightClosedInterval(start: number, end: number): Tersible { return tersible((a: any) => a > start && a <= end, () => `(${start}...${end}]`) } diff --git a/ts/isInRange.ts b/ts/isInRange.ts index b39d7cc..d567ce1 100644 --- a/ts/isInRange.ts +++ b/ts/isInRange.ts @@ -1,5 +1,6 @@ -import { tersible } from 'tersify' +import { Tersible, tersible } from 'tersify' +import { Predicate } from './interfaces' -export function isInRange(start: number, end: number) { +export function isInRange(start: number, end: number): Tersible { return tersible((a: any) => a >= start && a <= end, () => `[${start}...${end}]`) } diff --git a/ts/isTypeOf.ts b/ts/isTypeOf.ts index 07393af..67145e6 100644 --- a/ts/isTypeOf.ts +++ b/ts/isTypeOf.ts @@ -1,6 +1,7 @@ -import { tersible } from 'tersify' +import { Tersible, tersible } from 'tersify' +import { Predicate } from './interfaces' -export function isTypeOf(x: 'number' | 'boolean' | 'string') { +export function isTypeOf(x: 'number' | 'boolean' | 'string'): Tersible{ return tersible( // tslint:disable-next-line:strict-type-predicates (a: any) => typeof a === x, diff --git a/ts/none.spec.ts b/ts/none.spec.ts index 7c0eee6..b5b84e3 100644 --- a/ts/none.spec.ts +++ b/ts/none.spec.ts @@ -1,6 +1,6 @@ -import t from 'assert'; -import a from 'assertron'; -import { createSatisfier, none } from '.'; +import t from 'assert' +import a from 'assertron' +import { createSatisfier, none } from '.' test('non array returns false', () => { a.false(createSatisfier(none({ a: 1 })).test(true)) diff --git a/ts/none.ts b/ts/none.ts index a886944..a13a4e1 100644 --- a/ts/none.ts +++ b/ts/none.ts @@ -1,11 +1,12 @@ -import { tersible, tersify } from 'tersify' +import { Tersible, tersible, tersify } from 'tersify' import { createSatisfier } from './createSatisfier' +import { Predicate } from './interfaces' /** * Check if an array have no entry satisfying the expectation. * @param expectation expectation */ -export function none(expectation: any) { +export function none(expectation: any): Tersible { const s = createSatisfier(expectation) return tersible((e: any) => e && Array.isArray(e) && !e.some(v => s.test(v)), () => `none(${tersify(expectation)})`) } diff --git a/ts/satisfies.spec.ts b/ts/satisfies.spec.ts index 0ffb694..44a986e 100644 --- a/ts/satisfies.spec.ts +++ b/ts/satisfies.spec.ts @@ -47,4 +47,4 @@ describe('when actual is array', () => { test('expected entry can be predicate', () => { expect(satisfies([{ a: 1 }], [v => v.a === 1])).toBe(true) }) -}); +}) diff --git a/ts/satisfies.ts b/ts/satisfies.ts index 20e589d..86529ee 100644 --- a/ts/satisfies.ts +++ b/ts/satisfies.ts @@ -1,5 +1,5 @@ -import { createSatisfier } from './createSatisfier'; -import { Predicate } from './interfaces'; +import { createSatisfier } from './createSatisfier' +import { Predicate } from './interfaces' export type TargetedExpectation = ( T extends Array ? Array> : diff --git a/ts/some.spec.ts b/ts/some.spec.ts index 8ce31c9..cdc4d22 100644 --- a/ts/some.spec.ts +++ b/ts/some.spec.ts @@ -1,7 +1,7 @@ import t from 'assert' import a from 'assertron' -import { createSatisfier, some } from '.' +import { createSatisfier, satisfies, some } from '.' test('non array returns false', () => { a.false(createSatisfier(some({ a: 1 })).test(true)) @@ -29,5 +29,5 @@ test('tersify()', () => { }) test('match second', () => { - a.satisfies(['first', 'second'], some('second')) + satisfies(['first', 'second'], some('second')) }) diff --git a/ts/some.ts b/ts/some.ts index e4e6609..7c4c3a8 100644 --- a/ts/some.ts +++ b/ts/some.ts @@ -1,11 +1,12 @@ -import { tersible, tersify } from 'tersify' +import { Tersible, tersible, tersify } from 'tersify' import { createSatisfier, Expectation } from './createSatisfier' +import { Predicate } from './interfaces' /** * Check if an array have at least one entry satisfying the expectation. * @param expectation expectation */ -export function some(expectation: E) { +export function some(expectation: E): Tersible { const s = createSatisfier(expectation) return tersible((e: any) => e && Array.isArray(e) && e.some(v => s.test(v)), () => `some(${tersify(expectation)})`) } diff --git a/ts/startsWith.spec.ts b/ts/startsWith.spec.ts index 943daa5..536452e 100644 --- a/ts/startsWith.spec.ts +++ b/ts/startsWith.spec.ts @@ -1,5 +1,4 @@ -import { createSatisfier } from 'satisfier' -import { startsWith } from '.' +import { createSatisfier, startsWith } from '.' test('non array returns false', () => { expect(createSatisfier(startsWith([{ a: 1 }])).test(undefined)).toBe(false) diff --git a/ts/startsWith.ts b/ts/startsWith.ts index e174642..31495e3 100644 --- a/ts/startsWith.ts +++ b/ts/startsWith.ts @@ -1,5 +1,5 @@ -import { tersible, tersify } from 'tersify'; -import { createSatisfier } from './createSatisfier'; +import { tersible, tersify } from 'tersify' +import { createSatisfier } from './createSatisfier' /** diff --git a/ts/testPredicates.ts b/ts/testPredicates.ts new file mode 100644 index 0000000..c9b1559 --- /dev/null +++ b/ts/testPredicates.ts @@ -0,0 +1,7 @@ +/** + * internal for testing + */ + +export const testSymbol = Symbol() +export const testArrow = () => true +export const testFn = function () { return true } diff --git a/yarn.lock b/yarn.lock index c3b8d34..b70c42a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3665,13 +3665,6 @@ is-callable@^1.1.4, is-callable@^1.2.4: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== -is-ci@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" - integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== - dependencies: - ci-info "^3.2.0" - is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.8.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"