From c5785b9a71cc2edd8091cf67eae000c76010315c Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 7 Sep 2020 07:07:24 +0200 Subject: [PATCH] chore: clean types of circus initialization types (#10483) --- package.json | 1 + .../src/extractExpectedAssertionsErrors.ts | 24 ++++------ packages/expect/src/jestMatchersObject.ts | 25 ++++++---- packages/expect/src/types.ts | 17 ++++--- .../jestAdapterInit.ts | 46 ++++++++++--------- .../legacy-code-todo-rewrite/jestExpect.ts | 4 +- packages/jest-jasmine2/src/index.ts | 4 +- .../jest-jasmine2/src/setup_jest_globals.ts | 1 + packages/jest-runtime/src/index.ts | 17 ++++--- scripts/buildUtils.js | 9 ++-- yarn.lock | 1 + 11 files changed, 79 insertions(+), 70 deletions(-) diff --git a/package.json b/package.json index f314121c0225..9534da348d64 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "prettier": "^2.1.1", "progress": "^2.0.0", "promise": "^8.0.2", + "read-pkg": "^5.2.0", "resolve": "^1.15.0", "rimraf": "^3.0.0", "semver": "^7.3.2", diff --git a/packages/expect/src/extractExpectedAssertionsErrors.ts b/packages/expect/src/extractExpectedAssertionsErrors.ts index 44aa5ba95b2a..d4d19e8bbaca 100644 --- a/packages/expect/src/extractExpectedAssertionsErrors.ts +++ b/packages/expect/src/extractExpectedAssertionsErrors.ts @@ -12,8 +12,8 @@ import { matcherHint, pluralize, } from 'jest-matcher-utils'; - import {getState, setState} from './jestMatchersObject'; +import type {Expect, ExpectedAssertionsErrors} from './types'; const resetAssertionsLocalState = () => { setState({ @@ -23,16 +23,10 @@ const resetAssertionsLocalState = () => { }); }; -type AssertionsErrors = Array<{ - actual: string; - error: string; - expected: string | number; -}>; - // Create and format all errors related to the mismatched number of `expect` // calls and reset the matcher's state. -const extractExpectedAssertionsErrors: () => AssertionsErrors = () => { - const result: AssertionsErrors = []; +const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors'] = () => { + const result: ExpectedAssertionsErrors = []; const { assertionCalls, expectedAssertionsNumber, @@ -51,7 +45,7 @@ const extractExpectedAssertionsErrors: () => AssertionsErrors = () => { pluralize('assertion', expectedAssertionsNumber), ); - expectedAssertionsNumberError.message = + expectedAssertionsNumberError!.message = matcherHint('.assertions', '', String(expectedAssertionsNumber), { isDirectExpectCall: true, }) + @@ -61,16 +55,16 @@ const extractExpectedAssertionsErrors: () => AssertionsErrors = () => { '.'; result.push({ - actual: assertionCalls, - error: expectedAssertionsNumberError, - expected: expectedAssertionsNumber, + actual: assertionCalls.toString(), + error: expectedAssertionsNumberError!, + expected: expectedAssertionsNumber.toString(), }); } if (isExpectingAssertions && assertionCalls === 0) { const expected = EXPECTED_COLOR('at least one assertion'); const received = RECEIVED_COLOR('received none'); - isExpectingAssertionsError.message = + isExpectingAssertionsError!.message = matcherHint('.hasAssertions', '', '', { isDirectExpectCall: true, }) + @@ -79,7 +73,7 @@ const extractExpectedAssertionsErrors: () => AssertionsErrors = () => { result.push({ actual: 'none', - error: isExpectingAssertionsError, + error: isExpectingAssertionsError!, expected: 'at least one', }); } diff --git a/packages/expect/src/jestMatchersObject.ts b/packages/expect/src/jestMatchersObject.ts index 24b2c087071c..93876b220d60 100644 --- a/packages/expect/src/jestMatchersObject.ts +++ b/packages/expect/src/jestMatchersObject.ts @@ -7,7 +7,12 @@ */ import {AsymmetricMatcher} from './asymmetricMatchers'; -import type {Expect, MatchersObject, SyncExpectationResult} from './types'; +import type { + Expect, + MatcherState, + MatchersObject, + SyncExpectationResult, +} from './types'; // Global matchers object holds the list of available matchers and // the state, that can hold matcher specific values that change over time. @@ -18,22 +23,24 @@ const JEST_MATCHERS_OBJECT = Symbol.for('$$jest-matchers-object'); export const INTERNAL_MATCHER_FLAG = Symbol.for('$$jest-internal-matcher'); if (!global.hasOwnProperty(JEST_MATCHERS_OBJECT)) { + const defaultState: Partial = { + assertionCalls: 0, + expectedAssertionsNumber: null, + isExpectingAssertions: false, + suppressedErrors: [], // errors that are not thrown immediately. + }; Object.defineProperty(global, JEST_MATCHERS_OBJECT, { value: { matchers: Object.create(null), - state: { - assertionCalls: 0, - expectedAssertionsNumber: null, - isExpectingAssertions: false, - suppressedErrors: [], // errors that are not thrown immediately. - }, + state: defaultState, }, }); } -export const getState = (): any => (global as any)[JEST_MATCHERS_OBJECT].state; +export const getState = (): MatcherState => + (global as any)[JEST_MATCHERS_OBJECT].state; -export const setState = (state: object): void => { +export const setState = (state: Partial): void => { Object.assign((global as any)[JEST_MATCHERS_OBJECT].state, state); }; diff --git a/packages/expect/src/types.ts b/packages/expect/src/types.ts index 54b8486a15b1..e7555c2c09e4 100644 --- a/packages/expect/src/types.ts +++ b/packages/expect/src/types.ts @@ -40,8 +40,10 @@ export type MatcherState = { strictCheck?: boolean, ) => boolean; expand?: boolean; - expectedAssertionsNumber?: number; + expectedAssertionsNumber?: number | null; + expectedAssertionsNumberError?: Error; isExpectingAssertions?: boolean; + isExpectingAssertionsError?: Error; isNot: boolean; promise: string; suppressedErrors: Array; @@ -54,20 +56,21 @@ export type MatcherState = { export type AsymmetricMatcher = Record; export type MatchersObject = {[id: string]: RawMatcherFn}; +export type ExpectedAssertionsErrors = Array<{ + actual: string | number; + error: Error; + expected: string; +}>; export type Expect = { (actual: T): Matchers; // TODO: this is added by test runners, not `expect` itself addSnapshotSerializer(arg0: any): void; assertions(arg0: number): void; extend(arg0: any): void; - extractExpectedAssertionsErrors: () => Array<{ - actual: string | number; - error: Error; - expected: string; - }>; + extractExpectedAssertionsErrors: () => ExpectedAssertionsErrors; getState(): MatcherState; hasAssertions(): void; - setState(arg0: any): void; + setState(state: Partial): void; any(expectedObject: any): AsymmetricMatcher; anything(): AsymmetricMatcher; diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts index c55a067919fb..7841fccd2e0c 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts @@ -37,8 +37,6 @@ import globals from '..'; type Process = NodeJS.Process; -// TODO: hard to type -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const initialize = async ({ config, environment, @@ -59,36 +57,40 @@ export const initialize = async ({ testPath: Config.Path; parentProcess: Process; sendMessageToJest?: TestFileEvent; -}) => { +}): Promise<{ + globals: Global.TestFrameworkGlobals; + snapshotState: SnapshotStateType; +}> => { if (globalConfig.testTimeout) { getRunnerState().testTimeout = globalConfig.testTimeout; } const mutex = throat(globalConfig.maxConcurrency); - const nodeGlobal = global as Global.Global; - Object.assign(nodeGlobal, globals); - - nodeGlobal.xit = nodeGlobal.it.skip; - nodeGlobal.xtest = nodeGlobal.it.skip; - nodeGlobal.xdescribe = nodeGlobal.describe.skip; - nodeGlobal.fit = nodeGlobal.it.only; - nodeGlobal.fdescribe = nodeGlobal.describe.only; + // @ts-expect-error + const globalsObject: Global.TestFrameworkGlobals = { + ...globals, + fdescribe: globals.describe.only, + fit: globals.it.only, + xdescribe: globals.describe.skip, + xit: globals.it.skip, + xtest: globals.it.skip, + }; - nodeGlobal.test.concurrent = (test => { + globalsObject.test.concurrent = (test => { const concurrent = ( testName: string, testFn: () => Promise, timeout?: number, ) => { // For concurrent tests we first run the function that returns promise, and then register a - // nomral test that will be waiting on the returned promise (when we start the test, the promise + // normal test that will be waiting on the returned promise (when we start the test, the promise // will already be in the process of execution). // Unfortunately at this stage there's no way to know if there are any `.only` tests in the suite // that will result in this test to be skipped, so we'll be executing the promise function anyway, // even if it ends up being skipped. const promise = mutex(() => testFn()); - nodeGlobal.test(testName, () => promise, timeout); + globalsObject.test(testName, () => promise, timeout); }; const only = ( @@ -109,7 +111,10 @@ export const initialize = async ({ only.each = bind(test.only, false); return concurrent; - })(nodeGlobal.test); + })(globalsObject.test); + + const nodeGlobal = global as Global.Global; + Object.assign(nodeGlobal, globalsObject); addEventHandler(eventHandler); @@ -124,9 +129,7 @@ export const initialize = async ({ }); if (config.testLocationInResults) { - await dispatch({ - name: 'include_test_location_in_result', - }); + await dispatch({name: 'include_test_location_in_result'}); } // Jest tests snapshotSerializers in order preceding built-in serializers. @@ -134,9 +137,7 @@ export const initialize = async ({ config.snapshotSerializers .concat() .reverse() - .forEach(path => { - addSerializer(localRequire(path)); - }); + .forEach(path => addSerializer(localRequire(path))); const {expand, updateSnapshot} = globalConfig; const snapshotResolver = buildSnapshotResolver(config); @@ -147,6 +148,7 @@ export const initialize = async ({ getPrettier, updateSnapshot, }); + // @ts-expect-error: snapshotState is a jest extension of `expect` setState({snapshotState, testPath}); addEventHandler(handleSnapshotStateAfterRetry(snapshotState)); @@ -155,7 +157,7 @@ export const initialize = async ({ } // Return it back to the outer scope (test runner outside the VM). - return {globals, snapshotState}; + return {globals: globalsObject, snapshotState}; }; export const runAndTransformResultsToJestFormat = async ({ diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestExpect.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestExpect.ts index 8633be79fe97..064f1d800595 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestExpect.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestExpect.ts @@ -17,9 +17,7 @@ import { export default (config: {expand: boolean}): void => { global.expect = expect; - expect.setState({ - expand: config.expand, - }); + expect.setState({expand: config.expand}); expect.extend({ toMatchInlineSnapshot, toMatchSnapshot, diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index 7c081b7846b1..14378d66e798 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -127,9 +127,7 @@ async function jasmine2( .requireInternalModule( path.resolve(__dirname, './jestExpect.js'), ) - .default({ - expand: globalConfig.expand, - }); + .default({expand: globalConfig.expand}); if (globalConfig.errorOnDeprecated) { installErrorOnPrivate(environment.global); diff --git a/packages/jest-jasmine2/src/setup_jest_globals.ts b/packages/jest-jasmine2/src/setup_jest_globals.ts index 492ec9e3aef5..4164015263bc 100644 --- a/packages/jest-jasmine2/src/setup_jest_globals.ts +++ b/packages/jest-jasmine2/src/setup_jest_globals.ts @@ -115,6 +115,7 @@ export default ({ config.prettierPath ? require(config.prettierPath) : null, updateSnapshot, }); + // @ts-expect-error: snapshotState is a jest extension of `expect` setState({snapshotState, testPath}); // Return it back to the outer scope (test runner outside the VM). return snapshotState; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 522adabd1eb1..bedb854ee461 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -57,11 +57,14 @@ import { import {options as cliOptions} from './cli/args'; import {run as cliRun} from './cli'; -interface JestGlobalsValues extends Global.TestFrameworkGlobals { - jest: typeof JestGlobals.jest; +interface JestGlobals extends Global.TestFrameworkGlobals { expect: typeof JestGlobals.expect; } +interface JestGlobalsWithJest extends JestGlobals { + jest: typeof JestGlobals.jest; +} + type HasteMapOptions = { console?: Console; maxWorkers: number; @@ -564,7 +567,7 @@ class Runtime { } } - return this.requireModule(from, to, { + return this.requireModule(from, to, { isInternalModule: true, supportsDynamicImport: false, supportsStaticESM: false, @@ -572,7 +575,7 @@ class Runtime { } requireActual(from: Config.Path, moduleName: string): T { - return this.requireModule(from, moduleName, undefined, true); + return this.requireModule(from, moduleName, undefined, true); } requireMock(from: Config.Path, moduleName: string): T { @@ -1637,7 +1640,7 @@ class Runtime { throw e; } - private getGlobalsForCjs(from: Config.Path): JestGlobalsValues { + private getGlobalsForCjs(from: Config.Path): JestGlobalsWithJest { const jest = this.jestObjectCaches.get(from); invariant(jest, 'There should always be a Jest object already'); @@ -1657,7 +1660,7 @@ class Runtime { this.jestObjectCaches.set(from, jest); } - const globals: JestGlobalsValues = { + const globals: JestGlobalsWithJest = { ...this.getGlobalsFromEnvironment(), jest, }; @@ -1682,7 +1685,7 @@ class Runtime { return module; } - private getGlobalsFromEnvironment(): Omit { + private getGlobalsFromEnvironment(): JestGlobals { return { afterAll: this._environment.global.afterAll, afterEach: this._environment.global.afterEach, diff --git a/scripts/buildUtils.js b/scripts/buildUtils.js index 5241a9ae7842..979636c24016 100644 --- a/scripts/buildUtils.js +++ b/scripts/buildUtils.js @@ -11,6 +11,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); +const {sync: readPkg} = require('read-pkg'); const stringLength = require('string-length'); const rootPackage = require('../package.json'); @@ -25,20 +26,20 @@ module.exports.getPackages = function getPackages() { .map(file => path.resolve(PACKAGES_DIR, file)) .filter(f => fs.lstatSync(path.resolve(f)).isDirectory()); - const nodeEngineRequiremnt = rootPackage.engines.node; + const nodeEngineRequirement = rootPackage.engines.node; packages.forEach(packageDir => { - const pkg = require(`${packageDir}/package.json`); + const pkg = readPkg({cwd: packageDir}); assert.ok(pkg.engines, `Engine requirement in ${pkg.name} should exist`); - assert.equal( + assert.strictEqual( pkg.engines.node, pkg.name === 'jest-worker' ? '>= 10.13.0' : pkg.name === 'pretty-format' ? '>= 10' - : nodeEngineRequiremnt, + : nodeEngineRequirement, `Engine requirement in ${pkg.name} should match root`, ); }); diff --git a/yarn.lock b/yarn.lock index da3c6d446e3a..364f134a469c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17017,6 +17017,7 @@ fsevents@^1.2.7: prettier: ^2.1.1 progress: ^2.0.0 promise: ^8.0.2 + read-pkg: ^5.2.0 resolve: ^1.15.0 rimraf: ^3.0.0 semver: ^7.3.2