Skip to content

Commit

Permalink
fix: construct mather context for asymmetric matchers on demand
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Oct 5, 2021
1 parent f13abff commit f3e582d
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 28 deletions.
46 changes: 22 additions & 24 deletions packages/expect/src/asymmetricMatchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,28 @@ import {getState} from './jestMatchersObject';
import type {MatcherState} from './types';
import {iterableEquality, subsetEquality} from './utils';

export class AsymmetricMatcher<T> {
protected sample: T;
protected readonly matcherState: MatcherState;
$$typeof: symbol;
// TODO: remove this field in Jest 28 (use `matcherState`)
inverse?: boolean;
const utils = Object.freeze({
...matcherUtils,
iterableEquality,
subsetEquality,
});

constructor(sample: T, isNot = false) {
this.$$typeof = Symbol.for('jest.asymmetricMatcher');
this.sample = sample;
export abstract class AsymmetricMatcher<T> {
$$typeof = Symbol.for('jest.asymmetricMatcher');

const utils = {...matcherUtils, iterableEquality, subsetEquality};
constructor(protected sample: T, protected inverse = false) {}

const matcherContext: MatcherState = {
protected getMatcherContext(): MatcherState {
return {
...getState(),
equals,
isNot,
isNot: this.inverse,
utils,
};

this.inverse = matcherContext.isNot;

this.matcherState = matcherContext;
}

abstract asymmetricMatch(other: unknown): boolean;
abstract toString(): string;
}

class Any extends AsymmetricMatcher<any> {
Expand Down Expand Up @@ -152,11 +150,11 @@ class ArrayContaining extends AsymmetricMatcher<Array<unknown>> {
other.some(another => equals(item, another)),
));

return this.matcherState.isNot ? !result : result;
return this.inverse ? !result : result;
}

toString() {
return `Array${this.matcherState.isNot ? 'Not' : ''}Containing`;
return `Array${this.inverse ? 'Not' : ''}Containing`;
}

getExpectedType() {
Expand Down Expand Up @@ -190,11 +188,11 @@ class ObjectContaining extends AsymmetricMatcher<Record<string, unknown>> {
}
}

return this.matcherState.isNot ? !result : result;
return this.inverse ? !result : result;
}

toString() {
return `Object${this.matcherState.isNot ? 'Not' : ''}Containing`;
return `Object${this.inverse ? 'Not' : ''}Containing`;
}

getExpectedType() {
Expand All @@ -213,11 +211,11 @@ class StringContaining extends AsymmetricMatcher<string> {
asymmetricMatch(other: string) {
const result = isA('String', other) && other.includes(this.sample);

return this.matcherState.isNot ? !result : result;
return this.inverse ? !result : result;
}

toString() {
return `String${this.matcherState.isNot ? 'Not' : ''}Containing`;
return `String${this.inverse ? 'Not' : ''}Containing`;
}

getExpectedType() {
Expand All @@ -236,11 +234,11 @@ class StringMatching extends AsymmetricMatcher<RegExp> {
asymmetricMatch(other: string) {
const result = isA('String', other) && this.sample.test(other);

return this.matcherState.isNot ? !result : result;
return this.inverse ? !result : result;
}

toString() {
return `String${this.matcherState.isNot ? 'Not' : ''}Matching`;
return `String${this.inverse ? 'Not' : ''}Matching`;
}

getExpectedType() {
Expand Down
10 changes: 6 additions & 4 deletions packages/expect/src/jestMatchersObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,16 @@ export const setMatchers = (

asymmetricMatch(other: unknown) {
const {pass} = matcher.call(
this.matcherState,
this.getMatcherContext(),
other,
...this.sample,
) as SyncExpectationResult;

return this.matcherState.isNot ? !pass : pass;
return this.inverse ? !pass : pass;
}

toString() {
return `${this.matcherState.isNot ? 'not.' : ''}${key}`;
return `${this.inverse ? 'not.' : ''}${key}`;
}

getExpectedType() {
Expand All @@ -92,7 +92,9 @@ export const setMatchers = (
expect[key] = (...sample: [unknown, unknown]) =>
new CustomMatcher(false, ...sample);
if (!expect.not) {
expect.not = {};
throw new Error(
'`expect.not` is not defined - please report this bug to https://github.com/facebook/jest',
);
}
expect.not[key] = (...sample: [unknown, unknown]) =>
new CustomMatcher(true, ...sample);
Expand Down

0 comments on commit f3e582d

Please sign in to comment.