assertron 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +11 -29
- package/cjs/assert-order/AssertOrder.js +7 -7
- package/cjs/assert-order/InvalidOrder.d.ts +5 -6
- package/cjs/assert-order/InvalidOrder.d.ts.map +1 -1
- package/cjs/assert-order/InvalidOrder.js +9 -14
- package/cjs/assert-order/StateMachine.d.ts +1 -1
- package/cjs/assert-order/StateMachine.d.ts.map +1 -1
- package/cjs/assert-order/StateMachine.js +1 -1
- package/cjs/assert-order/index.d.ts +2 -1
- package/cjs/assert-order/index.d.ts.map +1 -1
- package/cjs/assert-order/index.js +3 -2
- package/cjs/assert-order/{interfaces.d.ts → types.d.ts} +1 -1
- package/cjs/assert-order/types.d.ts.map +1 -0
- package/cjs/assert-order/types.js +3 -0
- package/cjs/assertron/assertron.d.ts.map +1 -1
- package/cjs/assertron/assertron.js +5 -5
- package/cjs/assertron/falsy.d.ts.map +1 -1
- package/cjs/assertron/falsy.js +3 -4
- package/cjs/assertron/pathEqual.d.ts.map +1 -1
- package/cjs/assertron/pathEqual.js +3 -4
- package/cjs/assertron/rejects.d.ts.map +1 -1
- package/cjs/assertron/rejects.js +4 -8
- package/cjs/assertron/repeat.d.ts +0 -8
- package/cjs/assertron/repeat.d.ts.map +1 -1
- package/cjs/assertron/repeat.js +6 -17
- package/cjs/assertron/resolves.d.ts.map +1 -1
- package/cjs/assertron/resolves.js +4 -11
- package/cjs/assertron/satisfies.d.ts +4 -4
- package/cjs/assertron/satisfies.d.ts.map +1 -1
- package/cjs/assertron/satisfies.js +3 -4
- package/cjs/assertron/throws.d.ts +1 -1
- package/cjs/assertron/throws.d.ts.map +1 -1
- package/cjs/assertron/throws.js +25 -31
- package/cjs/assertron/truthy.d.ts.map +1 -1
- package/cjs/assertron/truthy.js +3 -4
- package/cjs/errors.d.ts +17 -0
- package/cjs/errors.d.ts.map +1 -0
- package/cjs/errors.js +29 -0
- package/cjs/index.d.ts +2 -1
- package/cjs/index.d.ts.map +1 -1
- package/cjs/index.js +3 -2
- package/cjs/{errors/interfaces.d.ts → types.d.ts} +1 -1
- package/cjs/types.d.ts.map +1 -0
- package/cjs/types.js +3 -0
- package/cjs/utils/index.d.ts +8 -0
- package/cjs/utils/index.d.ts.map +1 -0
- package/cjs/utils/index.js +16 -0
- package/cjs/{errors/util.d.ts → utils/isErrorConstructor.d.ts} +2 -2
- package/cjs/utils/isErrorConstructor.d.ts.map +1 -0
- package/cjs/utils/isErrorConstructor.js +8 -0
- package/cjs/{errors → utils}/notEqualMessage.d.ts +0 -0
- package/cjs/utils/notEqualMessage.d.ts.map +1 -0
- package/cjs/{errors → utils}/notEqualMessage.js +2 -2
- package/cjs/{errors/NotSatisfied.d.ts → utils/notSatisfiedMessage.d.ts} +1 -1
- package/cjs/utils/notSatisfiedMessage.d.ts.map +1 -0
- package/cjs/utils/notSatisfiedMessage.js +28 -0
- package/cjs/{errors → utils}/notThrownMessage.d.ts +0 -0
- package/cjs/utils/notThrownMessage.d.ts.map +1 -0
- package/cjs/{errors → utils}/notThrownMessage.js +1 -1
- package/cjs/utils/promiseMessages.d.ts +3 -0
- package/cjs/utils/promiseMessages.d.ts.map +1 -0
- package/cjs/utils/promiseMessages.js +15 -0
- package/cjs/{errors → utils}/unexpectedErrorMessage.d.ts +1 -1
- package/cjs/utils/unexpectedErrorMessage.d.ts.map +1 -0
- package/cjs/utils/unexpectedErrorMessage.js +11 -0
- package/esm/assert-order/AssertOrder.js +7 -7
- package/esm/assert-order/InvalidOrder.js +8 -8
- package/esm/assert-order/StateMachine.js +1 -1
- package/esm/assert-order/index.js +3 -2
- package/esm/assert-order/types.js +2 -0
- package/esm/assertron/assertron.js +5 -4
- package/esm/assertron/falsy.js +3 -3
- package/esm/assertron/pathEqual.js +4 -4
- package/esm/assertron/rejects.js +4 -7
- package/esm/assertron/repeat.js +4 -11
- package/esm/assertron/resolves.js +4 -10
- package/esm/assertron/satisfies.js +4 -4
- package/esm/assertron/throws.js +26 -32
- package/esm/assertron/truthy.js +3 -3
- package/esm/errors.js +18 -0
- package/esm/index.js +3 -2
- package/esm/types.js +2 -0
- package/esm/utils/index.js +11 -0
- package/esm/utils/isErrorConstructor.js +4 -0
- package/esm/utils/notEqualMessage.js +4 -0
- package/esm/utils/notSatisfiedMessage.js +23 -0
- package/esm/{errors → utils}/notThrownMessage.js +1 -1
- package/esm/utils/promiseMessages.js +10 -0
- package/esm/utils/unexpectedErrorMessage.js +7 -0
- package/package.json +17 -18
- package/src/assert-order/AssertOrder.spec.ts +10 -11
- package/src/assert-order/AssertOrder.ts +6 -6
- package/src/assert-order/InvalidOrder.ts +7 -9
- package/src/assert-order/StateMachine.ts +2 -3
- package/src/assert-order/index.ts +3 -1
- package/src/assert-order/{interfaces.ts → types.ts} +0 -0
- package/src/assertron/assertron.spec.ts +1 -2
- package/src/assertron/assertron.ts +5 -6
- package/src/assertron/falsy.spec.ts +1 -2
- package/src/assertron/falsy.ts +2 -6
- package/src/assertron/pathEqual.spec.ts +1 -2
- package/src/assertron/pathEqual.ts +3 -6
- package/src/assertron/rejects.spec.ts +1 -2
- package/src/assertron/rejects.ts +3 -9
- package/src/assertron/repeat.spec.ts +2 -4
- package/src/assertron/repeat.ts +3 -8
- package/src/assertron/resolves.spec.ts +1 -2
- package/src/assertron/resolves.ts +3 -10
- package/src/assertron/satisfies.spec.ts +51 -19
- package/src/assertron/satisfies.ts +18 -15
- package/src/assertron/throws.spec.ts +39 -35
- package/src/assertron/throws.ts +28 -54
- package/src/assertron/truthy.spec.ts +1 -2
- package/src/assertron/truthy.ts +2 -3
- package/src/errors.ts +22 -0
- package/src/index.ts +2 -1
- package/src/testUtils.ts +2 -3
- package/src/{errors/interfaces.ts → types.ts} +0 -0
- package/src/utils/index.ts +12 -0
- package/src/{errors/util.ts → utils/isErrorConstructor.ts} +1 -1
- package/src/utils/notEqualMessage.ts +4 -0
- package/src/{errors → utils}/notSatisfiedMessage.spec.ts +0 -0
- package/src/{errors/NotSatisfied.ts → utils/notSatisfiedMessage.ts} +0 -0
- package/src/{errors → utils}/notThrownMessage.ts +0 -0
- package/src/utils/promiseMessages.ts +12 -0
- package/src/{errors → utils}/unexpectedErrorMessage.ts +4 -3
- package/cjs/assert-order/interfaces.d.ts.map +0 -1
- package/cjs/assert-order/interfaces.js +0 -3
- package/cjs/errors/NotSatisfied.d.ts.map +0 -1
- package/cjs/errors/NotSatisfied.js +0 -28
- package/cjs/errors/index.d.ts +0 -8
- package/cjs/errors/index.d.ts.map +0 -1
- package/cjs/errors/index.js +0 -11
- package/cjs/errors/interfaces.d.ts.map +0 -1
- package/cjs/errors/interfaces.js +0 -3
- package/cjs/errors/notEqualMessage.d.ts.map +0 -1
- package/cjs/errors/notRejectedMessage.d.ts +0 -2
- package/cjs/errors/notRejectedMessage.d.ts.map +0 -1
- package/cjs/errors/notRejectedMessage.js +0 -8
- package/cjs/errors/notThrownMessage.d.ts.map +0 -1
- package/cjs/errors/returnNotRejectedMessage.d.ts +0 -2
- package/cjs/errors/returnNotRejectedMessage.d.ts.map +0 -1
- package/cjs/errors/returnNotRejectedMessage.js +0 -8
- package/cjs/errors/unexpectedErrorMessage.d.ts.map +0 -1
- package/cjs/errors/unexpectedErrorMessage.js +0 -10
- package/cjs/errors/util.d.ts.map +0 -1
- package/cjs/errors/util.js +0 -8
- package/esm/assert-order/interfaces.js +0 -2
- package/esm/errors/NotSatisfied.js +0 -23
- package/esm/errors/index.js +0 -8
- package/esm/errors/interfaces.js +0 -2
- package/esm/errors/notEqualMessage.js +0 -4
- package/esm/errors/notRejectedMessage.js +0 -4
- package/esm/errors/returnNotRejectedMessage.js +0 -4
- package/esm/errors/unexpectedErrorMessage.js +0 -6
- package/esm/errors/util.js +0 -4
- package/src/errors/index.ts +0 -7
- package/src/errors/notEqualMessage.ts +0 -3
- package/src/errors/notRejectedMessage.ts +0 -3
- package/src/errors/returnNotRejectedMessage.ts +0 -3
|
File without changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import AssertionError from '
|
|
1
|
+
import { AssertionError } from '../errors'
|
|
2
|
+
import { notEqualMessage } from '../utils'
|
|
2
3
|
import { falsy } from './falsy'
|
|
3
4
|
import { pathEqual } from './pathEqual'
|
|
4
5
|
import { rejects } from './rejects'
|
|
@@ -11,10 +12,7 @@ import { truthy } from './truthy'
|
|
|
11
12
|
export const assertron = {
|
|
12
13
|
false(value: any) {
|
|
13
14
|
if (value !== false)
|
|
14
|
-
throw new AssertionError(
|
|
15
|
-
`Expected value to equal false, but received ${value}`,
|
|
16
|
-
{ value },
|
|
17
|
-
assertron.false)
|
|
15
|
+
throw new AssertionError(notEqualMessage(value, false), { ssf: assertron.false })
|
|
18
16
|
},
|
|
19
17
|
falsy,
|
|
20
18
|
pathEqual,
|
|
@@ -24,7 +22,8 @@ export const assertron = {
|
|
|
24
22
|
satisfies,
|
|
25
23
|
throws,
|
|
26
24
|
true(value: any) {
|
|
27
|
-
if (value !== true)
|
|
25
|
+
if (value !== true)
|
|
26
|
+
throw new AssertionError(notEqualMessage(value, true), { ssf: assertron.true })
|
|
28
27
|
},
|
|
29
28
|
truthy
|
|
30
29
|
}
|
package/src/assertron/falsy.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import AssertionError from '
|
|
1
|
+
import { AssertionError } from '../errors'
|
|
2
2
|
|
|
3
3
|
export function falsy(value: any) {
|
|
4
4
|
if (value)
|
|
5
|
-
throw new AssertionError(
|
|
6
|
-
`Expected value to be falsy, but received ${value}`,
|
|
7
|
-
{ value },
|
|
8
|
-
falsy
|
|
9
|
-
)
|
|
5
|
+
throw new AssertionError(`Expected value to be falsy, but received ${value}`, { ssf: falsy })
|
|
10
6
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import AssertionError from 'assertion-error'
|
|
2
1
|
import { pathEqual as isPathEqual } from 'path-equal'
|
|
3
|
-
import {
|
|
2
|
+
import { AssertionError } from '../errors'
|
|
3
|
+
import { notEqualMessage } from '../utils'
|
|
4
4
|
|
|
5
5
|
export function pathEqual(actual: string, expected: string) {
|
|
6
6
|
if (!isPathEqual(actual, expected))
|
|
7
|
-
throw new AssertionError(
|
|
8
|
-
notEqualMessage(actual, expected),
|
|
9
|
-
{ actual, expected },
|
|
10
|
-
pathEqual)
|
|
7
|
+
throw new AssertionError(notEqualMessage(actual, expected), { ssf: pathEqual })
|
|
11
8
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import t from 'assert'
|
|
2
|
-
import AssertionError from 'assertion-error'
|
|
3
2
|
import a from '..'
|
|
4
3
|
import { assertAsyncThrows, noStackTraceFor } from '../testUtils'
|
|
5
4
|
|
|
@@ -28,6 +27,6 @@ test('throws on resolved object promise', async () => {
|
|
|
28
27
|
})
|
|
29
28
|
|
|
30
29
|
test('does not contain internal stack trace', async () => {
|
|
31
|
-
const err = await assertAsyncThrows(() => a.rejects(Promise.resolve({ a: 1 }))
|
|
30
|
+
const err = await assertAsyncThrows(() => a.rejects(Promise.resolve({ a: 1 })))
|
|
32
31
|
noStackTraceFor('rejects.ts', err)
|
|
33
32
|
})
|
package/src/assertron/rejects.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { AssertionError } from '../errors'
|
|
2
|
+
import { notRejectedMessage } from '../utils'
|
|
3
3
|
|
|
4
4
|
export function rejects(promise: Promise<any>) {
|
|
5
5
|
return promise.then(
|
|
6
|
-
value => {
|
|
7
|
-
throw new AssertionError(
|
|
8
|
-
`Expected promise to reject, but it resolves with ${typeof value === 'string' ?
|
|
9
|
-
`'${value}'` : tersify(value, { maxLength: Infinity })}`,
|
|
10
|
-
{ value },
|
|
11
|
-
rejects)
|
|
12
|
-
},
|
|
6
|
+
value => { throw new AssertionError(notRejectedMessage(value), { ssf: rejects }) },
|
|
13
7
|
() => { }
|
|
14
8
|
)
|
|
15
9
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import a from '..'
|
|
2
|
-
import { FailOnOccurrence } from './repeat'
|
|
1
|
+
import a, { FailOnOccurrence } from '..'
|
|
3
2
|
|
|
4
3
|
test('repeat function n times', () => {
|
|
5
4
|
let count = 0
|
|
@@ -26,8 +25,7 @@ test('repeat async function n times sequentially', async () => {
|
|
|
26
25
|
test('error is captured as inner error and indicate which call failed', () => {
|
|
27
26
|
let count = 0
|
|
28
27
|
const err = a.throws(() => a.repeat(() => {
|
|
29
|
-
++count
|
|
30
|
-
if (count === 5) throw new Error('failed')
|
|
28
|
+
if (++count === 5) throw new Error('failed')
|
|
31
29
|
}, 10), FailOnOccurrence)
|
|
32
30
|
|
|
33
31
|
expect(err.occurrence).toBe(5)
|
package/src/assertron/repeat.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import isPromise from 'is-promise';
|
|
2
|
-
import
|
|
2
|
+
import { FailOnOccurrence } from '../errors';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Repeat the specified function n times and return the last result.
|
|
@@ -17,7 +17,7 @@ function repeatRecur<R>(fn: () => R | (() => Promise<R>), i: number, times: numb
|
|
|
17
17
|
if (isPromise(result)) {
|
|
18
18
|
return result.then(
|
|
19
19
|
() => repeatRecur(fn, i + 1, times),
|
|
20
|
-
(e) => { throw new FailOnOccurrence(i, e) }
|
|
20
|
+
(e) => { throw new FailOnOccurrence(i, e, { ssf: repeat }) }
|
|
21
21
|
) as any
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
@@ -26,12 +26,7 @@ function repeatRecur<R>(fn: () => R | (() => Promise<R>), i: number, times: numb
|
|
|
26
26
|
}
|
|
27
27
|
catch (e) {
|
|
28
28
|
if (e instanceof FailOnOccurrence) throw e
|
|
29
|
-
throw new FailOnOccurrence(i, e)
|
|
29
|
+
throw new FailOnOccurrence(i, e, { ssf: repeat })
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export class FailOnOccurrence extends AssertionError<{ occurrence: number }> {
|
|
34
|
-
constructor(public occurrence: number, public error: any) {
|
|
35
|
-
super(`Failed on ${occurrence} occurrence`)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { AssertionError } from '../errors'
|
|
2
|
+
import { notResolvedMessage } from '../utils'
|
|
3
3
|
|
|
4
4
|
export function resolves(promise: Promise<any>) {
|
|
5
5
|
return promise.then(
|
|
6
6
|
() => { },
|
|
7
|
-
error => {
|
|
8
|
-
throw new AssertionError(`Expected promise to resolve, but it rejects with ${typeof error === 'string' ?
|
|
9
|
-
`'${error}'` :
|
|
10
|
-
error instanceof Error ?
|
|
11
|
-
error :
|
|
12
|
-
tersify(error, { maxLength: Infinity })}`, { error }, resolves
|
|
13
|
-
)
|
|
14
|
-
}
|
|
7
|
+
error => { throw new AssertionError(notResolvedMessage(error), { ssf: resolves }) }
|
|
15
8
|
)
|
|
16
9
|
}
|
|
@@ -1,20 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import a from '..'
|
|
1
|
+
// import { every } from 'satisfier'
|
|
2
|
+
import { isType } from 'type-plus'
|
|
3
|
+
import a, { AssertionError } from '..'
|
|
4
4
|
import { assertThrows, noStackTraceFor } from '../testUtils'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
describe('non-composable types', () => {
|
|
7
|
+
test('accept same type', () => {
|
|
8
|
+
a.satisfies(null, null)
|
|
9
|
+
a.satisfies(undefined, undefined)
|
|
10
|
+
a.satisfies(1, 1)
|
|
11
|
+
a.satisfies('a', 'a')
|
|
12
|
+
a.satisfies(true, true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('predicate parameter is the widen type', () => {
|
|
16
|
+
a.satisfies(null, (v) => isType<null>(v))
|
|
17
|
+
a.satisfies(undefined, (v) => isType<undefined>(v))
|
|
18
|
+
a.satisfies(1, (v) => isType<number>(v))
|
|
19
|
+
a.satisfies('a', (v) => isType<string>(v))
|
|
20
|
+
a.satisfies(true, (v) => isType<boolean>(v))
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('shows value directly in error', () => {
|
|
24
|
+
a.throws(() => a.satisfies(1, 2), e => e.message === 'Expect actual to satisfy 2, but received 1')
|
|
25
|
+
a.throws(() => a.satisfies(true, false), e => e.message === 'Expect actual to satisfy false, but received true')
|
|
26
|
+
a.throws(() => a.satisfies('a', 'b'), e => e.message === `Expect actual to satisfy 'b', but received 'a'`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('use regex to check against string', () => {
|
|
30
|
+
a.satisfies('abc', /a/)
|
|
31
|
+
})
|
|
18
32
|
})
|
|
19
33
|
|
|
20
34
|
test('empty object will pass any object', () => {
|
|
@@ -26,10 +40,10 @@ test('empty object will fail against primitive types', () => {
|
|
|
26
40
|
a.throws(() => a.satisfies(1, {} as any), e => e.message === 'Expect actual to satisfy {}, but received 1')
|
|
27
41
|
})
|
|
28
42
|
|
|
29
|
-
test(`can use satisfier util function such as has()/every()`, () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
})
|
|
43
|
+
// test(`can use satisfier util function such as has()/every()`, () => {
|
|
44
|
+
// a.satisfies([1], every(1))
|
|
45
|
+
// a.throws(() => a.satisfies([1, 2], every(1)), e => e.message === 'Expect actual[1] to satisfy 1, but received 2')
|
|
46
|
+
// })
|
|
33
47
|
|
|
34
48
|
test(`array entries are checked`, () => {
|
|
35
49
|
a.throws(() => a.satisfies([1], [2]), e => e.message === `Expect actual[0] to satisfy 2, but received 1`)
|
|
@@ -109,3 +123,21 @@ test('does not contain internal stack trace', async () => {
|
|
|
109
123
|
const err = assertThrows(() => a.satisfies({ a: 1 }, { a: 2 }), AssertionError)
|
|
110
124
|
noStackTraceFor('satisfies.ts', err)
|
|
111
125
|
})
|
|
126
|
+
|
|
127
|
+
test('allow partial expectation on array entries', () => {
|
|
128
|
+
type U = { type: 'a', a: string } | { type: 'b', b: string }
|
|
129
|
+
const x: U[] = [{ type: 'a', a: 'abc' }]
|
|
130
|
+
a.satisfies(x, [{ type: 'a' }])
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('allow predicate on array', () => {
|
|
134
|
+
type U = { type: 'a', a: string } | { type: 'b', b: string }
|
|
135
|
+
const x: U[] = [{ type: 'a', a: 'abc' }]
|
|
136
|
+
a.satisfies(x, (v) => v[0].type == 'a')
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('allow predicate on array entries', () => {
|
|
140
|
+
type U = { type: 'a', a: string } | { type: 'b', b: string }
|
|
141
|
+
const x: U[] = [{ type: 'a', a: 'abc' }]
|
|
142
|
+
a.satisfies(x, [(v) => v.type == 'a'])
|
|
143
|
+
})
|
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
import AssertionError from 'assertion-error'
|
|
2
1
|
import { createSatisfier } from 'satisfier'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { If, IsExtend, NonComposableTypes } from 'type-plus'
|
|
3
|
+
import { AssertionError } from '../errors'
|
|
4
|
+
import { notSatisfiedMessage } from '../utils'
|
|
5
5
|
|
|
6
6
|
export type SatisfyExpectation<T> = If<
|
|
7
|
-
|
|
8
|
-
T |
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
IsExtend<T, string>,
|
|
8
|
+
T | RegExp,
|
|
9
|
+
If<
|
|
10
|
+
IsExtend<T, NonComposableTypes>,
|
|
11
|
+
T,
|
|
12
|
+
If<IsExtend<T, Array<any>>,
|
|
13
|
+
T extends Array<infer E> ? Array<SatisfyExpectation<E>> : never,
|
|
14
|
+
{
|
|
15
|
+
[P in keyof T]?: T[P] extends string
|
|
16
|
+
? SatisfyExpectation<T[P]> | RegExp
|
|
17
|
+
: SatisfyExpectation<T[P]>
|
|
18
|
+
}
|
|
19
|
+
>>
|
|
20
|
+
> | ((v: T) => boolean)
|
|
14
21
|
|
|
15
22
|
/**
|
|
16
23
|
* Check if `actual` satisfies criteria in `expected`.
|
|
@@ -19,10 +26,6 @@ export type SatisfyExpectation<T> = If<
|
|
|
19
26
|
export function satisfies<Actual>(actual: Actual, expected: SatisfyExpectation<Actual>) {
|
|
20
27
|
const diff = createSatisfier(expected as any).exec(actual);
|
|
21
28
|
if (diff) {
|
|
22
|
-
throw new AssertionError(
|
|
23
|
-
notSatisfiedMessage(diff),
|
|
24
|
-
{ diff },
|
|
25
|
-
satisfies
|
|
26
|
-
)
|
|
29
|
+
throw new AssertionError(notSatisfiedMessage(diff), { ssf: satisfies })
|
|
27
30
|
}
|
|
28
31
|
}
|
|
@@ -1,59 +1,61 @@
|
|
|
1
1
|
import t from 'assert'
|
|
2
|
-
import AssertionError from '
|
|
3
|
-
import a from '..'
|
|
2
|
+
import a, { AssertionError } from '..'
|
|
4
3
|
import { assertAsyncThrows, assertIsError, assertIsPromise, assertThrows, noStackTraceFor } from '../testUtils'
|
|
5
4
|
|
|
6
|
-
test('when value is PromiseLike returns
|
|
7
|
-
let actual = a.throws(Promise.reject(new Error()), Error)
|
|
5
|
+
test('when value is PromiseLike returns a promise with the rejected value', async () => {
|
|
6
|
+
let actual = a.throws(Promise.reject(new Error('Miku')), Error)
|
|
8
7
|
assertIsPromise(actual)
|
|
8
|
+
t.equal((await actual).message, 'Miku')
|
|
9
9
|
|
|
10
|
-
actual = a.throws(Promise.reject(new Error()), () => true)
|
|
10
|
+
actual = a.throws(Promise.reject(new Error('Ren')), () => true)
|
|
11
11
|
assertIsPromise(actual)
|
|
12
|
+
t.equal((await actual).message, 'Ren')
|
|
12
13
|
|
|
13
|
-
actual = a.throws(Promise.reject(new Error()))
|
|
14
|
+
actual = a.throws(Promise.reject(new Error('Luka')))
|
|
14
15
|
assertIsPromise(actual)
|
|
16
|
+
t.equal((await actual).message, 'Luka')
|
|
15
17
|
})
|
|
16
18
|
|
|
17
|
-
test('when value is function returning promise, will return promise', () => {
|
|
18
|
-
let actual = a.throws(() => Promise.reject(new Error()), Error)
|
|
19
|
+
test('when value is function returning a promise, will return a promise with the rejected value', async () => {
|
|
20
|
+
let actual = a.throws(() => Promise.reject(new Error('Miku')), Error)
|
|
19
21
|
assertIsPromise(actual)
|
|
22
|
+
t.equal((await actual).message, 'Miku')
|
|
20
23
|
|
|
21
|
-
actual = a.throws(() => Promise.reject(new Error()), () => true)
|
|
24
|
+
actual = a.throws(() => Promise.reject(new Error('Luka')), () => true)
|
|
22
25
|
assertIsPromise(actual)
|
|
26
|
+
t.equal((await actual).message, 'Luka')
|
|
23
27
|
|
|
24
|
-
actual = a.throws(() => Promise.reject())
|
|
28
|
+
actual = a.throws(() => Promise.reject('Ren'))
|
|
25
29
|
assertIsPromise(actual)
|
|
30
|
+
t.equal((await actual), 'Ren')
|
|
26
31
|
})
|
|
27
32
|
|
|
28
33
|
test('when value is function returns error', () => {
|
|
29
|
-
let actual = a.throws((() => { throw new Error() })
|
|
34
|
+
let actual = a.throws((() => { throw new Error() }), Error)
|
|
30
35
|
assertIsError(actual)
|
|
31
36
|
|
|
32
|
-
actual = a.throws((() => { throw new Error() })
|
|
37
|
+
actual = a.throws((() => { throw new Error() }))
|
|
33
38
|
assertIsError(actual)
|
|
34
39
|
})
|
|
35
40
|
|
|
36
|
-
test('throws
|
|
41
|
+
test('throws if input is not a function or promise', () => {
|
|
37
42
|
assertThrows(() => a.throws(0 as any))
|
|
38
43
|
assertThrows(() => a.throws(true as any))
|
|
39
44
|
assertThrows(() => a.throws('...' as any))
|
|
40
45
|
assertThrows(() => a.throws(/foo/ as any))
|
|
41
46
|
})
|
|
42
47
|
|
|
43
|
-
test('throws for resolved promise',
|
|
44
|
-
|
|
45
|
-
t.strictEqual(actual.value, 'ok')
|
|
48
|
+
test('throws for resolved promise', () => {
|
|
49
|
+
return assertAsyncThrows(() => a.throws(Promise.resolve('ok')), AssertionError)
|
|
46
50
|
})
|
|
47
51
|
|
|
48
52
|
test('throws error does not contain internal stack trace for resolved promise', async () => {
|
|
49
|
-
const err = await assertAsyncThrows
|
|
53
|
+
const err = await assertAsyncThrows(() => a.throws(Promise.resolve('ok')), AssertionError)
|
|
50
54
|
noStackTraceFor('throws.ts', err)
|
|
51
55
|
})
|
|
52
56
|
|
|
53
57
|
test('passes with rejected promise', async () => {
|
|
54
|
-
const actual = await a.throws<string>(() => new Promise((_, r) =>
|
|
55
|
-
setImmediate(() => r('no'))
|
|
56
|
-
}))
|
|
58
|
+
const actual = await a.throws<string>(() => new Promise((_, r) => setImmediate(() => r('no'))))
|
|
57
59
|
t.strictEqual(actual, 'no')
|
|
58
60
|
})
|
|
59
61
|
|
|
@@ -62,13 +64,14 @@ test('passes with rejected promise passing validator', () => {
|
|
|
62
64
|
})
|
|
63
65
|
|
|
64
66
|
test('throws with rejected promise failing validator', async () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
await assertAsyncThrows(
|
|
68
|
+
() => a.throws(Promise.reject('no'), err => err !== 'no'),
|
|
69
|
+
AssertionError)
|
|
68
70
|
})
|
|
69
71
|
|
|
70
72
|
test('thrown error does not contain internal stack trace with rejected promise failing validator', async () => {
|
|
71
|
-
const err = await assertAsyncThrows
|
|
73
|
+
const err = await assertAsyncThrows(() => a.throws(Promise.reject('no'), err => err !== 'no'), AssertionError)
|
|
74
|
+
// Error.captureStackTrace(err, a.throws)
|
|
72
75
|
|
|
73
76
|
noStackTraceFor('throws.ts', err)
|
|
74
77
|
})
|
|
@@ -78,15 +81,14 @@ test('passes with throwing function', () => {
|
|
|
78
81
|
})
|
|
79
82
|
|
|
80
83
|
test('throws if function does not', () => {
|
|
81
|
-
|
|
84
|
+
assertThrows(
|
|
82
85
|
() => a.throws(() => { return 'foo' }, AssertionError),
|
|
83
86
|
AssertionError
|
|
84
87
|
)
|
|
85
|
-
t.strictEqual(err.value, 'foo')
|
|
86
88
|
})
|
|
87
89
|
|
|
88
90
|
test('thrown error does not contain internal stack track if function does not', () => {
|
|
89
|
-
const err = assertThrows
|
|
91
|
+
const err = assertThrows(
|
|
90
92
|
() => a.throws(() => { return 'foo' }, AssertionError),
|
|
91
93
|
AssertionError
|
|
92
94
|
)
|
|
@@ -94,14 +96,13 @@ test('thrown error does not contain internal stack track if function does not',
|
|
|
94
96
|
})
|
|
95
97
|
|
|
96
98
|
test('throws if function returns resolved promise', async () => {
|
|
97
|
-
|
|
99
|
+
await assertAsyncThrows(
|
|
98
100
|
() => a.throws(() => Promise.resolve('ok')),
|
|
99
101
|
AssertionError)
|
|
100
|
-
t.strictEqual(err.value, 'ok')
|
|
101
102
|
})
|
|
102
103
|
|
|
103
104
|
test('thrown error does not contain internal stack trace if function returns resolved promise', async () => {
|
|
104
|
-
const err = await assertAsyncThrows
|
|
105
|
+
const err = await assertAsyncThrows(
|
|
105
106
|
() => a.throws(() => Promise.resolve('ok')),
|
|
106
107
|
AssertionError)
|
|
107
108
|
noStackTraceFor('throws.ts', err)
|
|
@@ -118,14 +119,17 @@ test('pass if function returns rejected promise passing valdation', () => {
|
|
|
118
119
|
})
|
|
119
120
|
|
|
120
121
|
test('throws if function returns rejected promise not passing valdation', async () => {
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
await assertAsyncThrows(
|
|
123
|
+
() => a.throws(() => Promise.reject('ok'), err => err !== 'ok'),
|
|
124
|
+
AssertionError
|
|
125
|
+
)
|
|
123
126
|
})
|
|
124
127
|
|
|
125
128
|
test('thrown error does not contain stack trace if function returns rejected promise not passing valdation', async () => {
|
|
126
|
-
const err = await assertAsyncThrows
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
const err = await assertAsyncThrows(
|
|
130
|
+
() => a.throws(() => Promise.reject('ok'), err => err !== 'ok'),
|
|
131
|
+
AssertionError
|
|
132
|
+
)
|
|
129
133
|
// console.log('got err', err)
|
|
130
134
|
noStackTraceFor('throws.ts', err)
|
|
131
135
|
})
|
package/src/assertron/throws.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import AssertionError from 'assertion-error';
|
|
2
1
|
import isPromise from 'is-promise';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { AssertionError } from '../errors';
|
|
3
|
+
import { ErrorConstructor, ErrorValidator } from '../types';
|
|
4
|
+
import { isErrorConstructor, notRejectedMessage, notThrownMessage, unexpectedErrorMessage } from '../utils';
|
|
5
5
|
|
|
6
6
|
export function throws<E extends Error>(value: PromiseLike<any>, error?: ErrorValidator | ErrorConstructor<E>): Promise<E>
|
|
7
7
|
export function throws<E extends Error>(value: (...args: any[]) => never, error?: ErrorValidator | ErrorConstructor<E>): E
|
|
@@ -11,50 +11,34 @@ export function throws(value: PromiseLike<any> | (() => any | PromiseLike<any>),
|
|
|
11
11
|
if (typeof value !== 'function' && !isPromise(value)) {
|
|
12
12
|
throw new AssertionError(
|
|
13
13
|
'`assertron.throws()` must be called with a function or promise.',
|
|
14
|
-
|
|
15
|
-
throws
|
|
14
|
+
{ ssf: throws }
|
|
16
15
|
)
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
if (isPromise(value)) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{ value },
|
|
25
|
-
throws)
|
|
26
|
-
},
|
|
27
|
-
err => {
|
|
28
|
-
validateError(validator, err)
|
|
29
|
-
return err
|
|
18
|
+
if (!isPromise(value)) {
|
|
19
|
+
const { threw, err, result } = tryCatch(value)
|
|
20
|
+
if (threw) {
|
|
21
|
+
if (failValidation(validator, err)) {
|
|
22
|
+
throw new AssertionError(unexpectedErrorMessage(err, validator), { ssf: throws })
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (threw) {
|
|
35
|
-
validateError(validator, err)
|
|
36
|
-
return err
|
|
24
|
+
return err
|
|
25
|
+
}
|
|
26
|
+
value = result;
|
|
37
27
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
returnNotRejectedMessage(value),
|
|
43
|
-
{ value },
|
|
44
|
-
throws)
|
|
45
|
-
},
|
|
28
|
+
|
|
29
|
+
if (isPromise(value)) {
|
|
30
|
+
return value.then(
|
|
31
|
+
value => { throw new AssertionError(notRejectedMessage(value), { ssf: throws }) },
|
|
46
32
|
err => {
|
|
47
|
-
|
|
33
|
+
if (failValidation(validator, err)) {
|
|
34
|
+
throw new AssertionError(unexpectedErrorMessage(err, validator), { ssf: throws })
|
|
35
|
+
}
|
|
48
36
|
return err
|
|
49
37
|
}
|
|
50
38
|
)
|
|
51
39
|
}
|
|
52
40
|
|
|
53
|
-
throw new AssertionError(
|
|
54
|
-
notThrownMessage(result),
|
|
55
|
-
{ value: result },
|
|
56
|
-
throws
|
|
57
|
-
)
|
|
41
|
+
throw new AssertionError(notThrownMessage(value), { ssf: throws })
|
|
58
42
|
}
|
|
59
43
|
|
|
60
44
|
function tryCatch(fn: () => any) {
|
|
@@ -70,24 +54,14 @@ function tryCatch(fn: () => any) {
|
|
|
70
54
|
}
|
|
71
55
|
return { threw, err, result }
|
|
72
56
|
}
|
|
57
|
+
function failValidation(validator: ErrorValidator | ErrorConstructor<any> | undefined, error: any): validator is ErrorValidator | ErrorConstructor<any> {
|
|
58
|
+
if (!validator) return false
|
|
73
59
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
unexpectedErrorMessage(error, validator),
|
|
80
|
-
{ actual: error, expected: validator },
|
|
81
|
-
throws
|
|
82
|
-
)
|
|
83
|
-
}
|
|
84
|
-
else if (!validator(error)) {
|
|
85
|
-
// console.log('msg:', unexpectedErrorMessage(error, validator))
|
|
86
|
-
throw new AssertionError(
|
|
87
|
-
unexpectedErrorMessage(error, validator),
|
|
88
|
-
{ actual: error, expected: validator },
|
|
89
|
-
throws
|
|
90
|
-
)
|
|
91
|
-
}
|
|
60
|
+
if (isErrorConstructor(validator)) {
|
|
61
|
+
return !(error instanceof validator)
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return !validator(error)
|
|
92
65
|
}
|
|
93
66
|
}
|
|
67
|
+
|
package/src/assertron/truthy.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import AssertionError from '
|
|
1
|
+
import { AssertionError } from '../errors';
|
|
2
2
|
|
|
3
3
|
export function truthy(value: any) {
|
|
4
4
|
if (!value) throw new AssertionError(
|
|
5
5
|
`Expected value to be truthy, but received ${value}`,
|
|
6
|
-
{
|
|
7
|
-
truthy
|
|
6
|
+
{ ssf: truthy }
|
|
8
7
|
)
|
|
9
8
|
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IsoError, ModuleError } from 'iso-error'
|
|
2
|
+
import { RequiredPick } from 'type-plus'
|
|
3
|
+
import { failOnOccurrence } from './utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A base error for all assertion errors
|
|
7
|
+
*/
|
|
8
|
+
export class AssertionError extends ModuleError {
|
|
9
|
+
constructor(message: string, options: AssertionError.Options) {
|
|
10
|
+
super('assertron', message, options)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export namespace AssertionError {
|
|
15
|
+
export type Options = RequiredPick<IsoError.Options, 'ssf'>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class FailOnOccurrence extends AssertionError {
|
|
19
|
+
constructor(public occurrence: number, public error: any, options: AssertionError.Options) {
|
|
20
|
+
super(failOnOccurrence(occurrence, error), options)
|
|
21
|
+
}
|
|
22
|
+
}
|