From 992acd9530cb2611f8ccf762dd4145ab594174ee Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Thu, 10 Feb 2022 21:30:11 +0200 Subject: [PATCH 1/9] fix: export AsymmetricMatchers interface --- packages/expect/__typetests__/expect.test.ts | 75 +++++++++++++++++-- packages/expect/src/index.ts | 2 +- .../jest-types/__typetests__/expect.test.ts | 72 +++++++++++++----- 3 files changed, 126 insertions(+), 23 deletions(-) diff --git a/packages/expect/__typetests__/expect.test.ts b/packages/expect/__typetests__/expect.test.ts index af5d2ad1fe21..acd40562f0a0 100644 --- a/packages/expect/__typetests__/expect.test.ts +++ b/packages/expect/__typetests__/expect.test.ts @@ -5,12 +5,77 @@ * LICENSE file in the root directory of this source tree. */ -import {expectError} from 'tsd-lite'; -import type * as expect from 'expect'; +import {expectError, expectType} from 'tsd-lite'; +import type {EqualsFunction, Tester} from '@jest/expect-utils'; +import {type Matchers, expect} from 'expect'; +import type * as jestMatcherUtils from 'jest-matcher-utils'; -type M = expect.Matchers; -type N = expect.Matchers; +type M = Matchers; +type N = Matchers; expectError(() => { - type E = expect.Matchers; + type E = Matchers; }); + +// extend + +type MatcherUtils = typeof jestMatcherUtils & { + iterableEquality: Tester; + subsetEquality: Tester; +}; + +expectType( + expect.extend({ + toBeWithinRange(actual: number, floor: number, ceiling: number) { + expectType(this.assertionCalls); + expectType(this.currentTestName); + expectType<(() => void) | undefined>(this.dontThrow); + expectType(this.error); + expectType(this.equals); + expectType(this.expand); + expectType(this.expectedAssertionsNumber); + expectType(this.expectedAssertionsNumberError); + expectType(this.isExpectingAssertions); + expectType(this.isExpectingAssertionsError); + expectType(this.isNot); + expectType(this.promise); + expectType>(this.suppressedErrors); + expectType(this.testPath); + expectType(this.utils); + + const pass = actual >= floor && actual <= ceiling; + if (pass) { + return { + message: () => + `expected ${actual} not to be within range ${floor} - ${ceiling}`, + pass: true, + }; + } else { + return { + message: () => + `expected ${actual} to be within range ${floor} - ${ceiling}`, + pass: false, + }; + } + }, + }), +); + +declare module 'expect' { + interface AsymmetricMatchers { + toBeWithinRange(floor: number, ceiling: number): void; + } + interface Matchers { + toBeWithinRange(floor: number, ceiling: number): void; + } +} + +expectType(expect(100).toBeWithinRange(90, 110)); +expectType(expect(101).not.toBeWithinRange(0, 100)); + +expectType( + expect({apples: 6, bananas: 3}).toEqual({ + apples: expect.toBeWithinRange(1, 10), + bananas: expect.not.toBeWithinRange(11, 20), + }), +); diff --git a/packages/expect/src/index.ts b/packages/expect/src/index.ts index 7edb89b4d54d..637e36f194d2 100644 --- a/packages/expect/src/index.ts +++ b/packages/expect/src/index.ts @@ -49,7 +49,7 @@ import type { ThrowingMatcherFn, } from './types'; -export type {Expect, MatcherState, Matchers} from './types'; +export type {AsymmetricMatchers, Expect, MatcherState, Matchers} from './types'; export class JestAssertionError extends Error { matcherResult?: Omit & {message: string}; diff --git a/packages/jest-types/__typetests__/expect.test.ts b/packages/jest-types/__typetests__/expect.test.ts index 2c380a0c40c8..ece8c523f242 100644 --- a/packages/jest-types/__typetests__/expect.test.ts +++ b/packages/jest-types/__typetests__/expect.test.ts @@ -6,7 +6,9 @@ */ import {expectError, expectType} from 'tsd-lite'; +import type {EqualsFunction, Tester} from '@jest/expect-utils'; import {expect} from '@jest/globals'; +import type * as jestMatcherUtils from 'jest-matcher-utils'; // asymmetric matchers @@ -349,27 +351,63 @@ expectError(expect(jest.fn()).toThrowErrorMatchingInlineSnapshot(true)); // extend +type MatcherUtils = typeof jestMatcherUtils & { + iterableEquality: Tester; + subsetEquality: Tester; +}; + expectType( expect.extend({ - toBeDivisibleBy(actual: number, expected: number) { + toBeWithinRange(actual: number, floor: number, ceiling: number) { + expectType(this.assertionCalls); + expectType(this.currentTestName); + expectType<(() => void) | undefined>(this.dontThrow); + expectType(this.error); + expectType(this.equals); + expectType(this.expand); + expectType(this.expectedAssertionsNumber); + expectType(this.expectedAssertionsNumberError); + expectType(this.isExpectingAssertions); + expectType(this.isExpectingAssertionsError); expectType(this.isNot); - - const pass = actual % expected === 0; - const message = pass - ? () => - `expected ${this.utils.printReceived( - actual, - )} not to be divisible by ${expected}` - : () => - `expected ${this.utils.printReceived( - actual, - )} to be divisible by ${expected}`; - - return {message, pass}; + expectType(this.promise); + expectType>(this.suppressedErrors); + expectType(this.testPath); + expectType(this.utils); + + const pass = actual >= floor && actual <= ceiling; + if (pass) { + return { + message: () => + `expected ${actual} not to be within range ${floor} - ${ceiling}`, + pass: true, + }; + } else { + return { + message: () => + `expected ${actual} to be within range ${floor} - ${ceiling}`, + pass: false, + }; + } }, }), ); -// TODO -// expect(4).toBeDivisibleBy(2); -// expect.toBeDivisibleBy(2); +declare module 'expect' { + interface AsymmetricMatchers { + toBeWithinRange(floor: number, ceiling: number): void; + } + interface Matchers { + toBeWithinRange(floor: number, ceiling: number): R; + } +} + +expectType(expect(100).toBeWithinRange(90, 110)); +expectType(expect(101).not.toBeWithinRange(0, 100)); + +expectType( + expect({apples: 6, bananas: 3}).toEqual({ + apples: expect.toBeWithinRange(1, 10), + bananas: expect.not.toBeWithinRange(11, 20), + }), +); From 7b7fcd6869e51f19a49b533f151bd265149869eb Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Thu, 10 Feb 2022 21:56:43 +0200 Subject: [PATCH 2/9] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4366e726c58a..3fba7f583def 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ ### Fixes - `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346)) +- `[expect]` Export `AsymmetricMatchers` interface ([#12363](https://github.com/facebook/jest/pull/12363)) - `[jest-environment-jsdom]` Make `jsdom` accessible to extending environments again ([#12232](https://github.com/facebook/jest/pull/12232)) - `[jest-phabricator]` [**BREAKING**] Convert to ESM ([#12341](https://github.com/facebook/jest/pull/12341)) From 146f4dab500b5c3ad0287a5d1d25b8fff305d59d Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 11:26:52 +0200 Subject: [PATCH 3/9] expose RawMatcherFn --- packages/expect/src/index.ts | 8 ++- packages/expect/src/types.ts | 1 + packages/expect/tsconfig.json | 4 +- packages/jest-jasmine2/src/jestExpect.ts | 4 +- packages/jest-jasmine2/src/types.ts | 21 +----- packages/jest-snapshot/src/index.ts | 84 +++++++++++------------- packages/jest-snapshot/src/types.ts | 6 -- 7 files changed, 53 insertions(+), 75 deletions(-) diff --git a/packages/expect/src/index.ts b/packages/expect/src/index.ts index 637e36f194d2..ce4ab6e64384 100644 --- a/packages/expect/src/index.ts +++ b/packages/expect/src/index.ts @@ -49,7 +49,13 @@ import type { ThrowingMatcherFn, } from './types'; -export type {AsymmetricMatchers, Expect, MatcherState, Matchers} from './types'; +export type { + AsymmetricMatchers, + Expect, + MatcherState, + Matchers, + RawMatcherFn, +} from './types'; export class JestAssertionError extends Error { matcherResult?: Omit & {message: string}; diff --git a/packages/expect/src/types.ts b/packages/expect/src/types.ts index d9b7f31307fd..3fcdfa093baf 100644 --- a/packages/expect/src/types.ts +++ b/packages/expect/src/types.ts @@ -22,6 +22,7 @@ export type ExpectationResult = SyncExpectationResult | AsyncExpectationResult; export type RawMatcherFn = { (this: T, received: any, expected: any, options?: any): ExpectationResult; + /** @internal */ [INTERNAL_MATCHER_FLAG]?: boolean; }; diff --git a/packages/expect/tsconfig.json b/packages/expect/tsconfig.json index 3609d0f6e862..8bd68af78fd1 100644 --- a/packages/expect/tsconfig.json +++ b/packages/expect/tsconfig.json @@ -2,7 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "src", - "outDir": "build" + "outDir": "build", + + "stripInternal": true }, "include": ["./src/**/*"], "exclude": ["./**/__tests__/**/*"], diff --git a/packages/jest-jasmine2/src/jestExpect.ts b/packages/jest-jasmine2/src/jestExpect.ts index 6269cdfb40b0..836de548e832 100644 --- a/packages/jest-jasmine2/src/jestExpect.ts +++ b/packages/jest-jasmine2/src/jestExpect.ts @@ -7,7 +7,7 @@ /* eslint-disable local/prefer-spread-eventually */ -import {MatcherState, expect} from 'expect'; +import {type MatcherState, type RawMatcherFn, expect} from 'expect'; import { addSerializer, toMatchInlineSnapshot, @@ -15,7 +15,7 @@ import { toThrowErrorMatchingInlineSnapshot, toThrowErrorMatchingSnapshot, } from 'jest-snapshot'; -import type {JasmineMatchersObject, RawMatcherFn} from './types'; +import type {JasmineMatchersObject} from './types'; export default function jestExpect(config: {expand: boolean}): void { global.expect = expect; diff --git a/packages/jest-jasmine2/src/types.ts b/packages/jest-jasmine2/src/types.ts index 2d8282a4be6b..34ef38ebddec 100644 --- a/packages/jest-jasmine2/src/types.ts +++ b/packages/jest-jasmine2/src/types.ts @@ -7,7 +7,7 @@ import type {AssertionError} from 'assert'; import type {Config} from '@jest/types'; -import type {Expect} from 'expect'; +import type {Expect, RawMatcherFn} from 'expect'; import type CallTracker from './jasmine/CallTracker'; import type Env from './jasmine/Env'; import type JsApiReporter from './jasmine/JsApiReporter'; @@ -25,25 +25,6 @@ export interface AssertionErrorWithStack extends AssertionError { stack: string; } -// TODO Add expect types to @jest/types or leave it here -// Borrowed from "expect" -// -------START------- -export type SyncExpectationResult = { - pass: boolean; - message: () => string; -}; - -export type AsyncExpectationResult = Promise; - -export type ExpectationResult = SyncExpectationResult | AsyncExpectationResult; - -export type RawMatcherFn = ( - expected: unknown, - actual: unknown, - options?: unknown, -) => ExpectationResult; -// -------END------- - export type RunDetails = { totalSpecsDefined?: number; failedExpectations?: SuiteResult['failedExpectations']; diff --git a/packages/jest-snapshot/src/index.ts b/packages/jest-snapshot/src/index.ts index 322f4f549453..fd3b7f73fe2f 100644 --- a/packages/jest-snapshot/src/index.ts +++ b/packages/jest-snapshot/src/index.ts @@ -7,6 +7,7 @@ import * as fs from 'graceful-fs'; import type {Config} from '@jest/types'; +import type {RawMatcherFn} from 'expect'; import type {FS as HasteFS} from 'jest-haste-map'; import { BOLD_WEIGHT, @@ -30,7 +31,7 @@ import { printReceived, printSnapshotAndReceived, } from './printSnapshot'; -import type {Context, ExpectationResult, MatchSnapshotConfig} from './types'; +import type {Context, MatchSnapshotConfig} from './types'; import {deepMerge, escapeBacktickString, serialize} from './utils'; export {addSerializer, getSerializers} from './plugins'; @@ -155,12 +156,11 @@ export const cleanup = ( }; }; -export const toMatchSnapshot = function ( - this: Context, +export const toMatchSnapshot: RawMatcherFn = function ( received: unknown, propertiesOrHint?: object | Config.Path, hint?: Config.Path, -): ExpectationResult { +) { const matcherName = 'toMatchSnapshot'; let properties; @@ -214,12 +214,11 @@ export const toMatchSnapshot = function ( }); }; -export const toMatchInlineSnapshot = function ( - this: Context, +export const toMatchInlineSnapshot: RawMatcherFn = function ( received: unknown, propertiesOrSnapshot?: object | string, inlineSnapshot?: string, -): ExpectationResult { +) { const matcherName = 'toMatchInlineSnapshot'; let properties; @@ -408,12 +407,11 @@ const _toMatchSnapshot = (config: MatchSnapshotConfig) => { }; }; -export const toThrowErrorMatchingSnapshot = function ( - this: Context, +export const toThrowErrorMatchingSnapshot: RawMatcherFn = function ( received: unknown, hint: string | undefined, // because error TS1016 for hint?: string fromPromise: boolean, -): ExpectationResult { +) { const matcherName = 'toThrowErrorMatchingSnapshot'; // Future breaking change: Snapshot hint must be a string @@ -431,44 +429,40 @@ export const toThrowErrorMatchingSnapshot = function ( ); }; -export const toThrowErrorMatchingInlineSnapshot = function ( - this: Context, - received: unknown, - inlineSnapshot?: string, - fromPromise?: boolean, -): ExpectationResult { - const matcherName = 'toThrowErrorMatchingInlineSnapshot'; +export const toThrowErrorMatchingInlineSnapshot: RawMatcherFn = + function (received: unknown, inlineSnapshot?: string, fromPromise?: boolean) { + const matcherName = 'toThrowErrorMatchingInlineSnapshot'; - if (inlineSnapshot !== undefined && typeof inlineSnapshot !== 'string') { - const options: MatcherHintOptions = { - expectedColor: noColor, - isNot: this.isNot, - promise: this.promise, - }; + if (inlineSnapshot !== undefined && typeof inlineSnapshot !== 'string') { + const options: MatcherHintOptions = { + expectedColor: noColor, + isNot: this.isNot, + promise: this.promise, + }; - throw new Error( - matcherErrorMessage( - matcherHint(matcherName, undefined, SNAPSHOT_ARG, options), - 'Inline snapshot must be a string', - printWithType('Inline snapshot', inlineSnapshot, serialize), - ), - ); - } + throw new Error( + matcherErrorMessage( + matcherHint(matcherName, undefined, SNAPSHOT_ARG, options), + 'Inline snapshot must be a string', + printWithType('Inline snapshot', inlineSnapshot, serialize), + ), + ); + } - return _toThrowErrorMatchingSnapshot( - { - context: this, - inlineSnapshot: - inlineSnapshot !== undefined - ? stripAddedIndentation(inlineSnapshot) - : undefined, - isInline: true, - matcherName, - received, - }, - fromPromise, - ); -}; + return _toThrowErrorMatchingSnapshot( + { + context: this, + inlineSnapshot: + inlineSnapshot !== undefined + ? stripAddedIndentation(inlineSnapshot) + : undefined, + isInline: true, + matcherName, + received, + }, + fromPromise, + ); + }; const _toThrowErrorMatchingSnapshot = ( config: MatchSnapshotConfig, diff --git a/packages/jest-snapshot/src/types.ts b/packages/jest-snapshot/src/types.ts index 40ddd1cabfaa..dcc0c8e12de5 100644 --- a/packages/jest-snapshot/src/types.ts +++ b/packages/jest-snapshot/src/types.ts @@ -23,9 +23,3 @@ export type MatchSnapshotConfig = { }; export type SnapshotData = Record; - -// copied from `expect` - should be shared -export type ExpectationResult = { - pass: boolean; - message: () => string; -}; From d46987c77bc9233270c084bf5f7540f9c9a0ba3d Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 11:36:00 +0200 Subject: [PATCH 4/9] add example --- .../expect-extend/__tests__/ranges.test.ts | 20 +++++++++ examples/expect-extend/package.json | 30 +++++++++++++ examples/expect-extend/toBeWithinRange.ts | 43 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 examples/expect-extend/__tests__/ranges.test.ts create mode 100644 examples/expect-extend/package.json create mode 100644 examples/expect-extend/toBeWithinRange.ts diff --git a/examples/expect-extend/__tests__/ranges.test.ts b/examples/expect-extend/__tests__/ranges.test.ts new file mode 100644 index 000000000000..77f80e8a5ef8 --- /dev/null +++ b/examples/expect-extend/__tests__/ranges.test.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {expect, test} from '@jest/globals'; +import '../toBeWithinRange'; + +test('is within range', () => expect(100).toBeWithinRange(90, 110)); + +test('is NOT within range', () => expect(101).not.toBeWithinRange(0, 100)); + +test('asymmetric ranges', () => { + expect({apples: 6, bananas: 3}).toEqual({ + apples: expect.toBeWithinRange(1, 10), + bananas: expect.not.toBeWithinRange(11, 20), + }); +}); diff --git a/examples/expect-extend/package.json b/examples/expect-extend/package.json new file mode 100644 index 000000000000..2580ad9d4b47 --- /dev/null +++ b/examples/expect-extend/package.json @@ -0,0 +1,30 @@ +{ + "private": true, + "version": "0.0.0", + "name": "example-expect-extend", + "devDependencies": { + "@babel/core": "*", + "@babel/preset-env": "*", + "@babel/preset-typescript": "*", + "@jest/globals": "*", + "babel-jest": "*", + "expect": "*", + "jest": "*" + }, + "scripts": { + "test": "jest" + }, + "babel": { + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "node": "current" + } + } + ], + "@babel/preset-typescript" + ] + } +} diff --git a/examples/expect-extend/toBeWithinRange.ts b/examples/expect-extend/toBeWithinRange.ts new file mode 100644 index 000000000000..b7d43cddec73 --- /dev/null +++ b/examples/expect-extend/toBeWithinRange.ts @@ -0,0 +1,43 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {expect} from '@jest/globals'; +import type {RawMatcherFn} from 'expect'; + +const toBeWithinRange: RawMatcherFn = ( + actual: number, + floor: number, + ceiling: number, +) => { + const pass = actual >= floor && actual <= ceiling; + if (pass) { + return { + message: () => + `expected ${actual} not to be within range ${floor} - ${ceiling}`, + pass: true, + }; + } else { + return { + message: () => + `expected ${actual} to be within range ${floor} - ${ceiling}`, + pass: false, + }; + } +}; + +expect.extend({ + toBeWithinRange, +}); + +declare module 'expect' { + interface AsymmetricMatchers { + toBeWithinRange(a: number, b: number): void; + } + interface Matchers { + toBeWithinRange(a: number, b: number): R; + } +} From 3082734727ac0b80a97661c0b3c8c1b5813cd398 Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 11:38:39 +0200 Subject: [PATCH 5/9] lock file --- yarn.lock | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/yarn.lock b/yarn.lock index ea0db676e7c1..6d95abdf416c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2584,6 +2584,18 @@ __metadata: languageName: unknown linkType: soft +"@jest/environment@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/environment@npm:27.5.1" + dependencies: + "@jest/fake-timers": ^27.5.1 + "@jest/types": ^27.5.1 + "@types/node": "*" + jest-mock: ^27.5.1 + checksum: 2a9e18c35a015508dbec5b90b21c150230fa6c1c8cb8fabe029d46ee2ca4c40eb832fb636157da14c66590d0a4c8a2c053226b041f54a44507d6f6a89abefd66 + languageName: node + linkType: hard + "@jest/expect-utils@^28.0.0-alpha.0, @jest/expect-utils@workspace:packages/expect-utils": version: 0.0.0-use.local resolution: "@jest/expect-utils@workspace:packages/expect-utils" @@ -2607,6 +2619,20 @@ __metadata: languageName: unknown linkType: soft +"@jest/fake-timers@npm:^27.5.1": + version: 27.5.1 + resolution: "@jest/fake-timers@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@sinonjs/fake-timers": ^8.0.1 + "@types/node": "*" + jest-message-util: ^27.5.1 + jest-mock: ^27.5.1 + jest-util: ^27.5.1 + checksum: 02a0561ed2f4586093facd4ae500b74694f187ac24d4a00e949a39a1c5325bca8932b4fcb0388a2c5ed0656506fc1cf51fd3e32cdd48cea7497ad9c6e028aba8 + languageName: node + linkType: hard + "@jest/globals@^28.0.0-alpha.0, @jest/globals@workspace:*, @jest/globals@workspace:packages/jest-globals": version: 0.0.0-use.local resolution: "@jest/globals@workspace:packages/jest-globals" @@ -2617,6 +2643,17 @@ __metadata: languageName: unknown linkType: soft +"@jest/globals@npm:*": + version: 27.5.1 + resolution: "@jest/globals@npm:27.5.1" + dependencies: + "@jest/environment": ^27.5.1 + "@jest/types": ^27.5.1 + expect: ^27.5.1 + checksum: 087f97047e9dcf555f76fe2ce54aee681e005eaa837a0c0c2d251df6b6412c892c9df54cb871b180342114389a5ff895a4e52e6e6d3d0015bf83c02a54f64c3c + languageName: node + linkType: hard + "@jest/monorepo@workspace:.": version: 0.0.0-use.local resolution: "@jest/monorepo@workspace:." @@ -4375,6 +4412,15 @@ __metadata: languageName: node linkType: hard +"@sinonjs/fake-timers@npm:^8.0.1": + version: 8.1.0 + resolution: "@sinonjs/fake-timers@npm:8.1.0" + dependencies: + "@sinonjs/commons": ^1.7.0 + checksum: 09b5a158ce013a6c37613258bad79ca4efeb99b1f59c41c73cca36cac00b258aefcf46eeea970fccf06b989414d86fe9f54c1102272c0c3bdd51a313cea80949 + languageName: node + linkType: hard + "@sinonjs/fake-timers@npm:^9.1.0": version: 9.1.0 resolution: "@sinonjs/fake-timers@npm:9.1.0" @@ -8916,6 +8962,13 @@ __metadata: languageName: node linkType: hard +"diff-sequences@npm:^27.5.1": + version: 27.5.1 + resolution: "diff-sequences@npm:27.5.1" + checksum: a00db5554c9da7da225db2d2638d85f8e41124eccbd56cbaefb3b276dcbb1c1c2ad851c32defe2055a54a4806f030656cbf6638105fd6ce97bb87b90b32a33ca + languageName: node + linkType: hard + "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -9896,6 +9949,20 @@ __metadata: languageName: unknown linkType: soft +"example-expect-extend@workspace:examples/expect-extend": + version: 0.0.0-use.local + resolution: "example-expect-extend@workspace:examples/expect-extend" + dependencies: + "@babel/core": "*" + "@babel/preset-env": "*" + "@babel/preset-typescript": "*" + "@jest/globals": "*" + babel-jest: "*" + expect: "*" + jest: "*" + languageName: unknown + linkType: soft + "example-getting-started@workspace:examples/getting-started": version: 0.0.0-use.local resolution: "example-getting-started@workspace:examples/getting-started" @@ -10123,6 +10190,18 @@ __metadata: languageName: unknown linkType: soft +"expect@npm:*, expect@npm:^27.5.1": + version: 27.5.1 + resolution: "expect@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + jest-get-type: ^27.5.1 + jest-matcher-utils: ^27.5.1 + jest-message-util: ^27.5.1 + checksum: b2c66beb52de53ef1872165aace40224e722bca3c2274c54cfa74b6d617d55cf0ccdbf36783ccd64dbea501b280098ed33fd0b207d4f15bc03cd3c7a24364a6a + languageName: node + linkType: hard + "express@npm:^4.17.1": version: 4.17.2 resolution: "express@npm:4.17.2" @@ -12953,6 +13032,18 @@ __metadata: languageName: node linkType: hard +"jest-diff@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-diff@npm:27.5.1" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^27.5.1 + jest-get-type: ^27.5.1 + pretty-format: ^27.5.1 + checksum: 8be27c1e1ee57b2bb2bef9c0b233c19621b4c43d53a3c26e2c00a4e805eb4ea11fe1694a06a9fb0e80ffdcfdc0d2b1cb0b85920b3f5c892327ecd1e7bd96b865 + languageName: node + linkType: hard + "jest-docblock@^28.0.0-alpha.0, jest-docblock@workspace:packages/jest-docblock": version: 0.0.0-use.local resolution: "jest-docblock@workspace:packages/jest-docblock" @@ -13017,6 +13108,13 @@ __metadata: languageName: node linkType: hard +"jest-get-type@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-get-type@npm:27.5.1" + checksum: 63064ab70195c21007d897c1157bf88ff94a790824a10f8c890392e7d17eda9c3900513cb291ca1c8d5722cad79169764e9a1279f7c8a9c4cd6e9109ff04bbc0 + languageName: node + linkType: hard + "jest-haste-map@^28.0.0-alpha.0, jest-haste-map@workspace:packages/jest-haste-map": version: 0.0.0-use.local resolution: "jest-haste-map@workspace:packages/jest-haste-map" @@ -13130,6 +13228,18 @@ __metadata: languageName: unknown linkType: soft +"jest-matcher-utils@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-matcher-utils@npm:27.5.1" + dependencies: + chalk: ^4.0.0 + jest-diff: ^27.5.1 + jest-get-type: ^27.5.1 + pretty-format: ^27.5.1 + checksum: bb2135fc48889ff3fe73888f6cc7168ddab9de28b51b3148f820c89fdfd2effdcad005f18be67d0b9be80eda208ad47290f62f03d0a33f848db2dd0273c8217a + languageName: node + linkType: hard + "jest-message-util@^28.0.0-alpha.0, jest-message-util@workspace:packages/jest-message-util": version: 0.0.0-use.local resolution: "jest-message-util@workspace:packages/jest-message-util" @@ -13175,6 +13285,16 @@ __metadata: languageName: unknown linkType: soft +"jest-mock@npm:^27.5.1": + version: 27.5.1 + resolution: "jest-mock@npm:27.5.1" + dependencies: + "@jest/types": ^27.5.1 + "@types/node": "*" + checksum: f5b5904bb1741b4a1687a5f492535b7b1758dc26534c72a5423305f8711292e96a601dec966df81bb313269fb52d47227e29f9c2e08324d79529172f67311be0 + languageName: node + linkType: hard + "jest-phabricator@workspace:packages/jest-phabricator": version: 0.0.0-use.local resolution: "jest-phabricator@workspace:packages/jest-phabricator" From 7291941106396c9901a4d45aac42b788b27aabc3 Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 12:22:55 +0200 Subject: [PATCH 6/9] fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fba7f583def..38b949dba350 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ ### Fixes - `[expect]` Move typings of `.not`, `.rejects` and `.resolves` modifiers outside of `Matchers` interface ([#12346](https://github.com/facebook/jest/pull/12346)) -- `[expect]` Export `AsymmetricMatchers` interface ([#12363](https://github.com/facebook/jest/pull/12363)) +- `[expect]` Expose `AsymmetricMatchers` and `RawMatcherFn` interfaces ([#12363](https://github.com/facebook/jest/pull/12363)) - `[jest-environment-jsdom]` Make `jsdom` accessible to extending environments again ([#12232](https://github.com/facebook/jest/pull/12232)) - `[jest-phabricator]` [**BREAKING**] Convert to ESM ([#12341](https://github.com/facebook/jest/pull/12341)) From 3a6222ed6b9a0ae61b54f6d90a3e53e15c67d2f9 Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 12:23:02 +0200 Subject: [PATCH 7/9] fix resolution --- examples/expect-extend/package.json | 8 +- yarn.lock | 116 ++-------------------------- 2 files changed, 9 insertions(+), 115 deletions(-) diff --git a/examples/expect-extend/package.json b/examples/expect-extend/package.json index 2580ad9d4b47..7ffa1f92b773 100644 --- a/examples/expect-extend/package.json +++ b/examples/expect-extend/package.json @@ -6,10 +6,10 @@ "@babel/core": "*", "@babel/preset-env": "*", "@babel/preset-typescript": "*", - "@jest/globals": "*", - "babel-jest": "*", - "expect": "*", - "jest": "*" + "@jest/globals": "workspace:*", + "babel-jest": "workspace:*", + "expect": "workspace:*", + "jest": "workspace:*" }, "scripts": { "test": "jest" diff --git a/yarn.lock b/yarn.lock index 6d95abdf416c..7f6815a0fea3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2584,18 +2584,6 @@ __metadata: languageName: unknown linkType: soft -"@jest/environment@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/environment@npm:27.5.1" - dependencies: - "@jest/fake-timers": ^27.5.1 - "@jest/types": ^27.5.1 - "@types/node": "*" - jest-mock: ^27.5.1 - checksum: 2a9e18c35a015508dbec5b90b21c150230fa6c1c8cb8fabe029d46ee2ca4c40eb832fb636157da14c66590d0a4c8a2c053226b041f54a44507d6f6a89abefd66 - languageName: node - linkType: hard - "@jest/expect-utils@^28.0.0-alpha.0, @jest/expect-utils@workspace:packages/expect-utils": version: 0.0.0-use.local resolution: "@jest/expect-utils@workspace:packages/expect-utils" @@ -2619,20 +2607,6 @@ __metadata: languageName: unknown linkType: soft -"@jest/fake-timers@npm:^27.5.1": - version: 27.5.1 - resolution: "@jest/fake-timers@npm:27.5.1" - dependencies: - "@jest/types": ^27.5.1 - "@sinonjs/fake-timers": ^8.0.1 - "@types/node": "*" - jest-message-util: ^27.5.1 - jest-mock: ^27.5.1 - jest-util: ^27.5.1 - checksum: 02a0561ed2f4586093facd4ae500b74694f187ac24d4a00e949a39a1c5325bca8932b4fcb0388a2c5ed0656506fc1cf51fd3e32cdd48cea7497ad9c6e028aba8 - languageName: node - linkType: hard - "@jest/globals@^28.0.0-alpha.0, @jest/globals@workspace:*, @jest/globals@workspace:packages/jest-globals": version: 0.0.0-use.local resolution: "@jest/globals@workspace:packages/jest-globals" @@ -2643,17 +2617,6 @@ __metadata: languageName: unknown linkType: soft -"@jest/globals@npm:*": - version: 27.5.1 - resolution: "@jest/globals@npm:27.5.1" - dependencies: - "@jest/environment": ^27.5.1 - "@jest/types": ^27.5.1 - expect: ^27.5.1 - checksum: 087f97047e9dcf555f76fe2ce54aee681e005eaa837a0c0c2d251df6b6412c892c9df54cb871b180342114389a5ff895a4e52e6e6d3d0015bf83c02a54f64c3c - languageName: node - linkType: hard - "@jest/monorepo@workspace:.": version: 0.0.0-use.local resolution: "@jest/monorepo@workspace:." @@ -4412,15 +4375,6 @@ __metadata: languageName: node linkType: hard -"@sinonjs/fake-timers@npm:^8.0.1": - version: 8.1.0 - resolution: "@sinonjs/fake-timers@npm:8.1.0" - dependencies: - "@sinonjs/commons": ^1.7.0 - checksum: 09b5a158ce013a6c37613258bad79ca4efeb99b1f59c41c73cca36cac00b258aefcf46eeea970fccf06b989414d86fe9f54c1102272c0c3bdd51a313cea80949 - languageName: node - linkType: hard - "@sinonjs/fake-timers@npm:^9.1.0": version: 9.1.0 resolution: "@sinonjs/fake-timers@npm:9.1.0" @@ -8962,13 +8916,6 @@ __metadata: languageName: node linkType: hard -"diff-sequences@npm:^27.5.1": - version: 27.5.1 - resolution: "diff-sequences@npm:27.5.1" - checksum: a00db5554c9da7da225db2d2638d85f8e41124eccbd56cbaefb3b276dcbb1c1c2ad851c32defe2055a54a4806f030656cbf6638105fd6ce97bb87b90b32a33ca - languageName: node - linkType: hard - "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -9956,10 +9903,10 @@ __metadata: "@babel/core": "*" "@babel/preset-env": "*" "@babel/preset-typescript": "*" - "@jest/globals": "*" - babel-jest: "*" - expect: "*" - jest: "*" + "@jest/globals": "workspace:*" + babel-jest: "workspace:*" + expect: "workspace:*" + jest: "workspace:*" languageName: unknown linkType: soft @@ -10172,7 +10119,7 @@ __metadata: languageName: node linkType: hard -"expect@^28.0.0-alpha.0, expect@workspace:packages/expect": +"expect@^28.0.0-alpha.0, expect@workspace:*, expect@workspace:packages/expect": version: 0.0.0-use.local resolution: "expect@workspace:packages/expect" dependencies: @@ -10190,18 +10137,6 @@ __metadata: languageName: unknown linkType: soft -"expect@npm:*, expect@npm:^27.5.1": - version: 27.5.1 - resolution: "expect@npm:27.5.1" - dependencies: - "@jest/types": ^27.5.1 - jest-get-type: ^27.5.1 - jest-matcher-utils: ^27.5.1 - jest-message-util: ^27.5.1 - checksum: b2c66beb52de53ef1872165aace40224e722bca3c2274c54cfa74b6d617d55cf0ccdbf36783ccd64dbea501b280098ed33fd0b207d4f15bc03cd3c7a24364a6a - languageName: node - linkType: hard - "express@npm:^4.17.1": version: 4.17.2 resolution: "express@npm:4.17.2" @@ -13032,18 +12967,6 @@ __metadata: languageName: node linkType: hard -"jest-diff@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-diff@npm:27.5.1" - dependencies: - chalk: ^4.0.0 - diff-sequences: ^27.5.1 - jest-get-type: ^27.5.1 - pretty-format: ^27.5.1 - checksum: 8be27c1e1ee57b2bb2bef9c0b233c19621b4c43d53a3c26e2c00a4e805eb4ea11fe1694a06a9fb0e80ffdcfdc0d2b1cb0b85920b3f5c892327ecd1e7bd96b865 - languageName: node - linkType: hard - "jest-docblock@^28.0.0-alpha.0, jest-docblock@workspace:packages/jest-docblock": version: 0.0.0-use.local resolution: "jest-docblock@workspace:packages/jest-docblock" @@ -13108,13 +13031,6 @@ __metadata: languageName: node linkType: hard -"jest-get-type@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-get-type@npm:27.5.1" - checksum: 63064ab70195c21007d897c1157bf88ff94a790824a10f8c890392e7d17eda9c3900513cb291ca1c8d5722cad79169764e9a1279f7c8a9c4cd6e9109ff04bbc0 - languageName: node - linkType: hard - "jest-haste-map@^28.0.0-alpha.0, jest-haste-map@workspace:packages/jest-haste-map": version: 0.0.0-use.local resolution: "jest-haste-map@workspace:packages/jest-haste-map" @@ -13228,18 +13144,6 @@ __metadata: languageName: unknown linkType: soft -"jest-matcher-utils@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-matcher-utils@npm:27.5.1" - dependencies: - chalk: ^4.0.0 - jest-diff: ^27.5.1 - jest-get-type: ^27.5.1 - pretty-format: ^27.5.1 - checksum: bb2135fc48889ff3fe73888f6cc7168ddab9de28b51b3148f820c89fdfd2effdcad005f18be67d0b9be80eda208ad47290f62f03d0a33f848db2dd0273c8217a - languageName: node - linkType: hard - "jest-message-util@^28.0.0-alpha.0, jest-message-util@workspace:packages/jest-message-util": version: 0.0.0-use.local resolution: "jest-message-util@workspace:packages/jest-message-util" @@ -13285,16 +13189,6 @@ __metadata: languageName: unknown linkType: soft -"jest-mock@npm:^27.5.1": - version: 27.5.1 - resolution: "jest-mock@npm:27.5.1" - dependencies: - "@jest/types": ^27.5.1 - "@types/node": "*" - checksum: f5b5904bb1741b4a1687a5f492535b7b1758dc26534c72a5423305f8711292e96a601dec966df81bb313269fb52d47227e29f9c2e08324d79529172f67311be0 - languageName: node - linkType: hard - "jest-phabricator@workspace:packages/jest-phabricator": version: 0.0.0-use.local resolution: "jest-phabricator@workspace:packages/jest-phabricator" From bc691907cfe469557fc756ba944ff6f63e2458ee Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 12:30:32 +0200 Subject: [PATCH 8/9] tweak tsconfig --- packages/expect/tsconfig.json | 4 +--- tsconfig.json | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/expect/tsconfig.json b/packages/expect/tsconfig.json index 8bd68af78fd1..3609d0f6e862 100644 --- a/packages/expect/tsconfig.json +++ b/packages/expect/tsconfig.json @@ -2,9 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "rootDir": "src", - "outDir": "build", - - "stripInternal": true + "outDir": "build" }, "include": ["./src/**/*"], "exclude": ["./**/__tests__/**/*"], diff --git a/tsconfig.json b/tsconfig.json index 90c8a266d483..cff2131d1fb2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,11 @@ { "extends": "@tsconfig/node12/tsconfig.json", "compilerOptions": { - "declaration": true, "composite": true, + "declaration": true, "emitDeclarationOnly": true, - "isolatedModules": true, "importsNotUsedAsValues": "error", + "stripInternal": true, "strict": true, @@ -19,6 +19,7 @@ "moduleResolution": "node", /* This needs to be false so our types are possible to consume without setting this */ "esModuleInterop": false, + "isolatedModules": true, "skipLibCheck": false, "resolveJsonModule": true } From 4290c2f38b2758acadc6904615fb6acc92e0aabd Mon Sep 17 00:00:00 2001 From: mrazauskas <72159681+mrazauskas@users.noreply.github.com> Date: Fri, 11 Feb 2022 15:35:20 +0200 Subject: [PATCH 9/9] clean up --- packages/expect/src/index.ts | 2 +- packages/expect/src/types.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/expect/src/index.ts b/packages/expect/src/index.ts index ce4ab6e64384..1be8f83c9c0c 100644 --- a/packages/expect/src/index.ts +++ b/packages/expect/src/index.ts @@ -364,7 +364,7 @@ const makeThrowingMatcher = ( expect.extend = ( matchers: MatchersObject, -): void => setMatchers(matchers, false, expect); +) => setMatchers(matchers, false, expect); expect.anything = anything; expect.any = any; diff --git a/packages/expect/src/types.ts b/packages/expect/src/types.ts index 3fcdfa093baf..9e037c42d9f0 100644 --- a/packages/expect/src/types.ts +++ b/packages/expect/src/types.ts @@ -13,7 +13,7 @@ import {INTERNAL_MATCHER_FLAG} from './jestMatchersObject'; export type SyncExpectationResult = { pass: boolean; - message: () => string; + message(): string; }; export type AsyncExpectationResult = Promise; @@ -21,7 +21,7 @@ export type AsyncExpectationResult = Promise; export type ExpectationResult = SyncExpectationResult | AsyncExpectationResult; export type RawMatcherFn = { - (this: T, received: any, expected: any, options?: any): ExpectationResult; + (this: T, actual: any, expected: any, options?: any): ExpectationResult; /** @internal */ [INTERNAL_MATCHER_FLAG]?: boolean; }; @@ -32,7 +32,7 @@ export type PromiseMatcherFn = (actual: any) => Promise; export type MatcherState = { assertionCalls: number; currentTestName?: string; - dontThrow?: () => void; + dontThrow?(): void; error?: Error; equals: EqualsFunction; expand?: boolean; @@ -57,7 +57,7 @@ export interface AsymmetricMatcher { toAsymmetricMatcher?(): string; } export type MatchersObject = { - [id: string]: RawMatcherFn; + [name: string]: RawMatcherFn; }; export type ExpectedAssertionsErrors = Array<{ actual: string | number; @@ -74,7 +74,7 @@ export type Expect = { assertions(numberOfAssertions: number): void; // TODO: remove this `T extends` - should get from some interface merging extend(matchers: MatchersObject): void; - extractExpectedAssertionsErrors: () => ExpectedAssertionsErrors; + extractExpectedAssertionsErrors(): ExpectedAssertionsErrors; getState(): State; hasAssertions(): void; setState(state: Partial): void;