-
-
Notifications
You must be signed in to change notification settings - Fork 1k
/
jest-extend.ts
82 lines (67 loc) · 2.37 KB
/
jest-extend.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import chai, { util } from 'chai'
import { getState } from './jest-expect'
import * as matcherUtils from './jest-matcher-utils'
import {
equals,
iterableEquality,
subsetEquality,
} from './jest-utils'
import type {
ChaiPlugin,
MatcherState,
MatchersObject,
SyncExpectationResult,
} from './types'
const isAsyncFunction = (fn: unknown) =>
typeof fn === 'function' && (fn as any)[Symbol.toStringTag] === 'AsyncFunction'
const getMatcherState = (assertion: Chai.AssertionStatic & Chai.Assertion) => {
const actual = assertion._obj
const isNot = util.flag(assertion, 'negate') as boolean
const promise = util.flag(assertion, 'promise') || ''
const jestUtils = {
...matcherUtils,
iterableEquality,
subsetEquality,
}
const matcherState: MatcherState = {
isNot,
utils: jestUtils,
promise,
equals,
...getState(),
// needed for built-in jest-snapshots, but we don't use it
suppressedErrors: [],
}
return {
state: matcherState,
isNot,
actual,
}
}
function JestExtendPlugin(expects: MatchersObject): ChaiPlugin {
return (c, utils) => {
Object.entries(expects).forEach(([expectAssertionName, expectAssertion]) => {
function expectSyncWrapper(this: Chai.AssertionStatic & Chai.Assertion, ...args: any[]) {
const { state, isNot, actual } = getMatcherState(this)
// @ts-expect-error args wanting tuple
const { pass, message } = expectAssertion.call(state, actual, ...args) as SyncExpectationResult
if ((pass && isNot) || (!pass && !isNot))
c.expect.fail(message())
}
async function expectAsyncWrapper(this: Chai.AssertionStatic & Chai.Assertion, ...args: any[]) {
const { state, isNot, actual } = getMatcherState(this)
// @ts-expect-error args wanting tuple
const { pass, message } = await expectAssertion.call(state, actual, ...args) as SyncExpectationResult
if ((pass && isNot) || (!pass && !isNot))
c.expect.fail(message())
}
const expectAssertionWrapper = isAsyncFunction(expectAssertion) ? expectAsyncWrapper : expectSyncWrapper
utils.addMethod(chai.Assertion.prototype, expectAssertionName, expectAssertionWrapper)
})
}
}
export const JestExtend: ChaiPlugin = (chai, utils) => {
utils.addMethod(chai.expect, 'extend', (expects: MatchersObject) => {
chai.use(JestExtendPlugin(expects))
})
}