Skip to content

Commit

Permalink
chore: clean types of circus initialization types (#10483)
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB authored Sep 7, 2020
1 parent cd8828f commit c5785b9
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 70 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
24 changes: 9 additions & 15 deletions packages/expect/src/extractExpectedAssertionsErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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,
Expand All @@ -51,7 +45,7 @@ const extractExpectedAssertionsErrors: () => AssertionsErrors = () => {
pluralize('assertion', expectedAssertionsNumber),
);

expectedAssertionsNumberError.message =
expectedAssertionsNumberError!.message =
matcherHint('.assertions', '', String(expectedAssertionsNumber), {
isDirectExpectCall: true,
}) +
Expand All @@ -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,
}) +
Expand All @@ -79,7 +73,7 @@ const extractExpectedAssertionsErrors: () => AssertionsErrors = () => {

result.push({
actual: 'none',
error: isExpectingAssertionsError,
error: isExpectingAssertionsError!,
expected: 'at least one',
});
}
Expand Down
25 changes: 16 additions & 9 deletions packages/expect/src/jestMatchersObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<MatcherState> = {
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<MatcherState>): void => {
Object.assign((global as any)[JEST_MATCHERS_OBJECT].state, state);
};

Expand Down
17 changes: 10 additions & 7 deletions packages/expect/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Error>;
Expand All @@ -54,20 +56,21 @@ export type MatcherState = {

export type AsymmetricMatcher = Record<string, any>;
export type MatchersObject = {[id: string]: RawMatcherFn};
export type ExpectedAssertionsErrors = Array<{
actual: string | number;
error: Error;
expected: string;
}>;
export type Expect = {
<T = unknown>(actual: T): Matchers<T>;
// 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<MatcherState>): void;

any(expectedObject: any): AsymmetricMatcher;
anything(): AsymmetricMatcher;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<unknown>,
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 = (
Expand All @@ -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);

Expand All @@ -124,19 +129,15 @@ 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.
// Therefore, add in reverse because the last added is the first tested.
config.snapshotSerializers
.concat()
.reverse()
.forEach(path => {
addSerializer(localRequire(path));
});
.forEach(path => addSerializer(localRequire(path)));

const {expand, updateSnapshot} = globalConfig;
const snapshotResolver = buildSnapshotResolver(config);
Expand All @@ -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));
Expand All @@ -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 ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 1 addition & 3 deletions packages/jest-jasmine2/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ async function jasmine2(
.requireInternalModule<typeof import('./jestExpect')>(
path.resolve(__dirname, './jestExpect.js'),
)
.default({
expand: globalConfig.expand,
});
.default({expand: globalConfig.expand});

if (globalConfig.errorOnDeprecated) {
installErrorOnPrivate(environment.global);
Expand Down
1 change: 1 addition & 0 deletions packages/jest-jasmine2/src/setup_jest_globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 10 additions & 7 deletions packages/jest-runtime/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -564,15 +567,15 @@ class Runtime {
}
}

return this.requireModule(from, to, {
return this.requireModule<T>(from, to, {
isInternalModule: true,
supportsDynamicImport: false,
supportsStaticESM: false,
});
}

requireActual<T = unknown>(from: Config.Path, moduleName: string): T {
return this.requireModule(from, moduleName, undefined, true);
return this.requireModule<T>(from, moduleName, undefined, true);
}

requireMock<T = unknown>(from: Config.Path, moduleName: string): T {
Expand Down Expand Up @@ -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');
Expand All @@ -1657,7 +1660,7 @@ class Runtime {
this.jestObjectCaches.set(from, jest);
}

const globals: JestGlobalsValues = {
const globals: JestGlobalsWithJest = {
...this.getGlobalsFromEnvironment(),
jest,
};
Expand All @@ -1682,7 +1685,7 @@ class Runtime {
return module;
}

private getGlobalsFromEnvironment(): Omit<JestGlobalsValues, 'jest'> {
private getGlobalsFromEnvironment(): JestGlobals {
return {
afterAll: this._environment.global.afterAll,
afterEach: this._environment.global.afterEach,
Expand Down
Loading

0 comments on commit c5785b9

Please sign in to comment.