Skip to content

Commit

Permalink
refactor: define matchers in separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed Jan 3, 2024
1 parent c95be72 commit 6aadc02
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 13 deletions.
5 changes: 5 additions & 0 deletions packages/expect/src/assertions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import toMatchObject from './toMatchObject'

export default [
toMatchObject,
]
13 changes: 13 additions & 0 deletions packages/expect/src/assertions/toMatchObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineAssertion } from '../utils'
import { iterableEquality, equals as jestEquals, subsetEquality } from '../jest-utils'

export default defineAssertion('toMatchObject', function (expected: unknown) {
const actual = this._obj as unknown
this.assert(
jestEquals(actual, expected, [iterableEquality, subsetEquality]),
'expected #{this} to match object #{exp}',
'expected #{this} to not match object #{exp}',
expected,
actual,
)
})
20 changes: 9 additions & 11 deletions packages/expect/src/jest-expect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import type { MockInstance } from '@vitest/spy'
import { isMockFunction } from '@vitest/spy'
import type { Test } from '@vitest/runner'
import type { Assertion, ChaiPlugin } from './types'
import { arrayBufferEquality, generateToBeMessage, iterableEquality, equals as jestEquals, sparseArrayEquality, subsetEquality, typeEquality } from './jest-utils'
import { arrayBufferEquality, generateToBeMessage, iterableEquality, equals as jestEquals, sparseArrayEquality, typeEquality } from './jest-utils'
import type { AsymmetricMatcher } from './jest-asymmetric-matchers'
import { diff, stringify } from './jest-matcher-utils'
import { JEST_MATCHERS_OBJECT } from './constants'
import { recordAsyncExpect, wrapSoft } from './utils'

import matchers from './assertions/index'

// polyfill globals because expect can be used in node environment
declare class Node {
contains(item: unknown): boolean
Expand All @@ -19,11 +21,17 @@ declare class DOMTokenList {
contains(item: unknown): boolean
}

const defineJestMatchers: ChaiPlugin = (chai, utils) => {
matchers.forEach(define => define(chai, utils))
}

// Jest Expect Compact
export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
const { AssertionError } = chai
const c = () => getColors()

defineJestMatchers(chai, utils)

function def(name: keyof Assertion | (keyof Assertion)[], fn: ((this: Chai.AssertionStatic & Assertion, ...args: any[]) => any)) {
const addMethod = (n: keyof Assertion) => {
const softWrapper = wrapSoft(utils, fn)
Expand Down Expand Up @@ -156,16 +164,6 @@ export const JestChaiExpect: ChaiPlugin = (chai, utils) => {
actual,
)
})
def('toMatchObject', function (expected) {
const actual = this._obj
return this.assert(
jestEquals(actual, expected, [iterableEquality, subsetEquality]),
'expected #{this} to match object #{exp}',
'expected #{this} to not match object #{exp}',
expected,
actual,
)
})
def('toMatch', function (expected: string | RegExp) {
if (typeof expected === 'string')
return this.include(expected)
Expand Down
19 changes: 17 additions & 2 deletions packages/expect/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { processError } from '@vitest/utils/error'
import type { Test } from '@vitest/runner/types'
import { GLOBAL_EXPECT } from './constants'
import { GLOBAL_EXPECT, JEST_MATCHERS_OBJECT } from './constants'
import { getState } from './state'
import type { Assertion, MatcherState } from './types'
import type { Assertion, ChaiPlugin, MatcherState } from './types'

export function recordAsyncExpect(test: any, promise: Promise<any> | PromiseLike<any>) {
// record promise for test, that resolves before test ends
Expand Down Expand Up @@ -49,3 +49,18 @@ export function wrapSoft(utils: Chai.ChaiUtils, fn: (this: Chai.AssertionStatic
}
}
}

export function defineAssertion<T>(name: keyof Assertion, fn: (this: Omit<Chai.AssertionStatic & Assertion, '_obj'> & { _obj: T }, ...args: any) => any): ChaiPlugin {
return (chai, utils) => {
const addMethod = (n: keyof Assertion) => {
const softWrapper = wrapSoft(utils, fn)
utils.addMethod(chai.Assertion.prototype, n, softWrapper)
utils.addMethod((globalThis as any)[JEST_MATCHERS_OBJECT].matchers, n, softWrapper)
}

if (Array.isArray(name))
name.forEach(n => addMethod(n))
else
addMethod(name)
}
}

0 comments on commit 6aadc02

Please sign in to comment.