From c83051789cc60789f2c575374270236e3a428879 Mon Sep 17 00:00:00 2001 From: ychi Date: Sun, 12 Apr 2020 19:06:44 +0200 Subject: [PATCH 01/39] feat: Make console.error and warn log a stack trace and codeframe like thrown errors do (#9741) --- CHANGELOG.md | 1 + .../__snapshots__/beforeAllFiltered.ts.snap | 20 +++- .../__snapshots__/beforeEachQueue.ts.snap | 20 +++- .../__snapshots__/console.test.ts.snap | 87 ++++++++++++--- .../consoleAfterTeardown.test.ts.snap | 2 +- ...consoleLogOutputWhenRunInBand.test.ts.snap | 4 +- .../declarationErrors.test.ts.snap | 4 +- .../__snapshots__/jest.config.js.test.ts.snap | 4 +- .../__snapshots__/v8Coverage.test.ts.snap | 16 +++ e2e/__tests__/beforeAllFiltered.ts | 8 +- .../consoleLogOutputWhenRunInBand.test.ts | 18 ++- e2e/__tests__/declarationErrors.test.ts | 3 +- e2e/__tests__/resolveBrowserField.test.ts | 4 +- e2e/__tests__/v8Coverage.test.ts | 21 +--- packages/jest-console/package.json | 3 +- packages/jest-console/src/BufferedConsole.ts | 28 +++-- packages/jest-console/src/getConsoleOutput.ts | 40 +++++-- packages/jest-console/tsconfig.json | 3 +- .../__snapshots__/messages.test.ts.snap | 30 ++++- .../src/__tests__/messages.test.ts | 104 +++++++++++++++++- packages/jest-message-util/src/index.ts | 36 +++--- .../jest-reporters/src/default_reporter.ts | 1 + packages/jest-runner/src/runTest.ts | 19 +--- 23 files changed, 373 insertions(+), 103 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index fc943294bc3f..dbed475bddec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) ### Fixes diff --git a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap index 247de33015d5..77cb833acb56 100644 --- a/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeAllFiltered.ts.snap @@ -1,19 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Correct BeforeAll run ensures the BeforeAll of ignored suite is not run 1`] = ` - console.log __tests__/beforeAllFiltered.test.js:10 + console.log beforeAll 1 - console.log __tests__/beforeAllFiltered.test.js:13 + at log (__tests__/beforeAllFiltered.test.js:10:13) + + console.log beforeEach 1 - console.log __tests__/beforeAllFiltered.test.js:22 + at log (__tests__/beforeAllFiltered.test.js:13:13) + + console.log It Foo - console.log __tests__/beforeAllFiltered.test.js:16 + at log (__tests__/beforeAllFiltered.test.js:22:13) + + console.log afterEach 1 - console.log __tests__/beforeAllFiltered.test.js:19 + at log (__tests__/beforeAllFiltered.test.js:16:13) + + console.log afterAll 1 + at log (__tests__/beforeAllFiltered.test.js:19:13) + `; diff --git a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap index a665905a9f06..4acca9e4a59d 100644 --- a/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap +++ b/e2e/__tests__/__snapshots__/beforeEachQueue.ts.snap @@ -1,19 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Correct beforeEach order ensures the correct order for beforeEach 1`] = ` - console.log __tests__/beforeEachQueue.test.js:10 + console.log BeforeEach - console.log __tests__/beforeEachQueue.test.js:14 + at Object.log (__tests__/beforeEachQueue.test.js:10:13) + + console.log It Foo - console.log __tests__/beforeEachQueue.test.js:17 + at Object.log (__tests__/beforeEachQueue.test.js:14:13) + + console.log BeforeEach Inline Foo - console.log __tests__/beforeEachQueue.test.js:10 + at Object.log (__tests__/beforeEachQueue.test.js:17:15) + + console.log BeforeEach - console.log __tests__/beforeEachQueue.test.js:22 + at Object.log (__tests__/beforeEachQueue.test.js:10:13) + + console.log It Bar + at Object.log (__tests__/beforeEachQueue.test.js:22:13) + `; diff --git a/e2e/__tests__/__snapshots__/console.test.ts.snap b/e2e/__tests__/__snapshots__/console.test.ts.snap index 8077db761de9..161e2e9e4c21 100644 --- a/e2e/__tests__/__snapshots__/console.test.ts.snap +++ b/e2e/__tests__/__snapshots__/console.test.ts.snap @@ -4,14 +4,40 @@ exports[`console printing 1`] = ` PASS __tests__/console.test.js ● Console - console.log __tests__/console.test.js:10 + console.log This is a log message. - console.info __tests__/console.test.js:12 + + at Object.log (__tests__/console.test.js:10:11) + + console.info This is an info message. - console.warn __tests__/console.test.js:14 + + at Object.info (__tests__/console.test.js:12:11) + + console.warn This is a warning message. - console.error __tests__/console.test.js:16 + + 12 | console.info('This is an info message.'); + 13 | + > 14 | console.warn('This is a warning message.'); + | ^ + 15 | + 16 | console.error('This is an error message.'); + 17 | }); + + at Object.warn (__tests__/console.test.js:14:11) + + console.error This is an error message. + + 14 | console.warn('This is a warning message.'); + 15 | + > 16 | console.error('This is an error message.'); + | ^ + 17 | }); + 18 | + + at Object.error (__tests__/console.test.js:16:11) `; exports[`console printing 2`] = ` @@ -23,18 +49,41 @@ Ran all test suites. `; exports[`console printing with --verbose 1`] = ` - console.log __tests__/console.test.js:10 + console.log This is a log message. - console.info __tests__/console.test.js:12 + at Object.log (__tests__/console.test.js:10:11) + + console.info This is an info message. - console.warn __tests__/console.test.js:14 + at Object.info (__tests__/console.test.js:12:11) + + console.warn This is a warning message. - console.error __tests__/console.test.js:16 + 12 | console.info('This is an info message.'); + 13 | + > 14 | console.warn('This is a warning message.'); + | ^ + 15 | + 16 | console.error('This is an error message.'); + 17 | }); + + at Object.warn (__tests__/console.test.js:14:11) + + console.error This is an error message. + 14 | console.warn('This is a warning message.'); + 15 | + > 16 | console.error('This is an error message.'); + | ^ + 17 | }); + 18 | + + at Object.error (__tests__/console.test.js:16:11) + `; exports[`console printing with --verbose 2`] = ` @@ -56,17 +105,25 @@ exports[`does not error out when using winston 2`] = ` PASS __tests__/console.test.js ● Console - console.log node_modules/winston/lib/winston/transports/console.js:79 + console.log {"level":"info","message":"Log message from winston"} - - console.log node_modules/winston/lib/winston/transports/console.js:79 + + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + + console.log {"message":"Info message from winston","level":"info"} - - console.log node_modules/winston/lib/winston/transports/console.js:79 + + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + + console.log {"message":"Warn message from winston","level":"warn"} - - console.log node_modules/winston/lib/winston/transports/console.js:79 + + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) + + console.log {"message":"Error message from winston","level":"error"} + + at Console.log (node_modules/winston/lib/winston/transports/console.js:79:23) `; exports[`does not error out when using winston 3`] = ` diff --git a/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap b/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap index 80308c7d489c..c75128492c2e 100644 --- a/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap +++ b/e2e/__tests__/__snapshots__/consoleAfterTeardown.test.ts.snap @@ -15,6 +15,6 @@ PASS __tests__/console.test.js 14 | }); 15 | - at BufferedConsole.log (../../packages/jest-console/build/BufferedConsole.js:199:10) + at BufferedConsole.log (../../packages/jest-console/build/BufferedConsole.js:201:10) at log (__tests__/console.test.js:12:13) `; diff --git a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap index fb009e134aed..571dd419e639 100644 --- a/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap +++ b/e2e/__tests__/__snapshots__/consoleLogOutputWhenRunInBand.test.ts.snap @@ -17,7 +17,9 @@ Ran all test suites. `; exports[`prints console.logs when run with forceExit 3`] = ` - console.log __tests__/a-banana.js:1 + console.log Hey + at Object. (__tests__/a-banana.js:1:1) + `; diff --git a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap index ee816f95e8a1..017f5cc6d332 100644 --- a/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap +++ b/e2e/__tests__/__snapshots__/declarationErrors.test.ts.snap @@ -16,7 +16,7 @@ exports[`warns if describe returns a Promise 1`] = ` 14 | }); at Object.describe (__tests__/describeReturnPromise.test.js:11:1) - + `; @@ -36,6 +36,6 @@ exports[`warns if describe returns something 1`] = ` 14 | }); at Object.describe (__tests__/describeReturnSomething.test.js:11:1) - + `; diff --git a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap index 498c5c97bfd8..db94a91b08e4 100644 --- a/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap +++ b/e2e/__tests__/__snapshots__/jest.config.js.test.ts.snap @@ -1,9 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`traverses directory tree up until it finds jest.config 1`] = ` - console.log ../../../__tests__/a-banana.js:3 + console.log <>/jest.config.js/some/nested/directory + at Object.log (__tests__/a-banana.js:3:27) + `; exports[`traverses directory tree up until it finds jest.config 2`] = ` diff --git a/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap b/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap new file mode 100644 index 000000000000..a3fabf97c9d7 --- /dev/null +++ b/e2e/__tests__/__snapshots__/v8Coverage.test.ts.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`on node >=10 prints coverage 1`] = ` +" console.log + 42 + + at Object.log (__tests__/Thing.test.js:10:9) + +----------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +----------|---------|----------|---------|---------|------------------- +All files | 100 | 100 | 100 | 100 | + Thing.js | 100 | 100 | 100 | 100 | + x.css | 100 | 100 | 100 | 100 | +----------|---------|----------|---------|---------|-------------------" +`; diff --git a/e2e/__tests__/beforeAllFiltered.ts b/e2e/__tests__/beforeAllFiltered.ts index fdd03d373486..7d0a5cf4fbc5 100644 --- a/e2e/__tests__/beforeAllFiltered.ts +++ b/e2e/__tests__/beforeAllFiltered.ts @@ -10,7 +10,11 @@ import runJest from '../runJest'; describe('Correct BeforeAll run', () => { it('ensures the BeforeAll of ignored suite is not run', () => { - const result = runJest('before-all-filtered'); - expect(wrap(result.stdout.replace(/\\/g, '/'))).toMatchSnapshot(); + let {stdout} = runJest('before-all-filtered'); + + // for some reason Circus does not have the `Object` part + stdout = stdout.replace(/at Object.log \(/g, 'at log ('); + + expect(wrap(stdout)).toMatchSnapshot(); }); }); diff --git a/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts b/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts index e49a61328672..3e505c906365 100644 --- a/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts +++ b/e2e/__tests__/consoleLogOutputWhenRunInBand.test.ts @@ -15,6 +15,8 @@ const DIR = path.resolve(__dirname, '../console-log-output-when-run-in-band'); beforeEach(() => cleanup(DIR)); afterAll(() => cleanup(DIR)); +const nodeMajorVersion = Number(process.versions.node.split('.')[0]); + test('prints console.logs when run with forceExit', () => { writeFiles(DIR, { '__tests__/a-banana.js': ` @@ -23,12 +25,26 @@ test('prints console.logs when run with forceExit', () => { 'package.json': '{}', }); - const {stderr, stdout, exitCode} = runJest(DIR, [ + const {stderr, exitCode, ...res} = runJest(DIR, [ '-i', '--ci=false', '--forceExit', ]); + let {stdout} = res; + const {rest, summary} = extractSummary(stderr); + + if (nodeMajorVersion < 12) { + expect(stdout).toContain( + 'at Object..test (__tests__/a-banana.js:1:1)', + ); + + stdout = stdout.replace( + 'at Object..test (__tests__/a-banana.js:1:1)', + 'at Object. (__tests__/a-banana.js:1:1)', + ); + } + expect(exitCode).toBe(0); expect(wrap(rest)).toMatchSnapshot(); expect(wrap(summary)).toMatchSnapshot(); diff --git a/e2e/__tests__/declarationErrors.test.ts b/e2e/__tests__/declarationErrors.test.ts index e0c10bb09a3f..d0d1dda1db16 100644 --- a/e2e/__tests__/declarationErrors.test.ts +++ b/e2e/__tests__/declarationErrors.test.ts @@ -12,7 +12,8 @@ const normalizeCircusJasmine = (str: string) => wrap( str .replace(/console\.log .+:\d+/, 'console.log') - .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/g, ''), + .replace(/.+addSpecsToSuite (.+:\d+:\d+).+\n/g, '') + .replace(/.+_dispatchDescribe (.+:\d+:\d+).+\n/g, ''), ); it('warns if describe returns a Promise', () => { diff --git a/e2e/__tests__/resolveBrowserField.test.ts b/e2e/__tests__/resolveBrowserField.test.ts index f2e9383ed22c..2c37924e2bc5 100644 --- a/e2e/__tests__/resolveBrowserField.test.ts +++ b/e2e/__tests__/resolveBrowserField.test.ts @@ -63,8 +63,10 @@ test('preserves module identity for symlinks when using browser field resolution const {stdout, stderr, exitCode} = runJest(DIR, ['--no-watchman']); expect(stderr).toContain('Test Suites: 1 passed, 1 total'); expect(wrap(stdout.trim())).toMatchInlineSnapshot(` - console.log packages/needs-preserved-id/index.js:1 + console.log needs-preserved-id executed + + at Object. (packages/needs-preserved-id/index.js:1:13) `); expect(exitCode).toEqual(0); }); diff --git a/e2e/__tests__/v8Coverage.test.ts b/e2e/__tests__/v8Coverage.test.ts index 97dfea44252f..902d324aab10 100644 --- a/e2e/__tests__/v8Coverage.test.ts +++ b/e2e/__tests__/v8Coverage.test.ts @@ -14,6 +14,7 @@ const DIR = path.resolve(__dirname, '../v8-coverage'); onNodeVersions('>=10', () => { test('prints coverage', () => { const sourcemapDir = path.join(DIR, 'no-sourcemap'); + const {stdout, exitCode} = runJest( sourcemapDir, ['--coverage', '--coverage-provider', 'v8'], @@ -23,24 +24,6 @@ onNodeVersions('>=10', () => { ); expect(exitCode).toBe(0); - expect( - '\n' + - stdout - .split('\n') - .map(s => s.trimRight()) - .join('\n') + - '\n', - ).toEqual(` - console.log __tests__/Thing.test.js:10 - 42 - -----------|---------|----------|---------|---------|------------------- -File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s -----------|---------|----------|---------|---------|------------------- -All files | 100 | 100 | 100 | 100 | - Thing.js | 100 | 100 | 100 | 100 | - x.css | 100 | 100 | 100 | 100 | -----------|---------|----------|---------|---------|------------------- -`); + expect(stdout).toMatchSnapshot(); }); }); diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index e5501896ebfe..3b7e6f1ce578 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -17,8 +17,9 @@ } }, "dependencies": { - "@jest/source-map": "^25.2.6", + "@jest/types": "^25.3.0", "chalk": "^3.0.0", + "jest-message-util": "^25.3.0", "jest-util": "^25.3.0", "slash": "^3.0.0" }, diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 2ac94ac5c83b..2bf53f350f72 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -9,7 +9,7 @@ import assert = require('assert'); import {Console} from 'console'; import {format} from 'util'; import chalk = require('chalk'); -import {SourceMapRegistry, getCallsite} from '@jest/source-map'; +import {ErrorWithStack} from 'jest-util'; import type { ConsoleBuffer, LogCounters, @@ -23,18 +23,16 @@ export default class BufferedConsole extends Console { private _counters: LogCounters; private _timers: LogTimers; private _groupDepth: number; - private _getSourceMaps: () => SourceMapRegistry | null | undefined; - constructor(getSourceMaps: () => SourceMapRegistry | null | undefined) { + constructor() { const buffer: ConsoleBuffer = []; super({ write: (message: string) => { - BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()); + BufferedConsole.write(buffer, 'log', message, null); return true; }, } as NodeJS.WritableStream); - this._getSourceMaps = getSourceMaps; this._buffer = buffer; this._counters = {}; this._timers = {}; @@ -46,10 +44,17 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level?: number | null, - sourceMaps?: SourceMapRegistry | null, ): ConsoleBuffer { - const callsite = getCallsite(level != null ? level : 2, sourceMaps); - const origin = callsite.getFileName() + ':' + callsite.getLineNumber(); + const stackLevel = level != null ? level : 2; + const rawStack = new ErrorWithStack(undefined, BufferedConsole.write).stack; + + invariant(rawStack, 'always have a stack trace'); + + const origin = rawStack + .split('\n') + .slice(stackLevel) + .filter(Boolean) + .join('\n'); buffer.push({ message, @@ -66,7 +71,6 @@ export default class BufferedConsole extends Console { type, ' '.repeat(this._groupDepth) + message, 3, - this._getSourceMaps(), ); } @@ -163,3 +167,9 @@ export default class BufferedConsole extends Console { return this._buffer.length ? this._buffer : undefined; } } + +function invariant(condition: unknown, message?: string): asserts condition { + if (!condition) { + throw new Error(message); + } +} diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 09a3232b557e..1c3dba19f898 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -5,44 +5,68 @@ * LICENSE file in the root directory of this source tree. */ -import * as path from 'path'; import chalk = require('chalk'); -import slash = require('slash'); +import { + StackTraceConfig, + StackTraceOptions, + formatStackTrace, +} from 'jest-message-util'; import type {ConsoleBuffer} from './types'; export default ( + // TODO: remove in 26 root: string, verbose: boolean, buffer: ConsoleBuffer, + // TODO: make mandatory and take Config.ProjectConfig in 26 + config: StackTraceConfig = { + rootDir: root, + testMatch: [], + }, ): string => { const TITLE_INDENT = verbose ? ' ' : ' '; const CONSOLE_INDENT = TITLE_INDENT + ' '; - return buffer.reduce((output, {type, message, origin}) => { - origin = slash(path.relative(root, origin)); + const logEntries = buffer.reduce((output, {type, message, origin}) => { message = message .split(/\n/) .map(line => CONSOLE_INDENT + line) .join('\n'); let typeMessage = 'console.' + type; + let noStackTrace = true; + let noCodeFrame = true; + if (type === 'warn') { message = chalk.yellow(message); typeMessage = chalk.yellow(typeMessage); + noStackTrace = false; + noCodeFrame = false; } else if (type === 'error') { message = chalk.red(message); typeMessage = chalk.red(typeMessage); + noStackTrace = false; + noCodeFrame = false; } + const options: StackTraceOptions = { + noCodeFrame, + noStackTrace, + }; + + const formattedStackTrace = formatStackTrace(origin, config, options); + return ( output + TITLE_INDENT + chalk.dim(typeMessage) + - ' ' + - chalk.dim(origin) + '\n' + - message + - '\n' + message.trimRight() + + '\n' + + chalk.dim(formattedStackTrace.trimRight()) + + '\n\n' ); }, ''); + + return logEntries.trimRight() + '\n'; }; diff --git a/packages/jest-console/tsconfig.json b/packages/jest-console/tsconfig.json index 719bab0f554b..a436b61458e6 100644 --- a/packages/jest-console/tsconfig.json +++ b/packages/jest-console/tsconfig.json @@ -5,7 +5,8 @@ "outDir": "build" }, "references": [ - {"path": "../jest-source-map"}, + {"path": "../jest-message-util"}, + {"path": "../jest-types"}, {"path": "../jest-util"} ] } diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap index 8fb8249ca9b5..490db062e6fb 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap @@ -7,6 +7,18 @@ exports[`.formatExecError() 1`] = ` " `; +exports[`codeframe 1`] = ` +" ● Test suite failed to run + + Whoops! + + > 1 | throw new Error(\\"Whoops!\\"); + | ^ + + at Object. (file.js:1:7) +" +`; + exports[`formatStackTrace should strip node internals 1`] = ` " Unix test @@ -23,6 +35,22 @@ exports[`formatStackTrace should strip node internals 1`] = ` " `; +exports[`no codeframe 1`] = ` +" ● Test suite failed to run + + Whoops! + + at Object. (file.js:1:7) +" +`; + +exports[`no stack 1`] = ` +" ● Test suite failed to run + + Whoops! +" +`; + exports[`retains message in babel code frame error 1`] = ` " Babel test @@ -30,7 +58,7 @@ exports[`retains message in babel code frame error 1`] = ` packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) 18 | false, - 19 | 'forwardRef requires a render function but received a \`memo\` ' + 19 | 'forwardRef requires a render function but received a \`memo\` ' > 20 | 'component. Instead of forwardRef(memo(...)), use ' + | ^ 21 | 'memo(forwardRef(...)).', diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index 667038690713..41a14d0100da 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -6,8 +6,18 @@ * */ +import {readFileSync} from 'fs'; +import slash = require('slash'); +import tempy = require('tempy'); import {formatExecError, formatResultsErrors} from '..'; +const rootDir = tempy.directory(); + +jest.mock('fs', () => ({ + ...jest.requireActual('fs'), + readFileSync: jest.fn(), +})); + const unixStackTrace = ` ` + `at stack (../jest-jasmine2/build/jasmine-2.4.1.js:1580:17) @@ -61,7 +71,7 @@ const babelStack = ` packages/react/src/forwardRef.js: Unexpected token, expected , (20:10) \u001b[0m \u001b[90m 18 | \u001b[39m \u001b[36mfalse\u001b[39m\u001b[33m,\u001b[39m - \u001b[90m 19 | \u001b[39m \u001b[32m'forwardRef requires a render function but received a \`memo\` '\u001b[39m + \u001b[90m 19 | \u001b[39m \u001b[32m'forwardRef requires a render function but received a \`memo\` '\u001b[39m \u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 20 | \u001b[39m \u001b[32m'component. Instead of forwardRef(memo(...)), use '\u001b[39m \u001b[33m+\u001b[39m \u001b[90m | \u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m \u001b[90m 21 | \u001b[39m \u001b[32m'memo(forwardRef(...)).'\u001b[39m\u001b[33m,\u001b[39m @@ -69,6 +79,10 @@ const babelStack = \u001b[90m 23 | \u001b[39m } \u001b[36melse\u001b[39m \u001b[36mif\u001b[39m (\u001b[36mtypeof\u001b[39m render \u001b[33m!==\u001b[39m \u001b[32m'function'\u001b[39m) {\u001b[0m `; +beforeEach(() => { + jest.clearAllMocks(); +}); + it('should exclude jasmine from stack trace for Unix paths.', () => { const messages = formatResultsErrors( [ @@ -187,3 +201,91 @@ it('retains message in babel code frame error', () => { expect(messages).toMatchSnapshot(); }); + +it('codeframe', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) +`, + }, + { + rootDir, + testMatch: [], + }, + { + noCodeFrame: false, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); + +it('no codeframe', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) +`, + }, + { + rootDir, + testMatch: [], + }, + { + noCodeFrame: true, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); + +it('no stack', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + + const message = formatExecError( + { + message: 'Whoops!', + stack: ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) +`, + }, + { + rootDir, + testMatch: [], + }, + { + // if no stack, no codeframe is implied + noCodeFrame: true, + noStackTrace: true, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); +}); diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index b82b512690fa..b3c1fbb5967b 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -38,6 +38,7 @@ export type StackTraceConfig = Pick< export type StackTraceOptions = { noStackTrace: boolean; + noCodeFrame?: boolean; }; const PATH_NODE_MODULES = `${path.sep}node_modules${path.sep}`; @@ -251,7 +252,7 @@ const formatPaths = ( export const getStackTraceLines = ( stack: string, - options: StackTraceOptions = {noStackTrace: false}, + options: StackTraceOptions = {noCodeFrame: false, noStackTrace: false}, ): Array => removeInternalStackEntries(stack.split(/\n/), options); export const getTopFrame = (lines: Array): Frame | null => { @@ -277,24 +278,27 @@ export const formatStackTrace = ( testPath?: Path, ): string => { const lines = getStackTraceLines(stack, options); - const topFrame = getTopFrame(lines); let renderedCallsite = ''; const relativeTestPath = testPath ? slash(path.relative(config.rootDir, testPath)) : null; - if (topFrame) { - const {column, file: filename, line} = topFrame; - - if (line && filename && path.isAbsolute(filename)) { - let fileContent; - try { - // TODO: check & read HasteFS instead of reading the filesystem: - // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 - fileContent = fs.readFileSync(filename, 'utf8'); - renderedCallsite = getRenderedCallsite(fileContent, line, column); - } catch (e) { - // the file does not exist or is inaccessible, we ignore + if (!options.noCodeFrame) { + const topFrame = getTopFrame(lines); + + if (topFrame) { + const {column, file: filename, line} = topFrame; + + if (line && filename && path.isAbsolute(filename)) { + let fileContent; + try { + // TODO: check & read HasteFS instead of reading the filesystem: + // see: https://github.com/facebook/jest/pull/5405#discussion_r164281696 + fileContent = fs.readFileSync(filename, 'utf8'); + renderedCallsite = getRenderedCallsite(fileContent, line, column); + } catch (e) { + // the file does not exist or is inaccessible, we ignore + } } } } @@ -307,7 +311,9 @@ export const formatStackTrace = ( ) .join('\n'); - return `${renderedCallsite}\n${stacktrace}`; + return renderedCallsite + ? `${renderedCallsite}\n${stacktrace}` + : `\n${stacktrace}`; }; type FailedResults = Array<{ diff --git a/packages/jest-reporters/src/default_reporter.ts b/packages/jest-reporters/src/default_reporter.ts index ae90384cd2b8..9053fbf20eac 100644 --- a/packages/jest-reporters/src/default_reporter.ts +++ b/packages/jest-reporters/src/default_reporter.ts @@ -182,6 +182,7 @@ export default class DefaultReporter extends BaseReporter { config.cwd, !!this._globalConfig.verbose, result.console, + config, ), ); } diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index a617bc9d510c..87b9e809720c 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -114,21 +114,14 @@ async function runTestInternal( ? require(config.moduleLoader) : require('jest-runtime'); - let runtime: RuntimeClass | undefined = undefined; - const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; const consoleFormatter = (type: LogType, message: LogMessage) => getConsoleOutput( config.cwd, !!globalConfig.verbose, // 4 = the console call is buried 4 stack frames deep - BufferedConsole.write( - [], - type, - message, - 4, - runtime && runtime.getSourceMaps(), - ), + BufferedConsole.write([], type, message, 4), + config, ); let testConsole; @@ -138,7 +131,7 @@ async function runTestInternal( } else if (globalConfig.verbose) { testConsole = new CustomConsole(consoleOut, consoleOut, consoleFormatter); } else { - testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps()); + testConsole = new BufferedConsole(); } const environment = new TestEnvironment(config, { @@ -153,7 +146,7 @@ async function runTestInternal( const cacheFS = {[path]: testSource}; setGlobal(environment.global, 'console', testConsole); - runtime = new Runtime(config, environment, resolver, cacheFS, { + const runtime = new Runtime(config, environment, resolver, cacheFS, { changedFiles: context && context.changedFiles, collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, @@ -163,13 +156,13 @@ async function runTestInternal( const start = Date.now(); - config.setupFiles.forEach(path => runtime!.requireModule(path)); + config.setupFiles.forEach(path => runtime.requireModule(path)); const sourcemapOptions: sourcemapSupport.Options = { environment: 'node', handleUncaughtExceptions: false, retrieveSourceMap: source => { - const sourceMaps = runtime && runtime.getSourceMaps(); + const sourceMaps = runtime.getSourceMaps(); const sourceMapSource = sourceMaps && sourceMaps[source]; if (sourceMapSource) { From 99c6fb1e5d5db037ab42ea12ddc6cb9ed16e3785 Mon Sep 17 00:00:00 2001 From: Joel Einbinder Date: Mon, 13 Apr 2020 02:29:42 -0700 Subject: [PATCH 02/39] chore: type TestScheduler's testRunners object (#9804) --- packages/jest-core/src/TestScheduler.ts | 2 +- packages/jest-runner/src/index.ts | 1 + packages/jest-runner/src/types.ts | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 3211459f2148..41b40e18955f 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -175,7 +175,7 @@ export default class TestScheduler { showStatus: !runInBand, }); - const testRunners = Object.create(null); + const testRunners: {[key: string]: TestRunner} = Object.create(null); contexts.forEach(({config}) => { if (!testRunners[config.runner]) { const Runner: typeof TestRunner = require(config.runner); diff --git a/packages/jest-runner/src/index.ts b/packages/jest-runner/src/index.ts index 9969492ad738..518c07ad8f03 100644 --- a/packages/jest-runner/src/index.ts +++ b/packages/jest-runner/src/index.ts @@ -44,6 +44,7 @@ namespace TestRunner { class TestRunner { private _globalConfig: Config.GlobalConfig; private _context: JestTestRunnerContext; + readonly isSerial?: boolean; constructor( globalConfig: Config.GlobalConfig, diff --git a/packages/jest-runner/src/types.ts b/packages/jest-runner/src/types.ts index 08525df5e514..c45b44d32677 100644 --- a/packages/jest-runner/src/types.ts +++ b/packages/jest-runner/src/types.ts @@ -63,7 +63,6 @@ export type WatcherState = { }; export interface TestWatcher extends EventEmitter { state: WatcherState; - new ({isWatchMode}: {isWatchMode: boolean}): TestWatcher; setState(state: WatcherState): void; isInterrupted(): boolean; isWatchMode(): boolean; From c37abc24f7dc8815615ce668453d812c4a681b45 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Wed, 15 Apr 2020 23:14:53 +0200 Subject: [PATCH 03/39] =?UTF-8?q?fix(jest-each)=20Throws=20an=20error=20wh?= =?UTF-8?q?en=20too=20much=20arguments=20are=20pass=E2=80=A6=20(#9818)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../src/__tests__/__snapshots__/index.test.ts.snap | 3 +++ packages/jest-each/src/__tests__/index.test.ts | 14 ++++++++++++++ packages/jest-each/src/index.ts | 7 +++++++ 4 files changed, 25 insertions(+) create mode 100644 packages/jest-each/src/__tests__/__snapshots__/index.test.ts.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index dbed475bddec..3e31f6b2703b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - `[expect]` Restore support for passing functions to `toHaveLength` matcher ([#9796](https://github.com/facebook/jest/pull/9796)) - `[jest-changed-files]` `--only-changed` should include staged files ([#9799](https://github.com/facebook/jest/pull/9799)) +- `[jest-each]` `each` will throw an error when called with too many arguments ([#9818](https://github.com/facebook/jest/pull/9818)) ### Chore & Maintenance diff --git a/packages/jest-each/src/__tests__/__snapshots__/index.test.ts.snap b/packages/jest-each/src/__tests__/__snapshots__/index.test.ts.snap new file mode 100644 index 000000000000..af1a9318ba07 --- /dev/null +++ b/packages/jest-each/src/__tests__/__snapshots__/index.test.ts.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`throws an error when not called with the right number of arguments 1`] = `"\`.each\` must only be called with an Array or Tagged Template Literal."`; diff --git a/packages/jest-each/src/__tests__/index.test.ts b/packages/jest-each/src/__tests__/index.test.ts index 06b23edd9afc..40ba0c391700 100644 --- a/packages/jest-each/src/__tests__/index.test.ts +++ b/packages/jest-each/src/__tests__/index.test.ts @@ -32,3 +32,17 @@ describe('template', () => { }); }); }); + +test('throws an error when not called with the right number of arguments', () => { + expect(() => + each( + [ + [1, 1, 2], + [1, 2, 3], + [2, 1, 3], + ], + 'seems like a title but should not be here', + () => {}, + ), + ).toThrowErrorMatchingSnapshot(); +}); diff --git a/packages/jest-each/src/index.ts b/packages/jest-each/src/index.ts index 85a213b0cf47..9836bd2136cb 100644 --- a/packages/jest-each/src/index.ts +++ b/packages/jest-each/src/index.ts @@ -15,6 +15,13 @@ const install = ( table: Global.EachTable, ...data: Global.TemplateData ) => { + const bindingWithArray = data.length === 0; + const bindingWithTemplate = Array.isArray(table) && !!(table as any).raw; + if (!bindingWithArray && !bindingWithTemplate) { + throw new Error( + '`.each` must only be called with an Array or Tagged Template Literal.', + ); + } const test = (title: string, test: Global.EachTestFn, timeout?: number) => bind(g.test)(table, ...data)(title, test, timeout); test.skip = bind(g.test.skip)(table, ...data); From da637893ca4bb2f9942249f7f66034afabe6b6dd Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 16 Apr 2020 13:02:00 +0200 Subject: [PATCH 04/39] chore: remove declaration maps (#9822) --- CHANGELOG.md | 2 ++ tsconfig.json | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e31f6b2703b..e927e97d6a87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ ### Chore & Maintenance +- `[*]` Do not generate TypeScript declaration source maps ([#9822](https://github.com/facebook/jest/pull/9822)) + ### Performance ## 25.3.0 diff --git a/tsconfig.json b/tsconfig.json index 15f14f7381e7..2301b5e98b8b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,6 @@ "module": "commonjs", "lib": ["dom", "es2017"], "declaration": true, - "declarationMap": true, "composite": true, "emitDeclarationOnly": true, // blocked by https://github.com/chalk/chalk/pull/390 From 4010fddbd4ba18e60f25a2e466828e0e4f3bc726 Mon Sep 17 00:00:00 2001 From: Ahn Date: Thu, 16 Apr 2020 14:42:16 +0200 Subject: [PATCH 05/39] docs: update README for jest-worker (#9788) * docs: update README for jest-worker * docs: update CHANGELOG and documentation for JestPlatform --- docs/JestPlatform.md | 2 +- packages/jest-worker/README.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/JestPlatform.md b/docs/JestPlatform.md index 31f89f6eb6f2..47b7140a732e 100644 --- a/docs/JestPlatform.md +++ b/docs/JestPlatform.md @@ -119,7 +119,7 @@ You can read more about `jest-validate` in the [readme file](https://github.com/ ## jest-worker -Module used for parallelization of tasks. Exports a class `Worker` that takes the path of Node.js module and lets you call the module's exported methods as if they were class methods, returning a promise that resolves when the specified method finishes its execution in a forked process. +Module used for parallelization of tasks. Exports a class `JestWorker` that takes the path of Node.js module and lets you call the module's exported methods as if they were class methods, returning a promise that resolves when the specified method finishes its execution in a forked process. ### Example diff --git a/packages/jest-worker/README.md b/packages/jest-worker/README.md index 6efbc0587387..efc91bb9a7cb 100644 --- a/packages/jest-worker/README.md +++ b/packages/jest-worker/README.md @@ -21,10 +21,10 @@ This example covers the minimal usage: ### File `parent.js` ```javascript -import Worker from 'jest-worker'; +import JestWorker from 'jest-worker'; async function main() { - const worker = new Worker(require.resolve('./Worker')); + const worker = new JestWorker(require.resolve('./Worker')); const result = await worker.hello('Alice'); // "Hello, Alice" } @@ -47,7 +47,7 @@ Since `worker_threads` are considered experimental in Node, you have to opt-in t ## API -The only exposed method is a constructor (`Worker`) that is initialized by passing the worker path, plus an options object. +The only exposed method is a constructor (`JestWorker`) that is initialized by passing the worker path, plus an options object. ### `workerPath: string` (required) @@ -93,11 +93,11 @@ The arguments that will be passed to the `setup` method during initialization. `jest-worker` will automatically detect if `worker_threads` are available, but will not use them unless passed `enableWorkerThreads: true`. -## Worker +## JestWorker ### Methods -The returned `Worker` instance has all the exposed methods, plus some additional ones to interact with the workers itself: +The returned `JestWorker` instance has all the exposed methods, plus some additional ones to interact with the workers itself: #### `getStdout(): Readable` @@ -139,10 +139,10 @@ This example covers the standard usage: ### File `parent.js` ```javascript -import Worker from 'jest-worker'; +import JestWorker from 'jest-worker'; async function main() { - const myWorker = new Worker(require.resolve('./Worker'), { + const myWorker = new JestWorker(require.resolve('./Worker'), { exposedMethods: ['foo', 'bar', 'getWorkerId'], numWorkers: 4, }); @@ -183,10 +183,10 @@ This example covers the usage with a `computeWorkerKey` method: ### File `parent.js` ```javascript -import Worker from 'jest-worker'; +import JestWorker from 'jest-worker'; async function main() { - const myWorker = new Worker(require.resolve('./Worker'), { + const myWorker = new JestWorker(require.resolve('./Worker'), { computeWorkerKey: (method, filename) => filename, }); From fcfe7cdcfe288b263e7a6e74e490c8753c744fad Mon Sep 17 00:00:00 2001 From: Seong Min Park <32555977+notoriousmango@users.noreply.github.com> Date: Thu, 16 Apr 2020 23:26:47 +0900 Subject: [PATCH 06/39] feat: support `async function`s in `toThrow` (#9817) --- CHANGELOG.md | 1 + .../__snapshots__/matchers.test.js.snap | 16 ++++++++-------- packages/expect/src/__tests__/matchers.test.js | 6 ++++++ packages/expect/src/index.ts | 13 +++++++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e927e97d6a87..fb598b891946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) diff --git a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap index e442e66efcaf..652e3020ab90 100644 --- a/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/matchers.test.js.snap @@ -10,7 +10,7 @@ Resolved to value: 4 exports[`.rejects fails non-promise value "a" 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: string Received has value: "a" @@ -19,7 +19,7 @@ Received has value: "a" exports[`.rejects fails non-promise value [1] 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: array Received has value: [1] @@ -28,7 +28,7 @@ Received has value: [1] exports[`.rejects fails non-promise value [Function anonymous] 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: function Received has value: [Function anonymous] @@ -37,7 +37,7 @@ Received has value: [Function anonymous] exports[`.rejects fails non-promise value {"a": 1} 1`] = ` expect(received).rejects.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: object Received has value: {"a": 1} @@ -46,7 +46,7 @@ Received has value: {"a": 1} exports[`.rejects fails non-promise value 4 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: number Received has value: 4 @@ -55,7 +55,7 @@ Received has value: 4 exports[`.rejects fails non-promise value null 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has value: null `; @@ -63,7 +63,7 @@ Received has value: null exports[`.rejects fails non-promise value true 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has type: boolean Received has value: true @@ -72,7 +72,7 @@ Received has value: true exports[`.rejects fails non-promise value undefined 1`] = ` expect(received).rejects.not.toBeDefined() -Matcher error: received value must be a promise +Matcher error: received value must be a promise or a function returning a promise Received has value: undefined `; diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index 89f25a561ea8..4223f4e53475 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -56,6 +56,12 @@ describe('.rejects', () => { await jestExpect(fn()).rejects.toThrow('some error'); }); + it('should reject async function to toThrow', async () => { + await expect(async () => { + throw new Error('Test'); + }).rejects.toThrow('Test'); + }); + ['a', [1], () => {}, {a: 1}].forEach(value => { it(`fails non-promise value ${stringify(value)} synchronously`, () => { let error; diff --git a/packages/expect/src/index.ts b/packages/expect/src/index.ts index 80adf7d3c686..c715cd97354d 100644 --- a/packages/expect/src/index.ts +++ b/packages/expect/src/index.ts @@ -189,7 +189,7 @@ const makeRejectMatcher = ( matcherName: string, matcher: RawMatcherFn, isNot: boolean, - actual: Promise, + actual: Promise | (() => Promise), outerErr: JestAssertionError, ): PromiseMatcherFn => (...args) => { const options = { @@ -197,11 +197,16 @@ const makeRejectMatcher = ( promise: 'rejects', }; - if (!isPromise(actual)) { + const actualWrapper: Promise = + typeof actual === 'function' ? actual() : actual; + + if (!isPromise(actualWrapper)) { throw new JestAssertionError( matcherUtils.matcherErrorMessage( matcherUtils.matcherHint(matcherName, undefined, '', options), - `${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`, + `${matcherUtils.RECEIVED_COLOR( + 'received', + )} value must be a promise or a function returning a promise`, matcherUtils.printWithType( 'Received', actual, @@ -213,7 +218,7 @@ const makeRejectMatcher = ( const innerErr = new JestAssertionError(); - return actual.then( + return actualWrapper.then( result => { outerErr.message = matcherUtils.matcherHint(matcherName, undefined, '', options) + From cab4c1d68be2f6cdf692dbafc4a479ffd5b015b9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 16 Apr 2020 16:57:46 +0200 Subject: [PATCH 07/39] chore: target node 8.3, not 8.0 (#9827) --- CHANGELOG.md | 1 + babel.config.js | 4 ++-- e2e/__tests__/__snapshots__/transform.test.ts.snap | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb598b891946..16f7ee45a768 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ### Chore & Maintenance - `[*]` Do not generate TypeScript declaration source maps ([#9822](https://github.com/facebook/jest/pull/9822)) +- `[*]` Transpile code for Node 8.3, not 8.0 ([#9827](https://github.com/facebook/jest/pull/9827)) ### Performance diff --git a/babel.config.js b/babel.config.js index 343d46ea18ae..f062b0d8739f 100644 --- a/babel.config.js +++ b/babel.config.js @@ -31,7 +31,7 @@ module.exports = { { exclude: ['@babel/plugin-proposal-dynamic-import'], shippedProposals: true, - targets: {node: 8}, + targets: {node: '8.3'}, }, ], ], @@ -48,7 +48,7 @@ module.exports = { '@babel/preset-env', { shippedProposals: true, - targets: {node: 8}, + targets: {node: '8.3'}, }, ], ], diff --git a/e2e/__tests__/__snapshots__/transform.test.ts.snap b/e2e/__tests__/__snapshots__/transform.test.ts.snap index 142251e90fc7..5ccf71e5a934 100644 --- a/e2e/__tests__/__snapshots__/transform.test.ts.snap +++ b/e2e/__tests__/__snapshots__/transform.test.ts.snap @@ -6,7 +6,7 @@ FAIL __tests__/ignoredFile.test.js babel-jest: Babel ignores __tests__/ignoredFile.test.js - make sure to include the file in Jest's transformIgnorePatterns as well. - at loadBabelConfig (../../../packages/babel-jest/build/index.js:227:13) + at loadBabelConfig (../../../packages/babel-jest/build/index.js:178:13) `; exports[`babel-jest instruments only specific files and collects coverage 1`] = ` From 2a92e7f49fa35b219e5099d56b0179bccc1bf53e Mon Sep 17 00:00:00 2001 From: Josef Brandl Date: Thu, 16 Apr 2020 21:50:38 +0200 Subject: [PATCH 08/39] Use optional chaining in toHaveLength matcher (#9826) --- packages/expect/src/matchers.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/expect/src/matchers.ts b/packages/expect/src/matchers.ts index cd7274425fb0..de234b24b0b3 100644 --- a/packages/expect/src/matchers.ts +++ b/packages/expect/src/matchers.ts @@ -628,10 +628,7 @@ const matchers: MatchersObject = { promise: this.promise, }; - if ( - typeof received !== 'string' && - (!received || typeof received.length !== 'number') - ) { + if (typeof received?.length !== 'number') { throw new Error( matcherErrorMessage( matcherHint(matcherName, undefined, undefined, options), From aa64672e728738926571746a85c57d1658bdaf55 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 16 Apr 2020 21:59:03 +0200 Subject: [PATCH 09/39] feat: experimental ES Modules support (#9772) --- CHANGELOG.md | 1 + .../moduleNameMapper.test.ts.snap | 4 +- .../__snapshots__/nativeEsm.test.ts.snap | 9 + .../resolveNoFileExtensions.test.ts.snap | 2 +- e2e/__tests__/nativeEsm.test.ts | 36 ++++ e2e/native-esm/__tests__/native-esm.test.js | 46 +++++ e2e/native-esm/index.js | 10 ++ e2e/native-esm/package.json | 7 + .../legacy-code-todo-rewrite/jestAdapter.ts | 19 +- packages/jest-jasmine2/src/index.ts | 19 +- packages/jest-resolve/package.json | 1 + packages/jest-resolve/src/index.ts | 5 + packages/jest-resolve/src/shouldLoadAsEsm.ts | 78 ++++++++ packages/jest-runner/src/runTest.ts | 10 +- .../src/__mocks__/createRuntime.js | 10 +- packages/jest-runtime/src/cli/index.ts | 17 +- packages/jest-runtime/src/index.ts | 170 +++++++++++++++--- yarn.lock | 44 +++++ 18 files changed, 457 insertions(+), 31 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap create mode 100644 e2e/__tests__/nativeEsm.test.ts create mode 100644 e2e/native-esm/__tests__/native-esm.test.js create mode 100644 e2e/native-esm/index.js create mode 100644 e2e/native-esm/package.json create mode 100644 packages/jest-resolve/src/shouldLoadAsEsm.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f7ee45a768..0f9727101221 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) +- `[jest-runtime, jest-jasmine2, jest-circus]` Experimental, limited ECMAScript Modules support ([#9772](https://github.com/facebook/jest/pull/9772)) ### Fixes diff --git a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap index d43ffe5dce4f..ed248a26f289 100644 --- a/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap +++ b/e2e/__tests__/__snapshots__/moduleNameMapper.test.ts.snap @@ -36,7 +36,7 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:540:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:545:17) at Object.require (index.js:10:1) `; @@ -65,6 +65,6 @@ FAIL __tests__/index.js 12 | module.exports = () => 'test'; 13 | - at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:540:17) + at createNoMappedModuleFoundError (../../packages/jest-resolve/build/index.js:545:17) at Object.require (index.js:10:1) `; diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap new file mode 100644 index 000000000000..1ec158742c61 --- /dev/null +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`on node >=12.16.0 runs test with native ESM 1`] = ` +Test Suites: 1 passed, 1 total +Tests: 4 passed, 4 total +Snapshots: 0 total +Time: <> +Ran all test suites. +`; diff --git a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap index a62a66e69f80..062640b2406a 100644 --- a/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap +++ b/e2e/__tests__/__snapshots__/resolveNoFileExtensions.test.ts.snap @@ -37,6 +37,6 @@ FAIL __tests__/test.js | ^ 9 | - at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:296:11) + at Resolver.resolveModule (../../packages/jest-resolve/build/index.js:299:11) at Object.require (index.js:8:18) `; diff --git a/e2e/__tests__/nativeEsm.test.ts b/e2e/__tests__/nativeEsm.test.ts new file mode 100644 index 000000000000..405547a39743 --- /dev/null +++ b/e2e/__tests__/nativeEsm.test.ts @@ -0,0 +1,36 @@ +/** + * 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 {resolve} from 'path'; +import wrap from 'jest-snapshot-serializer-raw'; +import {onNodeVersions} from '@jest/test-utils'; +import runJest, {getConfig} from '../runJest'; +import {extractSummary} from '../Utils'; + +const DIR = resolve(__dirname, '../native-esm'); + +test('test config is without transform', () => { + const {configs} = getConfig(DIR); + + expect(configs).toHaveLength(1); + expect(configs[0].transform).toEqual([]); +}); + +// The versions vm.Module was introduced +onNodeVersions('>=12.16.0', () => { + test('runs test with native ESM', () => { + const {exitCode, stderr, stdout} = runJest(DIR, [], { + nodeOptions: '--experimental-vm-modules', + }); + + const {summary} = extractSummary(stderr); + + expect(wrap(summary)).toMatchSnapshot(); + expect(stdout).toBe(''); + expect(exitCode).toBe(0); + }); +}); diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js new file mode 100644 index 000000000000..3b8508cd77cf --- /dev/null +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -0,0 +1,46 @@ +/** + * 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 {readFileSync} from 'fs'; +import {dirname, resolve} from 'path'; +import {fileURLToPath} from 'url'; +import {double} from '../index'; + +test('should have correct import.meta', () => { + expect(typeof require).toBe('undefined'); + expect(typeof jest).toBe('undefined'); + expect(import.meta).toEqual({ + url: expect.any(String), + }); + expect( + import.meta.url.endsWith('/e2e/native-esm/__tests__/native-esm.test.js') + ).toBe(true); +}); + +test('should double stuff', () => { + expect(double(1)).toBe(2); +}); + +test('should support importing node core modules', () => { + const dir = dirname(fileURLToPath(import.meta.url)); + const packageJsonPath = resolve(dir, '../package.json'); + + expect(JSON.parse(readFileSync(packageJsonPath, 'utf8'))).toEqual({ + jest: { + testEnvironment: 'node', + transform: {}, + }, + type: 'module', + }); +}); + +test('dynamic import should work', async () => { + const {double: importedDouble} = await import('../index'); + + expect(importedDouble).toBe(double); + expect(importedDouble(1)).toBe(2); +}); diff --git a/e2e/native-esm/index.js b/e2e/native-esm/index.js new file mode 100644 index 000000000000..19bd49f5543e --- /dev/null +++ b/e2e/native-esm/index.js @@ -0,0 +1,10 @@ +/** + * 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. + */ + +export function double(num) { + return num * 2; +} diff --git a/e2e/native-esm/package.json b/e2e/native-esm/package.json new file mode 100644 index 000000000000..5a90624bc1fe --- /dev/null +++ b/e2e/native-esm/package.json @@ -0,0 +1,7 @@ +{ + "type": "module", + "jest": { + "testEnvironment": "node", + "transform": {} + } +} diff --git a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts index 026ba3f54c7c..a7fdf68cb0d9 100644 --- a/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts +++ b/packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts @@ -76,9 +76,24 @@ const jestAdapter = async ( } }); - config.setupFilesAfterEnv.forEach(path => runtime.requireModule(path)); + for (const path of config.setupFilesAfterEnv) { + const esm = runtime.unstable_shouldLoadAsEsm(path); + + if (esm) { + await runtime.unstable_importModule(path); + } else { + runtime.requireModule(path); + } + } + + const esm = runtime.unstable_shouldLoadAsEsm(testPath); + + if (esm) { + await runtime.unstable_importModule(testPath); + } else { + runtime.requireModule(testPath); + } - runtime.requireModule(testPath); const results = await runAndTransformResultsToJestFormat({ config, globalConfig, diff --git a/packages/jest-jasmine2/src/index.ts b/packages/jest-jasmine2/src/index.ts index f8ab81713895..03d2eebdc851 100644 --- a/packages/jest-jasmine2/src/index.ts +++ b/packages/jest-jasmine2/src/index.ts @@ -155,7 +155,15 @@ async function jasmine2( testPath, }); - config.setupFilesAfterEnv.forEach(path => runtime.requireModule(path)); + for (const path of config.setupFilesAfterEnv) { + const esm = runtime.unstable_shouldLoadAsEsm(path); + + if (esm) { + await runtime.unstable_importModule(path); + } else { + runtime.requireModule(path); + } + } if (globalConfig.enabledTestsMap) { env.specFilter = (spec: Spec) => { @@ -169,7 +177,14 @@ async function jasmine2( env.specFilter = (spec: Spec) => testNameRegex.test(spec.getFullName()); } - runtime.requireModule(testPath); + const esm = runtime.unstable_shouldLoadAsEsm(testPath); + + if (esm) { + await runtime.unstable_importModule(testPath); + } else { + runtime.requireModule(testPath); + } + await env.execute(); const results = await reporter.getResults(); diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index fe0e8e5de75e..e4056c273d91 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -21,6 +21,7 @@ "browser-resolve": "^1.11.3", "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", + "read-pkg-up": "^7.0.1", "realpath-native": "^2.0.0", "resolve": "^1.15.1", "slash": "^3.0.0" diff --git a/packages/jest-resolve/src/index.ts b/packages/jest-resolve/src/index.ts index 15856fb5aeb2..5cdbbd8a3ef3 100644 --- a/packages/jest-resolve/src/index.ts +++ b/packages/jest-resolve/src/index.ts @@ -15,6 +15,7 @@ import isBuiltinModule from './isBuiltinModule'; import defaultResolver, {clearDefaultResolverCache} from './defaultResolver'; import type {ResolverConfig} from './types'; import ModuleNotFoundError from './ModuleNotFoundError'; +import shouldLoadAsEsm, {clearCachedLookups} from './shouldLoadAsEsm'; type FindNodeModuleConfig = { basedir: Config.Path; @@ -100,6 +101,7 @@ class Resolver { static clearDefaultResolverCache(): void { clearDefaultResolverCache(); + clearCachedLookups(); } static findNodeModule( @@ -129,6 +131,9 @@ class Resolver { return null; } + // unstable as it should be replaced by https://github.com/nodejs/modules/issues/393, and we don't want people to use it + static unstable_shouldLoadAsEsm = shouldLoadAsEsm; + resolveModuleFromDirIfExists( dirname: Config.Path, moduleName: string, diff --git a/packages/jest-resolve/src/shouldLoadAsEsm.ts b/packages/jest-resolve/src/shouldLoadAsEsm.ts new file mode 100644 index 000000000000..ca49e3fdda75 --- /dev/null +++ b/packages/jest-resolve/src/shouldLoadAsEsm.ts @@ -0,0 +1,78 @@ +/** + * 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 {dirname, extname} from 'path'; +// @ts-ignore: experimental, not added to the types +import {SourceTextModule} from 'vm'; +import type {Config} from '@jest/types'; +import readPkgUp = require('read-pkg-up'); + +const runtimeSupportsVmModules = typeof SourceTextModule === 'function'; + +const cachedFileLookups = new Map(); +const cachedDirLookups = new Map(); + +export function clearCachedLookups(): void { + cachedFileLookups.clear(); + cachedDirLookups.clear(); +} + +export default function cachedShouldLoadAsEsm(path: Config.Path): boolean { + let cachedLookup = cachedFileLookups.get(path); + + if (cachedLookup === undefined) { + cachedLookup = shouldLoadAsEsm(path); + cachedFileLookups.set(path, cachedLookup); + } + + return cachedLookup; +} + +// this is a bad version of what https://github.com/nodejs/modules/issues/393 would provide +function shouldLoadAsEsm(path: Config.Path): boolean { + if (!runtimeSupportsVmModules) { + return false; + } + + const extension = extname(path); + + if (extension === '.mjs') { + return true; + } + + if (extension === '.cjs') { + return false; + } + + // this isn't correct - we might wanna load any file as a module (using synthetic module) + // do we need an option to Jest so people can opt in to ESM for non-js? + if (extension !== '.js') { + return false; + } + + const cwd = dirname(path); + + let cachedLookup = cachedDirLookups.get(cwd); + + if (cachedLookup === undefined) { + cachedLookup = cachedPkgCheck(cwd); + cachedFileLookups.set(cwd, cachedLookup); + } + + return cachedLookup; +} + +function cachedPkgCheck(cwd: Config.Path): boolean { + // TODO: can we cache lookups somehow? + const pkg = readPkgUp.sync({cwd, normalize: false}); + + if (!pkg) { + return false; + } + + return pkg.packageJson.type === 'module'; +} diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 87b9e809720c..36754d3f086e 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -156,7 +156,15 @@ async function runTestInternal( const start = Date.now(); - config.setupFiles.forEach(path => runtime.requireModule(path)); + for (const path of config.setupFiles) { + const esm = runtime.unstable_shouldLoadAsEsm(path); + + if (esm) { + await runtime.unstable_importModule(path); + } else { + runtime.requireModule(path); + } + } const sourcemapOptions: sourcemapSupport.Options = { environment: 'node', diff --git a/packages/jest-runtime/src/__mocks__/createRuntime.js b/packages/jest-runtime/src/__mocks__/createRuntime.js index 1efc081eabfa..1512da0cb3eb 100644 --- a/packages/jest-runtime/src/__mocks__/createRuntime.js +++ b/packages/jest-runtime/src/__mocks__/createRuntime.js @@ -49,7 +49,15 @@ module.exports = async function createRuntime(filename, config) { Runtime.createResolver(config, hasteMap.moduleMap), ); - config.setupFiles.forEach(path => runtime.requireModule(path)); + for (const path of config.setupFiles) { + const esm = runtime.unstable_shouldLoadAsEsm(path); + + if (esm) { + await runtime.unstable_importModule(path); + } else { + runtime.requireModule(path); + } + } runtime.__mockRootPath = path.join(config.rootDir, 'root.js'); runtime.__mockSubdirPath = path.join( diff --git a/packages/jest-runtime/src/cli/index.ts b/packages/jest-runtime/src/cli/index.ts index e7c8e1dd3750..54857611e5c2 100644 --- a/packages/jest-runtime/src/cli/index.ts +++ b/packages/jest-runtime/src/cli/index.ts @@ -93,9 +93,22 @@ export async function run( const runtime = new Runtime(config, environment, hasteMap.resolver); - config.setupFiles.forEach(path => runtime.requireModule(path)); + for (const path of config.setupFiles) { + const esm = runtime.unstable_shouldLoadAsEsm(path); - runtime.requireModule(filePath); + if (esm) { + await runtime.unstable_importModule(path); + } else { + runtime.requireModule(path); + } + } + const esm = runtime.unstable_shouldLoadAsEsm(filePath); + + if (esm) { + await runtime.unstable_importModule(filePath); + } else { + runtime.requireModule(filePath); + } } catch (e) { console.error(chalk.red(e.stack || e)); process.on('exit', () => (process.exitCode = 1)); diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index d80cfd780b8e..1a5cff8361a7 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -5,9 +5,19 @@ * LICENSE file in the root directory of this source tree. */ -import {URL, fileURLToPath} from 'url'; +import {URL, fileURLToPath, pathToFileURL} from 'url'; import * as path from 'path'; -import {Script, compileFunction} from 'vm'; +import { + Script, + // @ts-ignore: experimental, not added to the types + SourceTextModule, + // @ts-ignore: experimental, not added to the types + SyntheticModule, + Context as VMContext, + // @ts-ignore: experimental, not added to the types + Module as VMModule, + compileFunction, +} from 'vm'; import * as nativeModule from 'module'; import type {Config, Global} from '@jest/types'; import type { @@ -106,6 +116,8 @@ const EVAL_RESULT_VARIABLE = 'Object.'; type RunScriptEvalResult = {[EVAL_RESULT_VARIABLE]: ModuleWrapper}; +const runtimeSupportsVmModules = typeof SourceTextModule === 'function'; + /* eslint-disable-next-line no-redeclare */ class Runtime { private _cacheFS: CacheFS; @@ -125,6 +137,7 @@ class Runtime { private _moduleMocker: typeof jestMock; private _isolatedModuleRegistry: ModuleRegistry | null; private _moduleRegistry: ModuleRegistry; + private _esmoduleRegistry: Map; private _needsCoverageMapped: Set; private _resolver: Resolver; private _shouldAutoMock: boolean; @@ -169,6 +182,7 @@ class Runtime { this._isolatedModuleRegistry = null; this._isolatedMockRegistry = null; this._moduleRegistry = new Map(); + this._esmoduleRegistry = new Map(); this._needsCoverageMapped = new Set(); this._resolver = resolver; this._scriptTransformer = new ScriptTransformer(config); @@ -302,6 +316,89 @@ class Runtime { return cliOptions; } + // unstable as it should be replaced by https://github.com/nodejs/modules/issues/393, and we don't want people to use it + unstable_shouldLoadAsEsm = Resolver.unstable_shouldLoadAsEsm; + + private async loadEsmModule( + modulePath: Config.Path, + query = '', + ): Promise { + if (modulePath === '@jest/globals') { + // TODO: create a Synthetic Module for this. Will need to create a `jest` object without a `LocalModuleRequire` + throw new Error( + 'Importing `@jest/globals` is not supported from ESM yet', + ); + } + + const cacheKey = modulePath + query; + + if (!this._esmoduleRegistry.has(cacheKey)) { + invariant( + typeof this._environment.getVmContext === 'function', + 'ES Modules are only supported if your test environment has the `getVmContext` function', + ); + + const context = this._environment.getVmContext(); + + invariant(context); + + if (this._resolver.isCoreModule(modulePath)) { + const core = await this._importCoreModule(modulePath, context); + this._esmoduleRegistry.set(cacheKey, core); + return core; + } + + const transformedFile = this.transformFile(modulePath, { + isInternalModule: false, + supportsDynamicImport: true, + supportsStaticESM: true, + }); + + const module = new SourceTextModule(transformedFile.code, { + context, + identifier: modulePath, + importModuleDynamically: ( + specifier: string, + referencingModule: VMModule, + ) => + this.loadEsmModule( + this._resolveModule(referencingModule.identifier, specifier), + ), + initializeImportMeta(meta: ImportMeta) { + meta.url = pathToFileURL(modulePath).href; + }, + }); + + this._esmoduleRegistry.set(cacheKey, module); + } + + const module = this._esmoduleRegistry.get(cacheKey); + + invariant(module); + + return module; + } + + async unstable_importModule( + from: Config.Path, + moduleName?: string, + ): Promise { + invariant( + runtimeSupportsVmModules, + 'You need to run with a version of node that supports ES Modules in the VM API.', + ); + + const modulePath = this._resolveModule(from, moduleName); + + const module = await this.loadEsmModule(modulePath); + await module.link((specifier: string, referencingModule: VMModule) => + this.loadEsmModule( + this._resolveModule(referencingModule.identifier, specifier), + ), + ); + await module.evaluate(); + } + requireModule( from: Config.Path, moduleName?: string, @@ -577,6 +674,7 @@ class Runtime { this._isolatedMockRegistry = null; this._mockRegistry.clear(); this._moduleRegistry.clear(); + this._esmoduleRegistry.clear(); if (this._environment) { if (this._environment.global) { @@ -795,23 +893,8 @@ class Runtime { Object.defineProperty(localModule, 'require', { value: this._createRequireImplementation(localModule, options), }); - const transformedFile = this._scriptTransformer.transform( - filename, - this._getFullTransformationOptions(options), - this._cacheFS[filename], - ); - // we only care about non-internal modules - if (!options || !options.isInternalModule) { - this._fileTransforms.set(filename, transformedFile); - } - - if (transformedFile.sourceMapPath) { - this._sourceMapRegistry[filename] = transformedFile.sourceMapPath; - if (transformedFile.mapCoverage) { - this._needsCoverageMapped.add(filename); - } - } + const transformedFile = this.transformFile(filename, options); let compiledFunction: ModuleWrapper | null = null; @@ -907,6 +990,27 @@ class Runtime { this._currentlyExecutingModulePath = lastExecutingModulePath; } + private transformFile(filename: string, options?: InternalModuleOptions) { + const transformedFile = this._scriptTransformer.transform( + filename, + this._getFullTransformationOptions(options), + this._cacheFS[filename], + ); + + // we only care about non-internal modules + if (!options || !options.isInternalModule) { + this._fileTransforms.set(filename, transformedFile); + } + + if (transformedFile.sourceMapPath) { + this._sourceMapRegistry[filename] = transformedFile.sourceMapPath; + if (transformedFile.mapCoverage) { + this._needsCoverageMapped.add(filename); + } + } + return transformedFile; + } + private createScriptFromCode(scriptSource: string, filename: string) { try { return new Script(this.wrapCodeInModuleWrapper(scriptSource), { @@ -932,6 +1036,24 @@ class Runtime { return require(moduleName); } + private _importCoreModule(moduleName: string, context: VMContext) { + const required = this._requireCoreModule(moduleName); + + return new SyntheticModule( + ['default', ...Object.keys(required)], + function () { + // @ts-ignore: TS doesn't know what `this` is + this.setExport('default', required); + Object.entries(required).forEach(([key, value]) => { + // @ts-ignore: TS doesn't know what `this` is + this.setExport(key, value); + }); + }, + // should identifier be `node://${moduleName}`? + {context, identifier: moduleName}, + ); + } + private _getMockedNativeModule(): typeof nativeModule.Module { if (this._moduleImplementation) { return this._moduleImplementation; @@ -966,13 +1088,20 @@ class Runtime { // should we implement the class ourselves? class Module extends nativeModule.Module {} + Object.entries(nativeModule.Module).forEach(([key, value]) => { + // @ts-ignore + Module[key] = value; + }); + Module.Module = Module; if ('createRequire' in nativeModule) { Module.createRequire = createRequire; } if ('createRequireFromPath' in nativeModule) { - Module.createRequireFromPath = (filename: string | URL) => { + Module.createRequireFromPath = function createRequireFromPath( + filename: string | URL, + ) { if (typeof filename !== 'string') { const error = new TypeError( `The argument 'filename' must be string. Received '${filename}'.${ @@ -989,7 +1118,7 @@ class Runtime { }; } if ('syncBuiltinESMExports' in nativeModule) { - Module.syncBuiltinESMExports = () => {}; + Module.syncBuiltinESMExports = function syncBuiltinESMExports() {}; } this._moduleImplementation = Module; @@ -1358,6 +1487,7 @@ class Runtime { private getGlobalsForFile(from: Config.Path): JestGlobalsValues { const jest = this.jestObjectCaches.get(from); + // This won't exist in ESM invariant(jest, 'There should always be a Jest object already'); return { diff --git a/yarn.lock b/yarn.lock index 7a6349aa8a03..5263a63044e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2435,6 +2435,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.1.tgz#49a2a83df9d26daacead30d0ccc8762b128d53c7" integrity sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/prettier@^1.19.0": version "1.19.1" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" @@ -9178,6 +9183,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + list-item@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/list-item/-/list-item-1.1.1.tgz#0c65d00e287cb663ccb3cb3849a77e89ec268a56" @@ -11200,6 +11210,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-node-version@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" @@ -12272,6 +12292,15 @@ read-pkg-up@^3.0.0: find-up "^2.0.0" read-pkg "^3.0.0" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -12299,6 +12328,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + read@1, read@~1.0.1: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" @@ -14293,6 +14332,11 @@ type-fest@^0.3.0, type-fest@^0.3.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" From 3681cca5f53f901715ab0064c5bf78f463914498 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Fri, 17 Apr 2020 13:14:00 +0200 Subject: [PATCH 10/39] fix: throw on nested test declarations (#9828) --- CHANGELOG.md | 1 + .../nestedTestDefinitions.test.ts.snap | 40 +++++++++++++ e2e/__tests__/nestedTestDefinitions.test.ts | 57 +++++++++++++++++++ .../__tests__/nestedDescribeInTest.js | 18 ++++++ .../__tests__/nestedTestOutsideDescribe.js | 18 ++++++ .../__tests__/nestedTestWithinDescribe.js | 20 +++++++ e2e/nested-test-definitions/index.js | 10 ++++ e2e/nested-test-definitions/package.json | 5 ++ packages/jest-circus/src/eventHandler.ts | 18 +++++- packages/jest-jasmine2/src/jasmine/Env.ts | 6 +- 10 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/nestedTestDefinitions.test.ts.snap create mode 100644 e2e/__tests__/nestedTestDefinitions.test.ts create mode 100644 e2e/nested-test-definitions/__tests__/nestedDescribeInTest.js create mode 100644 e2e/nested-test-definitions/__tests__/nestedTestOutsideDescribe.js create mode 100644 e2e/nested-test-definitions/__tests__/nestedTestWithinDescribe.js create mode 100644 e2e/nested-test-definitions/index.js create mode 100644 e2e/nested-test-definitions/package.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f9727101221..4215de6b474b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixes - `[expect]` Restore support for passing functions to `toHaveLength` matcher ([#9796](https://github.com/facebook/jest/pull/9796)) +- `[jest-circus]` Throw on nested test definitions ([#9828](https://github.com/facebook/jest/pull/9828)) - `[jest-changed-files]` `--only-changed` should include staged files ([#9799](https://github.com/facebook/jest/pull/9799)) - `[jest-each]` `each` will throw an error when called with too many arguments ([#9818](https://github.com/facebook/jest/pull/9818)) diff --git a/e2e/__tests__/__snapshots__/nestedTestDefinitions.test.ts.snap b/e2e/__tests__/__snapshots__/nestedTestDefinitions.test.ts.snap new file mode 100644 index 000000000000..daba859d0094 --- /dev/null +++ b/e2e/__tests__/__snapshots__/nestedTestDefinitions.test.ts.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`print correct error message with nested test definitions inside describe 1`] = ` +FAIL __tests__/nestedTestWithinDescribe.js + in describe + ✕ outer test + + ● in describe › outer test + + Tests cannot be nested. Test "inner test" cannot run because it is nested within "outer test". + + 14 | expect(getTruthy()).toBeTruthy(); + 15 | + > 16 | test('inner test', () => { + | ^ + 17 | expect(getTruthy()).toBeTruthy(); + 18 | }); + 19 | }); + + at Object.test (__tests__/nestedTestWithinDescribe.js:16:5) +`; + +exports[`print correct error message with nested test definitions outside describe 1`] = ` +FAIL __tests__/nestedTestOutsideDescribe.js + ✕ outer test + + ● outer test + + Tests cannot be nested. Test "inner test" cannot run because it is nested within "outer test". + + 13 | expect(getTruthy()).toBeTruthy(); + 14 | + > 15 | test('inner test', () => { + | ^ + 16 | expect(getTruthy()).toEqual('This test should not have run'); + 17 | }); + 18 | }); + + at Object.test (__tests__/nestedTestOutsideDescribe.js:15:3) +`; diff --git a/e2e/__tests__/nestedTestDefinitions.test.ts b/e2e/__tests__/nestedTestDefinitions.test.ts new file mode 100644 index 000000000000..0a26d4fc14c5 --- /dev/null +++ b/e2e/__tests__/nestedTestDefinitions.test.ts @@ -0,0 +1,57 @@ +/** + * 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 {wrap} from 'jest-snapshot-serializer-raw'; +import {isJestCircusRun} from '@jest/test-utils'; +import runJest from '../runJest'; +import {extractSummary} from '../Utils'; + +const cleanupRunnerStack = (stderr: string) => + wrap( + stderr + .split('\n') + .filter( + line => + !line.includes('packages/jest-jasmine2/build') && + !line.includes('packages/jest-circus/build'), + ) + .join('\n'), + ); + +test('print correct error message with nested test definitions outside describe', () => { + const result = runJest('nested-test-definitions', ['outside']); + + expect(result.exitCode).toBe(1); + + const summary = extractSummary(result.stderr); + + expect(cleanupRunnerStack(summary.rest)).toMatchSnapshot(); +}); + +test('print correct error message with nested test definitions inside describe', () => { + const result = runJest('nested-test-definitions', ['within']); + + expect(result.exitCode).toBe(1); + + const summary = extractSummary(result.stderr); + + expect(cleanupRunnerStack(summary.rest)).toMatchSnapshot(); +}); + +test('print correct message when nesting describe inside it', () => { + if (!isJestCircusRun()) { + return; + } + + const result = runJest('nested-test-definitions', ['nestedDescribeInTest']); + + expect(result.exitCode).toBe(1); + + expect(result.stderr).toContain( + 'Cannot nest a describe inside a test. Describe block "inner describe" cannot run because it is nested within "test".', + ); +}); diff --git a/e2e/nested-test-definitions/__tests__/nestedDescribeInTest.js b/e2e/nested-test-definitions/__tests__/nestedDescribeInTest.js new file mode 100644 index 000000000000..186e795484c7 --- /dev/null +++ b/e2e/nested-test-definitions/__tests__/nestedDescribeInTest.js @@ -0,0 +1,18 @@ +/** + * 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. + */ + +'use strict'; + +const {getTruthy} = require('../index'); + +test('test', () => { + expect(getTruthy()).toBeTruthy(); + + describe('inner describe', () => { + // nothing to see here + }); +}); diff --git a/e2e/nested-test-definitions/__tests__/nestedTestOutsideDescribe.js b/e2e/nested-test-definitions/__tests__/nestedTestOutsideDescribe.js new file mode 100644 index 000000000000..b8c6eb9726c0 --- /dev/null +++ b/e2e/nested-test-definitions/__tests__/nestedTestOutsideDescribe.js @@ -0,0 +1,18 @@ +/** + * 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. + */ + +'use strict'; + +const {getTruthy} = require('../index'); + +test('outer test', () => { + expect(getTruthy()).toBeTruthy(); + + test('inner test', () => { + expect(getTruthy()).toEqual('This test should not have run'); + }); +}); diff --git a/e2e/nested-test-definitions/__tests__/nestedTestWithinDescribe.js b/e2e/nested-test-definitions/__tests__/nestedTestWithinDescribe.js new file mode 100644 index 000000000000..30160cee5a4b --- /dev/null +++ b/e2e/nested-test-definitions/__tests__/nestedTestWithinDescribe.js @@ -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. + */ + +'use strict'; + +const {getTruthy} = require('../index'); + +describe('in describe', () => { + test('outer test', () => { + expect(getTruthy()).toBeTruthy(); + + test('inner test', () => { + expect(getTruthy()).toBeTruthy(); + }); + }); +}); diff --git a/e2e/nested-test-definitions/index.js b/e2e/nested-test-definitions/index.js new file mode 100644 index 000000000000..849dbee86e41 --- /dev/null +++ b/e2e/nested-test-definitions/index.js @@ -0,0 +1,10 @@ +/** + * 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. + */ + +'use strict'; + +module.exports.getTruthy = () => true; diff --git a/e2e/nested-test-definitions/package.json b/e2e/nested-test-definitions/package.json new file mode 100644 index 000000000000..0ded940b7cb7 --- /dev/null +++ b/e2e/nested-test-definitions/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "jsdom" + } +} diff --git a/packages/jest-circus/src/eventHandler.ts b/packages/jest-circus/src/eventHandler.ts index 7c3a0f9299f4..2e1327a8ad6b 100644 --- a/packages/jest-circus/src/eventHandler.ts +++ b/packages/jest-circus/src/eventHandler.ts @@ -36,7 +36,14 @@ const eventHandler: Circus.EventHandler = ( } case 'start_describe_definition': { const {blockName, mode} = event; - const {currentDescribeBlock} = state; + const {currentDescribeBlock, currentlyRunningTest} = state; + + if (currentlyRunningTest) { + throw new Error( + `Cannot nest a describe inside a test. Describe block "${blockName}" cannot run because it is nested within "${currentlyRunningTest.name}".`, + ); + } + const describeBlock = makeDescribe(blockName, currentDescribeBlock, mode); currentDescribeBlock.children.push(describeBlock); state.currentDescribeBlock = describeBlock; @@ -88,8 +95,15 @@ const eventHandler: Circus.EventHandler = ( break; } case 'add_test': { - const {currentDescribeBlock} = state; + const {currentDescribeBlock, currentlyRunningTest} = state; const {asyncError, fn, mode, testName: name, timeout} = event; + + if (currentlyRunningTest) { + throw new Error( + `Tests cannot be nested. Test "${name}" cannot run because it is nested within "${currentlyRunningTest.name}".`, + ); + } + const test = makeTest( fn, mode, diff --git a/packages/jest-jasmine2/src/jasmine/Env.ts b/packages/jest-jasmine2/src/jasmine/Env.ts index 48e6b82fd4b4..a94173a7321f 100644 --- a/packages/jest-jasmine2/src/jasmine/Env.ts +++ b/packages/jest-jasmine2/src/jasmine/Env.ts @@ -566,11 +566,7 @@ export default function (j$: Jasmine) { // This check throws an error to warn the user about the edge-case. if (currentSpec !== null) { throw new Error( - 'Tests cannot be nested. Test `' + - spec.description + - '` cannot run because it is nested within `' + - currentSpec.description + - '`.', + `Tests cannot be nested. Test "${spec.description}" cannot run because it is nested within "${currentSpec.description}".`, ); } currentDeclarationSuite.addChild(spec); From 75ab1abe67d30f7aa25a5b01218af6af1059f8f9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 19 Apr 2020 23:19:09 +0200 Subject: [PATCH 11/39] Revert "feat: add `@jest/globals` package for importing globals explicitly (#9801)" This reverts commit 2882d2848c290ce40c356a7b0d62c36439efb445. --- CHANGELOG.md | 1 - docs/GlobalAPI.md | 2 +- docs/JestObjectAPI.md | 2 +- e2e/__tests__/importedGlobals.test.ts | 13 ----- e2e/imported-globals/__tests__/env.test.js | 22 --------- e2e/imported-globals/babel.config.js | 8 --- e2e/imported-globals/package.json | 5 -- packages/jest-globals/.npmignore | 5 -- packages/jest-globals/package.json | 30 ------------ packages/jest-globals/src/__tests__/index.ts | 12 ----- packages/jest-globals/src/index.ts | 31 ------------ packages/jest-globals/tsconfig.json | 14 ------ packages/jest-runtime/package.json | 1 - packages/jest-runtime/src/index.ts | 51 ++------------------ packages/jest-runtime/tsconfig.json | 1 - 15 files changed, 7 insertions(+), 191 deletions(-) delete mode 100644 e2e/__tests__/importedGlobals.test.ts delete mode 100644 e2e/imported-globals/__tests__/env.test.js delete mode 100644 e2e/imported-globals/babel.config.js delete mode 100644 e2e/imported-globals/package.json delete mode 100644 packages/jest-globals/.npmignore delete mode 100644 packages/jest-globals/package.json delete mode 100644 packages/jest-globals/src/__tests__/index.ts delete mode 100644 packages/jest-globals/src/index.ts delete mode 100644 packages/jest-globals/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 4215de6b474b..2ad55d074c54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,6 @@ - `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) -- `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) - `[jest-runtime, jest-jasmine2, jest-circus]` Experimental, limited ECMAScript Modules support ([#9772](https://github.com/facebook/jest/pull/9772)) ### Fixes diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index bbbc7d526b05..d01f975884b8 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -3,7 +3,7 @@ id: api title: Globals --- -In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them. However, if you prefer explicit imports, you can do `import {describe, expect, it} from '@jest/globals'`. +In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them. ## Methods diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index 784c5c3370f1..638e16f38550 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -3,7 +3,7 @@ id: jest-object title: The Jest Object --- -The `jest` object is automatically in scope within every test file. The methods in the `jest` object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via `import {jest} from '@jest/globals'`. +The `jest` object is automatically in scope within every test file. The methods in the `jest` object help create mocks and let you control Jest's overall behavior. ## Mock Modules diff --git a/e2e/__tests__/importedGlobals.test.ts b/e2e/__tests__/importedGlobals.test.ts deleted file mode 100644 index 146ed6544715..000000000000 --- a/e2e/__tests__/importedGlobals.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * 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 runJest from '../runJest'; - -test('imported globals', () => { - const result = runJest('imported-globals'); - expect(result.exitCode).toBe(0); -}); diff --git a/e2e/imported-globals/__tests__/env.test.js b/e2e/imported-globals/__tests__/env.test.js deleted file mode 100644 index e81a1db5a6d5..000000000000 --- a/e2e/imported-globals/__tests__/env.test.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 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 as importedExpect, - jest as importedJest, - test as importedTest, -} from '@jest/globals'; - -importedTest('they match the globals', () => { - importedExpect(importedExpect).toBe(expect); - importedExpect(importedJest).toBe(jest); - importedExpect(importedTest).toBe(test); - - expect(importedExpect).toBe(expect); - expect(importedJest).toBe(jest); - expect(importedTest).toBe(test); -}); diff --git a/e2e/imported-globals/babel.config.js b/e2e/imported-globals/babel.config.js deleted file mode 100644 index 9be036106918..000000000000 --- a/e2e/imported-globals/babel.config.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * 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. - */ - -module.exports = require('../../babel.config'); diff --git a/e2e/imported-globals/package.json b/e2e/imported-globals/package.json deleted file mode 100644 index 148788b25446..000000000000 --- a/e2e/imported-globals/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "jest": { - "testEnvironment": "node" - } -} diff --git a/packages/jest-globals/.npmignore b/packages/jest-globals/.npmignore deleted file mode 100644 index 3ee5d55b0b89..000000000000 --- a/packages/jest-globals/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -**/__mocks__/** -**/__tests__/** -src -tsconfig.json -tsconfig.tsbuildinfo diff --git a/packages/jest-globals/package.json b/packages/jest-globals/package.json deleted file mode 100644 index 80ac807c888e..000000000000 --- a/packages/jest-globals/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@jest/globals", - "version": "25.3.0", - "repository": { - "type": "git", - "url": "https://github.com/facebook/jest.git", - "directory": "packages/jest-globals" - }, - "engines": { - "node": ">= 8.3" - }, - "license": "MIT", - "main": "build/index.js", - "types": "build/index.d.ts", - "typesVersions": { - "<3.8": { - "build/*": [ - "build/ts3.4/*" - ] - } - }, - "dependencies": { - "@jest/environment": "^25.3.0", - "@jest/types": "^25.3.0", - "expect": "^25.3.0" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/jest-globals/src/__tests__/index.ts b/packages/jest-globals/src/__tests__/index.ts deleted file mode 100644 index cb0af7398581..000000000000 --- a/packages/jest-globals/src/__tests__/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 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. - */ - -test('throw when directly imported', () => { - expect(() => require('../')).toThrowError( - 'Do not import `@jest/globals` outside of the Jest test environment', - ); -}); diff --git a/packages/jest-globals/src/index.ts b/packages/jest-globals/src/index.ts deleted file mode 100644 index 82bc15a3b522..000000000000 --- a/packages/jest-globals/src/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 importedExpect = require('expect'); -import type {Jest} from '@jest/environment'; -import type {Global} from '@jest/types'; - -export declare type jest = Jest; - -export declare type expect = typeof importedExpect; - -export declare type it = Global.GlobalAdditions['it']; -export declare type test = Global.GlobalAdditions['test']; -export declare type fit = Global.GlobalAdditions['fit']; -export declare type xit = Global.GlobalAdditions['xit']; -export declare type xtest = Global.GlobalAdditions['xtest']; -export declare type describe = Global.GlobalAdditions['describe']; -export declare type xdescribe = Global.GlobalAdditions['xdescribe']; -export declare type fdescribe = Global.GlobalAdditions['fdescribe']; -export declare type beforeAll = Global.GlobalAdditions['beforeAll']; -export declare type beforeEach = Global.GlobalAdditions['beforeEach']; -export declare type afterEach = Global.GlobalAdditions['afterEach']; -export declare type afterAll = Global.GlobalAdditions['afterAll']; - -throw new Error( - 'Do not import `@jest/globals` outside of the Jest test environment', -); diff --git a/packages/jest-globals/tsconfig.json b/packages/jest-globals/tsconfig.json deleted file mode 100644 index b6678e5f0aed..000000000000 --- a/packages/jest-globals/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - // we don't want `@types/jest` to be referenced - "types": ["node"], - "rootDir": "src", - "outDir": "build" - }, - "references": [ - {"path": "../expect"}, - {"path": "../jest-environment"}, - {"path": "../jest-types"} - ] -} diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index 822778a4f389..bf389a1ef25f 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -19,7 +19,6 @@ "dependencies": { "@jest/console": "^25.3.0", "@jest/environment": "^25.3.0", - "@jest/globals": "^25.3.0", "@jest/source-map": "^25.2.6", "@jest/test-result": "^25.3.0", "@jest/transform": "^25.3.0", diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 1a5cff8361a7..5e0c5ff8ec70 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -19,7 +19,7 @@ import { compileFunction, } from 'vm'; import * as nativeModule from 'module'; -import type {Config, Global} from '@jest/types'; +import type {Config} from '@jest/types'; import type { Jest, JestEnvironment, @@ -27,7 +27,6 @@ import type { Module, ModuleWrapper, } from '@jest/environment'; -import type * as JestGlobals from '@jest/globals'; import type {SourceMapRegistry} from '@jest/source-map'; import {formatStackTrace, separateMessageFromStack} from 'jest-message-util'; import {createDirectory, deepCyclicCopy} from 'jest-util'; @@ -53,11 +52,6 @@ import Resolver = require('jest-resolve'); import Snapshot = require('jest-snapshot'); import stripBOM = require('strip-bom'); -interface JestGlobalsValues extends Global.TestFrameworkGlobals { - jest: JestGlobals.jest; - expect: JestGlobals.expect; -} - type HasteMapOptions = { console?: Console; maxWorkers: number; @@ -152,7 +146,6 @@ class Runtime { private _unmockList: RegExp | undefined; private _virtualMocks: BooleanObject; private _moduleImplementation?: typeof nativeModule.Module; - private jestObjectCaches: Map; constructor( config: Config.ProjectConfig, @@ -190,7 +183,6 @@ class Runtime { this._sourceMapRegistry = Object.create(null); this._fileTransforms = new Map(); this._virtualMocks = Object.create(null); - this.jestObjectCaches = new Map(); this._mockMetaDataCache = Object.create(null); this._shouldMockModuleCache = Object.create(null); @@ -428,11 +420,6 @@ class Runtime { modulePath = manualMock; } - if (moduleName === '@jest/globals') { - // @ts-ignore: we don't care that it's not assignable to T - return this.getGlobalsForFile(from); - } - if (moduleName && this._resolver.isCoreModule(moduleName)) { return this._requireCoreModule(moduleName); } @@ -955,13 +942,6 @@ class Runtime { return; } - const jestObject = this._createJestObjectFor( - filename, - localModule.require as LocalModuleRequire, - ); - - this.jestObjectCaches.set(filename, jestObject); - try { compiledFunction.call( localModule.exports, @@ -971,7 +951,10 @@ class Runtime { dirname, // __dirname filename, // __filename this._environment.global, // global object - jestObject, // jest object + this._createJestObjectFor( + filename, + localModule.require as LocalModuleRequire, + ), // jest object ...this._config.extraGlobals.map(globalVariable => { if (this._environment.global[globalVariable]) { return this._environment.global[globalVariable]; @@ -1483,30 +1466,6 @@ class Runtime { throw e; } - - private getGlobalsForFile(from: Config.Path): JestGlobalsValues { - const jest = this.jestObjectCaches.get(from); - - // This won't exist in ESM - invariant(jest, 'There should always be a Jest object already'); - - return { - afterAll: this._environment.global.afterAll, - afterEach: this._environment.global.afterEach, - beforeAll: this._environment.global.beforeAll, - beforeEach: this._environment.global.beforeEach, - describe: this._environment.global.describe, - expect: this._environment.global.expect, - fdescribe: this._environment.global.fdescribe, - fit: this._environment.global.fit, - it: this._environment.global.it, - jest, - test: this._environment.global.test, - xdescribe: this._environment.global.xdescribe, - xit: this._environment.global.xit, - xtest: this._environment.global.xtest, - }; - } } function invariant(condition: unknown, message?: string): asserts condition { diff --git a/packages/jest-runtime/tsconfig.json b/packages/jest-runtime/tsconfig.json index 2955d779d6b1..08abc7a9ddfc 100644 --- a/packages/jest-runtime/tsconfig.json +++ b/packages/jest-runtime/tsconfig.json @@ -9,7 +9,6 @@ {"path": "../jest-console"}, {"path": "../jest-environment"}, {"path": "../jest-environment-node"}, - {"path": "../jest-globals"}, {"path": "../jest-haste-map"}, {"path": "../jest-message-util"}, {"path": "../jest-mock"}, From ed4cadbc91115c82d99601d7bb5d52f77e8ee064 Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Sun, 19 Apr 2020 22:35:25 +0100 Subject: [PATCH 12/39] `[jest-runner]` Don't print warning to stdout when using `--json (#9843) --- CHANGELOG.md | 1 + e2e/__tests__/workerForceExit.test.ts | 4 ++-- packages/jest-runner/src/index.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad55d074c54..582be5e1111f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - `[jest-circus]` Throw on nested test definitions ([#9828](https://github.com/facebook/jest/pull/9828)) - `[jest-changed-files]` `--only-changed` should include staged files ([#9799](https://github.com/facebook/jest/pull/9799)) - `[jest-each]` `each` will throw an error when called with too many arguments ([#9818](https://github.com/facebook/jest/pull/9818)) +- `[jest-runner]` Don't print warning to stdout when using `--json` ([#9843](https://github.com/facebook/jest/pull/9843)) ### Chore & Maintenance diff --git a/e2e/__tests__/workerForceExit.test.ts b/e2e/__tests__/workerForceExit.test.ts index 884b2987c953..ec27fa0cd197 100644 --- a/e2e/__tests__/workerForceExit.test.ts +++ b/e2e/__tests__/workerForceExit.test.ts @@ -42,11 +42,11 @@ test('prints a warning if a worker is force exited', () => { }); `, }); - const {exitCode, stderr, stdout} = runJest(DIR, ['--maxWorkers=2']); + const {exitCode, stderr} = runJest(DIR, ['--maxWorkers=2']); expect(exitCode).toBe(0); verifyNumPassed(stderr); - expect(stdout).toContain('A worker process has failed to exit gracefully'); + expect(stderr).toContain('A worker process has failed to exit gracefully'); }); test('force exits a worker that fails to exit gracefully', async () => { diff --git a/packages/jest-runner/src/index.ts b/packages/jest-runner/src/index.ts index 518c07ad8f03..9cf5659426cb 100644 --- a/packages/jest-runner/src/index.ts +++ b/packages/jest-runner/src/index.ts @@ -194,7 +194,7 @@ class TestRunner { const cleanup = async () => { const {forceExited} = await worker.end(); if (forceExited) { - console.log( + console.error( chalk.yellow( 'A worker process has failed to exit gracefully and has been force exited. ' + 'This is likely caused by tests leaking due to improper teardown. ' + From 8b70b47fdf2f2a28dbe7676bce9140a3bd3081c5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 19 Apr 2020 23:38:39 +0200 Subject: [PATCH 13/39] feat: support importing CommonJS from ESM files (#9842) --- CHANGELOG.md | 2 +- .../__snapshots__/nativeEsm.test.ts.snap | 2 +- e2e/native-esm/__tests__/native-esm.test.js | 41 +++++++++++++ e2e/native-esm/commonjs.cjs | 10 ++++ e2e/native-esm/dynamicImport.js | 8 +++ e2e/native-esm/stateful.cjs | 13 ++++ e2e/native-esm/stateful.mjs | 13 ++++ packages/jest-runtime/src/index.ts | 60 ++++++++++++++++--- 8 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 e2e/native-esm/commonjs.cjs create mode 100644 e2e/native-esm/dynamicImport.js create mode 100644 e2e/native-esm/stateful.cjs create mode 100644 e2e/native-esm/stateful.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 582be5e1111f..1c96253b5665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ - `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) -- `[jest-runtime, jest-jasmine2, jest-circus]` Experimental, limited ECMAScript Modules support ([#9772](https://github.com/facebook/jest/pull/9772)) +- `[jest-runtime, jest-jasmine2, jest-circus]` Experimental, limited ECMAScript Modules support ([#9772](https://github.com/facebook/jest/pull/9772) & [#9842](https://github.com/facebook/jest/pull/9842)) ### Fixes diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index 1ec158742c61..14cb786f3ddb 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -2,7 +2,7 @@ exports[`on node >=12.16.0 runs test with native ESM 1`] = ` Test Suites: 1 passed, 1 total -Tests: 4 passed, 4 total +Tests: 8 passed, 8 total Snapshots: 0 total Time: <> Ran all test suites. diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index 3b8508cd77cf..5a406a9137c7 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -6,8 +6,10 @@ */ import {readFileSync} from 'fs'; +import {createRequire} from 'module'; import {dirname, resolve} from 'path'; import {fileURLToPath} from 'url'; +import staticImportedStateful from '../stateful.mjs'; import {double} from '../index'; test('should have correct import.meta', () => { @@ -44,3 +46,42 @@ test('dynamic import should work', async () => { expect(importedDouble).toBe(double); expect(importedDouble(1)).toBe(2); }); + +test('import cjs', async () => { + const {default: half} = await import('../commonjs.cjs'); + + expect(half(4)).toBe(2); +}); + +test('require(cjs) and import(cjs) should share caches', async () => { + const require = createRequire(import.meta.url); + + const {default: importedStateful} = await import('../stateful.cjs'); + const requiredStateful = require('../stateful.cjs'); + + expect(importedStateful()).toBe(1); + expect(importedStateful()).toBe(2); + expect(requiredStateful()).toBe(3); + expect(importedStateful()).toBe(4); + expect(requiredStateful()).toBe(5); + expect(requiredStateful()).toBe(6); +}); + +test('import from mjs and import(mjs) should share caches', async () => { + const {default: importedStateful} = await import('../stateful.mjs'); + + expect(importedStateful()).toBe(1); + expect(importedStateful()).toBe(2); + expect(staticImportedStateful()).toBe(3); + expect(importedStateful()).toBe(4); + expect(staticImportedStateful()).toBe(5); + expect(staticImportedStateful()).toBe(6); +}); + +test('handle unlinked dynamic imports', async () => { + const {double: deepDouble} = await import('../dynamicImport'); + + expect(deepDouble).toBe(double); + + expect(deepDouble(4)).toBe(8); +}); diff --git a/e2e/native-esm/commonjs.cjs b/e2e/native-esm/commonjs.cjs new file mode 100644 index 000000000000..dcb0cfd461fb --- /dev/null +++ b/e2e/native-esm/commonjs.cjs @@ -0,0 +1,10 @@ +/** + * 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. + */ + +module.exports = function half(num) { + return num / 2; +}; diff --git a/e2e/native-esm/dynamicImport.js b/e2e/native-esm/dynamicImport.js new file mode 100644 index 000000000000..84b87a513c85 --- /dev/null +++ b/e2e/native-esm/dynamicImport.js @@ -0,0 +1,8 @@ +/** + * 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. + */ + +export * from './index'; diff --git a/e2e/native-esm/stateful.cjs b/e2e/native-esm/stateful.cjs new file mode 100644 index 000000000000..cda0aec7cdcd --- /dev/null +++ b/e2e/native-esm/stateful.cjs @@ -0,0 +1,13 @@ +/** + * 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. + */ + +let num = 0; + +module.exports = function inc() { + num++; + return num; +}; diff --git a/e2e/native-esm/stateful.mjs b/e2e/native-esm/stateful.mjs new file mode 100644 index 000000000000..485da62bd3c3 --- /dev/null +++ b/e2e/native-esm/stateful.mjs @@ -0,0 +1,13 @@ +/** + * 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. + */ + +let num = 0; + +export default function inc() { + num++; + return num; +} diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 5e0c5ff8ec70..4a7883aa260b 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -352,16 +352,38 @@ class Runtime { importModuleDynamically: ( specifier: string, referencingModule: VMModule, - ) => - this.loadEsmModule( - this._resolveModule(referencingModule.identifier, specifier), - ), + ) => { + const resolved = this._resolveModule( + referencingModule.identifier, + specifier, + ); + if ( + this._resolver.isCoreModule(resolved) || + this.unstable_shouldLoadAsEsm(resolved) + ) { + return this.loadEsmModule(resolved); + } + + return this.loadCjsAsEsm( + referencingModule.identifier, + resolved, + context, + ); + }, initializeImportMeta(meta: ImportMeta) { meta.url = pathToFileURL(modulePath).href; }, }); this._esmoduleRegistry.set(cacheKey, module); + + await module.link((specifier: string, referencingModule: VMModule) => + this.loadEsmModule( + this._resolveModule(referencingModule.identifier, specifier), + ), + ); + + await module.evaluate(); } const module = this._esmoduleRegistry.get(cacheKey); @@ -382,13 +404,33 @@ class Runtime { const modulePath = this._resolveModule(from, moduleName); - const module = await this.loadEsmModule(modulePath); - await module.link((specifier: string, referencingModule: VMModule) => - this.loadEsmModule( - this._resolveModule(referencingModule.identifier, specifier), - ), + return this.loadEsmModule(modulePath); + } + + private async loadCjsAsEsm( + from: Config.Path, + modulePath: Config.Path, + context: VMContext, + ) { + // CJS loaded via `import` should share cache with other CJS: https://github.com/nodejs/modules/issues/503 + const cjs = this.requireModuleOrMock(from, modulePath); + + const module = new SyntheticModule( + ['default'], + function () { + // @ts-ignore: TS doesn't know what `this` is + this.setExport('default', cjs); + }, + {context, identifier: modulePath}, ); + + await module.link(() => { + throw new Error('This should never happen'); + }); + await module.evaluate(); + + return module; } requireModule( From cf3f85439deaa41f3bb4b1cbee08327847e1def9 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 19 Apr 2020 23:40:00 +0200 Subject: [PATCH 14/39] chore: update changelog for release --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c96253b5665..839115831aea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ### Features +### Fixes + +### Chore & Maintenance + +### Performance + +## 25.4.0 + - `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) - `[jest-console]` Add code frame to `console.error` and `console.warn` ([#9741](https://github.com/facebook/jest/pull/9741)) - `[jest-runtime, jest-jasmine2, jest-circus]` Experimental, limited ECMAScript Modules support ([#9772](https://github.com/facebook/jest/pull/9772) & [#9842](https://github.com/facebook/jest/pull/9842)) From 5b129d714cadb818be28afbe313cbeae8fbb1dde Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 19 Apr 2020 23:50:11 +0200 Subject: [PATCH 15/39] v25.4.0 --- lerna.json | 2 +- packages/babel-jest/package.json | 8 ++-- packages/babel-plugin-jest-hoist/package.json | 2 +- packages/babel-preset-jest/package.json | 4 +- packages/expect/package.json | 8 ++-- packages/jest-changed-files/package.json | 4 +- packages/jest-circus/package.json | 24 ++++++------ packages/jest-cli/package.json | 14 +++---- packages/jest-config/package.json | 22 +++++------ packages/jest-console/package.json | 8 ++-- packages/jest-core/package.json | 38 +++++++++---------- packages/jest-diff/package.json | 4 +- packages/jest-each/package.json | 8 ++-- packages/jest-environment-jsdom/package.json | 12 +++--- packages/jest-environment-node/package.json | 12 +++--- packages/jest-environment/package.json | 8 ++-- packages/jest-fake-timers/package.json | 10 ++--- packages/jest-haste-map/package.json | 8 ++-- packages/jest-jasmine2/package.json | 24 ++++++------ packages/jest-leak-detector/package.json | 4 +- packages/jest-matcher-utils/package.json | 6 +-- packages/jest-message-util/package.json | 4 +- packages/jest-mock/package.json | 4 +- packages/jest-phabricator/package.json | 4 +- packages/jest-repl/package.json | 12 +++--- packages/jest-reporters/package.json | 18 ++++----- .../jest-resolve-dependencies/package.json | 12 +++--- packages/jest-resolve/package.json | 6 +-- packages/jest-runner/package.json | 30 +++++++-------- packages/jest-runtime/package.json | 30 +++++++-------- packages/jest-snapshot/package.json | 18 ++++----- packages/jest-test-result/package.json | 6 +-- packages/jest-test-sequencer/package.json | 10 ++--- packages/jest-transform/package.json | 8 ++-- packages/jest-types/package.json | 2 +- packages/jest-util/package.json | 4 +- packages/jest-validate/package.json | 6 +-- packages/jest-watcher/package.json | 8 ++-- packages/jest-worker/package.json | 2 +- packages/jest/package.json | 6 +-- packages/pretty-format/package.json | 4 +- 41 files changed, 212 insertions(+), 212 deletions(-) diff --git a/lerna.json b/lerna.json index 6c27659d1a81..b6e56f7c55fc 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "25.3.0", + "version": "25.4.0", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/babel-jest/package.json b/packages/babel-jest/package.json index bc29e23c19a5..a6eca647bef5 100644 --- a/packages/babel-jest/package.json +++ b/packages/babel-jest/package.json @@ -1,7 +1,7 @@ { "name": "babel-jest", "description": "Jest plugin to use babel for transformation.", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,11 +18,11 @@ } }, "dependencies": { - "@jest/transform": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/transform": "^25.4.0", + "@jest/types": "^25.4.0", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^25.3.0", + "babel-preset-jest": "^25.4.0", "chalk": "^3.0.0", "slash": "^3.0.0" }, diff --git a/packages/babel-plugin-jest-hoist/package.json b/packages/babel-plugin-jest-hoist/package.json index e46bfbd5f680..de303f8cfdff 100644 --- a/packages/babel-plugin-jest-hoist/package.json +++ b/packages/babel-plugin-jest-hoist/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-jest-hoist", - "version": "25.2.6", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", diff --git a/packages/babel-preset-jest/package.json b/packages/babel-preset-jest/package.json index 676b6dbcd1d1..9695bdbed32c 100644 --- a/packages/babel-preset-jest/package.json +++ b/packages/babel-preset-jest/package.json @@ -1,6 +1,6 @@ { "name": "babel-preset-jest", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -9,7 +9,7 @@ "license": "MIT", "main": "index.js", "dependencies": { - "babel-plugin-jest-hoist": "^25.2.6", + "babel-plugin-jest-hoist": "^25.4.0", "babel-preset-current-node-syntax": "^0.1.2" }, "peerDependencies": { diff --git a/packages/expect/package.json b/packages/expect/package.json index 48f17a6dabf2..04dbdb74f56a 100644 --- a/packages/expect/package.json +++ b/packages/expect/package.json @@ -1,6 +1,6 @@ { "name": "expect", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,11 +18,11 @@ }, "browser": "build-es5/index.js", "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "ansi-styles": "^4.0.0", "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.3.0", - "jest-message-util": "^25.3.0", + "jest-matcher-utils": "^25.4.0", + "jest-message-util": "^25.4.0", "jest-regex-util": "^25.2.6" }, "devDependencies": { diff --git a/packages/jest-changed-files/package.json b/packages/jest-changed-files/package.json index 9abd11d0157c..454b06e57b69 100644 --- a/packages/jest-changed-files/package.json +++ b/packages/jest-changed-files/package.json @@ -1,6 +1,6 @@ { "name": "jest-changed-files", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,7 +17,7 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "execa": "^3.2.0", "throat": "^5.0.0" }, diff --git a/packages/jest-circus/package.json b/packages/jest-circus/package.json index 053fae413eca..da9d3547d944 100644 --- a/packages/jest-circus/package.json +++ b/packages/jest-circus/package.json @@ -1,6 +1,6 @@ { "name": "jest-circus", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,20 +18,20 @@ }, "dependencies": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^25.3.0", - "@jest/test-result": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/environment": "^25.4.0", + "@jest/test-result": "^25.4.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "co": "^4.6.0", - "expect": "^25.3.0", + "expect": "^25.4.0", "is-generator-fn": "^2.0.0", - "jest-each": "^25.3.0", - "jest-matcher-utils": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-runtime": "^25.3.0", - "jest-snapshot": "^25.3.0", - "jest-util": "^25.3.0", - "pretty-format": "^25.3.0", + "jest-each": "^25.4.0", + "jest-matcher-utils": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-runtime": "^25.4.0", + "jest-snapshot": "^25.4.0", + "jest-util": "^25.4.0", + "pretty-format": "^25.4.0", "stack-utils": "^1.0.1", "throat": "^5.0.0" }, diff --git a/packages/jest-cli/package.json b/packages/jest-cli/package.json index a7e640f5d876..f556af3d0144 100644 --- a/packages/jest-cli/package.json +++ b/packages/jest-cli/package.json @@ -1,7 +1,7 @@ { "name": "jest-cli", "description": "Delightful JavaScript Testing.", - "version": "25.3.0", + "version": "25.4.0", "main": "build/index.js", "types": "build/index.d.ts", "typesVersions": { @@ -12,16 +12,16 @@ } }, "dependencies": { - "@jest/core": "^25.3.0", - "@jest/test-result": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/core": "^25.4.0", + "@jest/test-result": "^25.4.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "exit": "^0.1.2", "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^25.3.0", - "jest-util": "^25.3.0", - "jest-validate": "^25.3.0", + "jest-config": "^25.4.0", + "jest-util": "^25.4.0", + "jest-validate": "^25.4.0", "prompts": "^2.0.1", "realpath-native": "^2.0.0", "yargs": "^15.3.1" diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index f3f74d08f554..7cf920caf17f 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -1,6 +1,6 @@ { "name": "jest-config", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,22 +18,22 @@ }, "dependencies": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^25.3.0", - "@jest/types": "^25.3.0", - "babel-jest": "^25.3.0", + "@jest/test-sequencer": "^25.4.0", + "@jest/types": "^25.4.0", + "babel-jest": "^25.4.0", "chalk": "^3.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", - "jest-environment-jsdom": "^25.3.0", - "jest-environment-node": "^25.3.0", + "jest-environment-jsdom": "^25.4.0", + "jest-environment-node": "^25.4.0", "jest-get-type": "^25.2.6", - "jest-jasmine2": "^25.3.0", + "jest-jasmine2": "^25.4.0", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.3.0", - "jest-util": "^25.3.0", - "jest-validate": "^25.3.0", + "jest-resolve": "^25.4.0", + "jest-util": "^25.4.0", + "jest-validate": "^25.4.0", "micromatch": "^4.0.2", - "pretty-format": "^25.3.0", + "pretty-format": "^25.4.0", "realpath-native": "^2.0.0" }, "devDependencies": { diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 3b7e6f1ce578..ba663dc366ca 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -1,6 +1,6 @@ { "name": "@jest/console", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,10 +17,10 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", - "jest-message-util": "^25.3.0", - "jest-util": "^25.3.0", + "jest-message-util": "^25.4.0", + "jest-util": "^25.4.0", "slash": "^3.0.0" }, "devDependencies": { diff --git a/packages/jest-core/package.json b/packages/jest-core/package.json index ac2c69310ddb..19a6c5d804b8 100644 --- a/packages/jest-core/package.json +++ b/packages/jest-core/package.json @@ -1,7 +1,7 @@ { "name": "@jest/core", "description": "Delightful JavaScript Testing.", - "version": "25.3.0", + "version": "25.4.0", "main": "build/jest.js", "types": "build/jest.d.ts", "typesVersions": { @@ -12,28 +12,28 @@ } }, "dependencies": { - "@jest/console": "^25.3.0", - "@jest/reporters": "^25.3.0", - "@jest/test-result": "^25.3.0", - "@jest/transform": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/console": "^25.4.0", + "@jest/reporters": "^25.4.0", + "@jest/test-result": "^25.4.0", + "@jest/transform": "^25.4.0", + "@jest/types": "^25.4.0", "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.3", - "jest-changed-files": "^25.3.0", - "jest-config": "^25.3.0", - "jest-haste-map": "^25.3.0", - "jest-message-util": "^25.3.0", + "jest-changed-files": "^25.4.0", + "jest-config": "^25.4.0", + "jest-haste-map": "^25.4.0", + "jest-message-util": "^25.4.0", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.3.0", - "jest-resolve-dependencies": "^25.3.0", - "jest-runner": "^25.3.0", - "jest-runtime": "^25.3.0", - "jest-snapshot": "^25.3.0", - "jest-util": "^25.3.0", - "jest-validate": "^25.3.0", - "jest-watcher": "^25.3.0", + "jest-resolve": "^25.4.0", + "jest-resolve-dependencies": "^25.4.0", + "jest-runner": "^25.4.0", + "jest-runtime": "^25.4.0", + "jest-snapshot": "^25.4.0", + "jest-util": "^25.4.0", + "jest-validate": "^25.4.0", + "jest-watcher": "^25.4.0", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "realpath-native": "^2.0.0", @@ -42,7 +42,7 @@ "strip-ansi": "^6.0.0" }, "devDependencies": { - "@jest/test-sequencer": "^25.3.0", + "@jest/test-sequencer": "^25.4.0", "@types/exit": "^0.1.30", "@types/graceful-fs": "^4.1.2", "@types/micromatch": "^4.0.0", diff --git a/packages/jest-diff/package.json b/packages/jest-diff/package.json index 56d44250aa38..561942c03c01 100644 --- a/packages/jest-diff/package.json +++ b/packages/jest-diff/package.json @@ -1,6 +1,6 @@ { "name": "jest-diff", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -20,7 +20,7 @@ "chalk": "^3.0.0", "diff-sequences": "^25.2.6", "jest-get-type": "^25.2.6", - "pretty-format": "^25.3.0" + "pretty-format": "^25.4.0" }, "devDependencies": { "@jest/test-utils": "^25.3.0", diff --git a/packages/jest-each/package.json b/packages/jest-each/package.json index 2b3b94de400c..316149df7c50 100644 --- a/packages/jest-each/package.json +++ b/packages/jest-each/package.json @@ -1,6 +1,6 @@ { "name": "jest-each", - "version": "25.3.0", + "version": "25.4.0", "description": "Parameterised tests for Jest", "main": "build/index.js", "types": "build/index.d.ts", @@ -25,11 +25,11 @@ "author": "Matt Phillips (mattphillips)", "license": "MIT", "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "jest-get-type": "^25.2.6", - "jest-util": "^25.3.0", - "pretty-format": "^25.3.0" + "jest-util": "^25.4.0", + "pretty-format": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-environment-jsdom/package.json b/packages/jest-environment-jsdom/package.json index c355720a4eb9..06c38b58c389 100644 --- a/packages/jest-environment-jsdom/package.json +++ b/packages/jest-environment-jsdom/package.json @@ -1,6 +1,6 @@ { "name": "jest-environment-jsdom", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,11 +17,11 @@ } }, "dependencies": { - "@jest/environment": "^25.3.0", - "@jest/fake-timers": "^25.3.0", - "@jest/types": "^25.3.0", - "jest-mock": "^25.3.0", - "jest-util": "^25.3.0", + "@jest/environment": "^25.4.0", + "@jest/fake-timers": "^25.4.0", + "@jest/types": "^25.4.0", + "jest-mock": "^25.4.0", + "jest-util": "^25.4.0", "jsdom": "^15.2.1" }, "devDependencies": { diff --git a/packages/jest-environment-node/package.json b/packages/jest-environment-node/package.json index 96512c431199..cfec5d2b3eb0 100644 --- a/packages/jest-environment-node/package.json +++ b/packages/jest-environment-node/package.json @@ -1,6 +1,6 @@ { "name": "jest-environment-node", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,11 +17,11 @@ } }, "dependencies": { - "@jest/environment": "^25.3.0", - "@jest/fake-timers": "^25.3.0", - "@jest/types": "^25.3.0", - "jest-mock": "^25.3.0", - "jest-util": "^25.3.0", + "@jest/environment": "^25.4.0", + "@jest/fake-timers": "^25.4.0", + "@jest/types": "^25.4.0", + "jest-mock": "^25.4.0", + "jest-util": "^25.4.0", "semver": "^6.3.0" }, "devDependencies": { diff --git a/packages/jest-environment/package.json b/packages/jest-environment/package.json index 27858e12e838..4e68a7f81dd6 100644 --- a/packages/jest-environment/package.json +++ b/packages/jest-environment/package.json @@ -1,6 +1,6 @@ { "name": "@jest/environment", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,9 +17,9 @@ } }, "dependencies": { - "@jest/fake-timers": "^25.3.0", - "@jest/types": "^25.3.0", - "jest-mock": "^25.3.0" + "@jest/fake-timers": "^25.4.0", + "@jest/types": "^25.4.0", + "jest-mock": "^25.4.0" }, "devDependencies": { "@types/node": "*" diff --git a/packages/jest-fake-timers/package.json b/packages/jest-fake-timers/package.json index dca478ad1ac4..e3a22a68beb7 100644 --- a/packages/jest-fake-timers/package.json +++ b/packages/jest-fake-timers/package.json @@ -1,6 +1,6 @@ { "name": "@jest/fake-timers", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,10 +17,10 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-mock": "^25.3.0", - "jest-util": "^25.3.0", + "@jest/types": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-mock": "^25.4.0", + "jest-util": "^25.4.0", "lolex": "^5.0.0" }, "devDependencies": { diff --git a/packages/jest-haste-map/package.json b/packages/jest-haste-map/package.json index 418e16f9aa00..8d8db4832b20 100644 --- a/packages/jest-haste-map/package.json +++ b/packages/jest-haste-map/package.json @@ -1,6 +1,6 @@ { "name": "jest-haste-map", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,13 +17,13 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.3", "jest-serializer": "^25.2.6", - "jest-util": "^25.3.0", - "jest-worker": "^25.2.6", + "jest-util": "^25.4.0", + "jest-worker": "^25.4.0", "micromatch": "^4.0.2", "sane": "^4.0.3", "walker": "^1.0.7", diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 5f7c1bdcd015..6a00b3ee56c7 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -1,6 +1,6 @@ { "name": "jest-jasmine2", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,21 +18,21 @@ }, "dependencies": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^25.3.0", + "@jest/environment": "^25.4.0", "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/test-result": "^25.4.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "co": "^4.6.0", - "expect": "^25.3.0", + "expect": "^25.4.0", "is-generator-fn": "^2.0.0", - "jest-each": "^25.3.0", - "jest-matcher-utils": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-runtime": "^25.3.0", - "jest-snapshot": "^25.3.0", - "jest-util": "^25.3.0", - "pretty-format": "^25.3.0", + "jest-each": "^25.4.0", + "jest-matcher-utils": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-runtime": "^25.4.0", + "jest-snapshot": "^25.4.0", + "jest-util": "^25.4.0", + "pretty-format": "^25.4.0", "throat": "^5.0.0" }, "devDependencies": { diff --git a/packages/jest-leak-detector/package.json b/packages/jest-leak-detector/package.json index 6f8faab05595..1cfcbab61a70 100644 --- a/packages/jest-leak-detector/package.json +++ b/packages/jest-leak-detector/package.json @@ -1,6 +1,6 @@ { "name": "jest-leak-detector", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,7 +18,7 @@ }, "dependencies": { "jest-get-type": "^25.2.6", - "pretty-format": "^25.3.0" + "pretty-format": "^25.4.0" }, "devDependencies": { "@types/weak-napi": "^1.0.0", diff --git a/packages/jest-matcher-utils/package.json b/packages/jest-matcher-utils/package.json index 54232319d6ce..d0e896a247f4 100644 --- a/packages/jest-matcher-utils/package.json +++ b/packages/jest-matcher-utils/package.json @@ -1,7 +1,7 @@ { "name": "jest-matcher-utils", "description": "A set of utility functions for expect and related packages", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -22,9 +22,9 @@ }, "dependencies": { "chalk": "^3.0.0", - "jest-diff": "^25.3.0", + "jest-diff": "^25.4.0", "jest-get-type": "^25.2.6", - "pretty-format": "^25.3.0" + "pretty-format": "^25.4.0" }, "devDependencies": { "@jest/test-utils": "^25.3.0", diff --git a/packages/jest-message-util/package.json b/packages/jest-message-util/package.json index 51c2c28b8f43..4f579e9d82da 100644 --- a/packages/jest-message-util/package.json +++ b/packages/jest-message-util/package.json @@ -1,6 +1,6 @@ { "name": "jest-message-util", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -21,7 +21,7 @@ }, "dependencies": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "@types/stack-utils": "^1.0.1", "chalk": "^3.0.0", "micromatch": "^4.0.2", diff --git a/packages/jest-mock/package.json b/packages/jest-mock/package.json index 643937b7c382..294324e7630d 100644 --- a/packages/jest-mock/package.json +++ b/packages/jest-mock/package.json @@ -1,6 +1,6 @@ { "name": "jest-mock", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -10,7 +10,7 @@ "node": ">= 8.3" }, "dependencies": { - "@jest/types": "^25.3.0" + "@jest/types": "^25.4.0" }, "devDependencies": { "@types/node": "*" diff --git a/packages/jest-phabricator/package.json b/packages/jest-phabricator/package.json index 90965d00b5e8..3d0b2297fe44 100644 --- a/packages/jest-phabricator/package.json +++ b/packages/jest-phabricator/package.json @@ -1,6 +1,6 @@ { "name": "jest-phabricator", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -15,7 +15,7 @@ } }, "dependencies": { - "@jest/test-result": "^25.3.0" + "@jest/test-result": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-repl/package.json b/packages/jest-repl/package.json index 25e7e7df5f2a..b93eeb57cfc3 100644 --- a/packages/jest-repl/package.json +++ b/packages/jest-repl/package.json @@ -1,6 +1,6 @@ { "name": "jest-repl", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,11 +17,11 @@ } }, "dependencies": { - "@jest/transform": "^25.3.0", - "@jest/types": "^25.3.0", - "jest-config": "^25.3.0", - "jest-runtime": "^25.3.0", - "jest-validate": "^25.3.0", + "@jest/transform": "^25.4.0", + "@jest/types": "^25.4.0", + "jest-config": "^25.4.0", + "jest-runtime": "^25.4.0", + "jest-validate": "^25.4.0", "repl": "^0.1.3", "yargs": "^15.3.1" }, diff --git a/packages/jest-reporters/package.json b/packages/jest-reporters/package.json index df56ebb1ba8f..d9ca29b2bbb8 100644 --- a/packages/jest-reporters/package.json +++ b/packages/jest-reporters/package.json @@ -1,7 +1,7 @@ { "name": "@jest/reporters", "description": "Jest's reporters", - "version": "25.3.0", + "version": "25.4.0", "main": "build/index.js", "types": "build/index.d.ts", "typesVersions": { @@ -13,10 +13,10 @@ }, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^25.3.0", - "@jest/test-result": "^25.3.0", - "@jest/transform": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/console": "^25.4.0", + "@jest/test-result": "^25.4.0", + "@jest/transform": "^25.4.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", @@ -26,10 +26,10 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^25.3.0", - "jest-resolve": "^25.3.0", - "jest-util": "^25.3.0", - "jest-worker": "^25.2.6", + "jest-haste-map": "^25.4.0", + "jest-resolve": "^25.4.0", + "jest-util": "^25.4.0", + "jest-worker": "^25.4.0", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^3.1.0", diff --git a/packages/jest-resolve-dependencies/package.json b/packages/jest-resolve-dependencies/package.json index d49c92582164..91ff489f1bab 100644 --- a/packages/jest-resolve-dependencies/package.json +++ b/packages/jest-resolve-dependencies/package.json @@ -1,6 +1,6 @@ { "name": "jest-resolve-dependencies", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,14 +17,14 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "jest-regex-util": "^25.2.6", - "jest-snapshot": "^25.3.0" + "jest-snapshot": "^25.4.0" }, "devDependencies": { - "jest-haste-map": "^25.3.0", - "jest-resolve": "^25.3.0", - "jest-runtime": "^25.3.0" + "jest-haste-map": "^25.4.0", + "jest-resolve": "^25.4.0", + "jest-runtime": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index e4056c273d91..822e452b9b57 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -1,6 +1,6 @@ { "name": "jest-resolve", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,7 +17,7 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "browser-resolve": "^1.11.3", "chalk": "^3.0.0", "jest-pnp-resolver": "^1.2.1", @@ -29,7 +29,7 @@ "devDependencies": { "@types/browser-resolve": "^1.11.0", "@types/resolve": "^1.14.0", - "jest-haste-map": "^25.3.0" + "jest-haste-map": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json index a28d896d5686..87c46de216ca 100644 --- a/packages/jest-runner/package.json +++ b/packages/jest-runner/package.json @@ -1,6 +1,6 @@ { "name": "jest-runner", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,23 +17,23 @@ } }, "dependencies": { - "@jest/console": "^25.3.0", - "@jest/environment": "^25.3.0", - "@jest/test-result": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/console": "^25.4.0", + "@jest/environment": "^25.4.0", + "@jest/test-result": "^25.4.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.3", - "jest-config": "^25.3.0", + "jest-config": "^25.4.0", "jest-docblock": "^25.3.0", - "jest-haste-map": "^25.3.0", - "jest-jasmine2": "^25.3.0", - "jest-leak-detector": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-resolve": "^25.3.0", - "jest-runtime": "^25.3.0", - "jest-util": "^25.3.0", - "jest-worker": "^25.2.6", + "jest-haste-map": "^25.4.0", + "jest-jasmine2": "^25.4.0", + "jest-leak-detector": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-resolve": "^25.4.0", + "jest-runtime": "^25.4.0", + "jest-util": "^25.4.0", + "jest-worker": "^25.4.0", "source-map-support": "^0.5.6", "throat": "^5.0.0" }, @@ -42,7 +42,7 @@ "@types/graceful-fs": "^4.1.2", "@types/node": "*", "@types/source-map-support": "^0.5.0", - "jest-circus": "^25.3.0" + "jest-circus": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index bf389a1ef25f..bcbe8cc534c7 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -1,6 +1,6 @@ { "name": "jest-runtime", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,27 +17,27 @@ } }, "dependencies": { - "@jest/console": "^25.3.0", - "@jest/environment": "^25.3.0", + "@jest/console": "^25.4.0", + "@jest/environment": "^25.4.0", "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.3.0", - "@jest/transform": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/test-result": "^25.4.0", + "@jest/transform": "^25.4.0", + "@jest/types": "^25.4.0", "@types/yargs": "^15.0.0", "chalk": "^3.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.3", - "jest-config": "^25.3.0", - "jest-haste-map": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-mock": "^25.3.0", + "jest-config": "^25.4.0", + "jest-haste-map": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-mock": "^25.4.0", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.3.0", - "jest-snapshot": "^25.3.0", - "jest-util": "^25.3.0", - "jest-validate": "^25.3.0", + "jest-resolve": "^25.4.0", + "jest-snapshot": "^25.4.0", + "jest-util": "^25.4.0", + "jest-validate": "^25.4.0", "realpath-native": "^2.0.0", "slash": "^3.0.0", "strip-bom": "^4.0.0", @@ -49,7 +49,7 @@ "@types/glob": "^7.1.1", "@types/graceful-fs": "^4.1.2", "execa": "^3.2.0", - "jest-environment-node": "^25.3.0", + "jest-environment-node": "^25.4.0", "jest-snapshot-serializer-raw": "^1.1.0" }, "bin": "./bin/jest-runtime.js", diff --git a/packages/jest-snapshot/package.json b/packages/jest-snapshot/package.json index 7dade23ce516..7082f7ee0e96 100644 --- a/packages/jest-snapshot/package.json +++ b/packages/jest-snapshot/package.json @@ -1,6 +1,6 @@ { "name": "jest-snapshot", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,18 +18,18 @@ }, "dependencies": { "@babel/types": "^7.0.0", - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "@types/prettier": "^1.19.0", "chalk": "^3.0.0", - "expect": "^25.3.0", - "jest-diff": "^25.3.0", + "expect": "^25.4.0", + "jest-diff": "^25.4.0", "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.3.0", - "jest-message-util": "^25.3.0", - "jest-resolve": "^25.3.0", + "jest-matcher-utils": "^25.4.0", + "jest-message-util": "^25.4.0", + "jest-resolve": "^25.4.0", "make-dir": "^3.0.0", "natural-compare": "^1.4.0", - "pretty-format": "^25.3.0", + "pretty-format": "^25.4.0", "semver": "^6.3.0" }, "devDependencies": { @@ -38,7 +38,7 @@ "@types/semver": "^6.0.1", "ansi-regex": "^5.0.0", "ansi-styles": "^4.2.0", - "jest-haste-map": "^25.3.0", + "jest-haste-map": "^25.4.0", "prettier": "^1.13.4" }, "engines": { diff --git a/packages/jest-test-result/package.json b/packages/jest-test-result/package.json index 5d134ded7850..fba5b4302545 100644 --- a/packages/jest-test-result/package.json +++ b/packages/jest-test-result/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-result", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,8 +17,8 @@ } }, "dependencies": { - "@jest/console": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/console": "^25.4.0", + "@jest/types": "^25.4.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, diff --git a/packages/jest-test-sequencer/package.json b/packages/jest-test-sequencer/package.json index eef6f9a201a5..167fe0758485 100644 --- a/packages/jest-test-sequencer/package.json +++ b/packages/jest-test-sequencer/package.json @@ -1,6 +1,6 @@ { "name": "@jest/test-sequencer", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,10 +17,10 @@ } }, "dependencies": { - "@jest/test-result": "^25.3.0", - "jest-haste-map": "^25.3.0", - "jest-runner": "^25.3.0", - "jest-runtime": "^25.3.0" + "@jest/test-result": "^25.4.0", + "jest-haste-map": "^25.4.0", + "jest-runner": "^25.4.0", + "jest-runtime": "^25.4.0" }, "engines": { "node": ">= 8.3" diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json index d64a6809ed03..d3e250138097 100644 --- a/packages/jest-transform/package.json +++ b/packages/jest-transform/package.json @@ -1,6 +1,6 @@ { "name": "@jest/transform", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -18,15 +18,15 @@ }, "dependencies": { "@babel/core": "^7.1.0", - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "babel-plugin-istanbul": "^6.0.0", "chalk": "^3.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.3", - "jest-haste-map": "^25.3.0", + "jest-haste-map": "^25.4.0", "jest-regex-util": "^25.2.6", - "jest-util": "^25.3.0", + "jest-util": "^25.4.0", "micromatch": "^4.0.2", "pirates": "^4.0.1", "realpath-native": "^2.0.0", diff --git a/packages/jest-types/package.json b/packages/jest-types/package.json index 496567c4a25b..d4f560e9b74c 100644 --- a/packages/jest-types/package.json +++ b/packages/jest-types/package.json @@ -1,6 +1,6 @@ { "name": "@jest/types", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", diff --git a/packages/jest-util/package.json b/packages/jest-util/package.json index ee065c80c263..0123d0e4d56d 100644 --- a/packages/jest-util/package.json +++ b/packages/jest-util/package.json @@ -1,6 +1,6 @@ { "name": "jest-util", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,7 +17,7 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "chalk": "^3.0.0", "is-ci": "^2.0.0", "make-dir": "^3.0.0" diff --git a/packages/jest-validate/package.json b/packages/jest-validate/package.json index 0eac7742571e..6c6b82dcab82 100644 --- a/packages/jest-validate/package.json +++ b/packages/jest-validate/package.json @@ -1,6 +1,6 @@ { "name": "jest-validate", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -17,12 +17,12 @@ } }, "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "camelcase": "^5.3.1", "chalk": "^3.0.0", "jest-get-type": "^25.2.6", "leven": "^3.1.0", - "pretty-format": "^25.3.0" + "pretty-format": "^25.4.0" }, "devDependencies": { "@types/yargs": "^15.0.3" diff --git a/packages/jest-watcher/package.json b/packages/jest-watcher/package.json index d34b8fb22268..c95a55f5eb91 100644 --- a/packages/jest-watcher/package.json +++ b/packages/jest-watcher/package.json @@ -1,7 +1,7 @@ { "name": "jest-watcher", "description": "Delightful JavaScript Testing.", - "version": "25.3.0", + "version": "25.4.0", "main": "build/index.js", "types": "build/index.d.ts", "typesVersions": { @@ -12,11 +12,11 @@ } }, "dependencies": { - "@jest/test-result": "^25.3.0", - "@jest/types": "^25.3.0", + "@jest/test-result": "^25.4.0", + "@jest/types": "^25.4.0", "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", - "jest-util": "^25.3.0", + "jest-util": "^25.4.0", "string-length": "^3.1.0" }, "devDependencies": { diff --git a/packages/jest-worker/package.json b/packages/jest-worker/package.json index d07eca4ed821..ca26e4393389 100644 --- a/packages/jest-worker/package.json +++ b/packages/jest-worker/package.json @@ -1,6 +1,6 @@ { "name": "jest-worker", - "version": "25.2.6", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", diff --git a/packages/jest/package.json b/packages/jest/package.json index 4e263e72cc2a..cafa26011e5d 100644 --- a/packages/jest/package.json +++ b/packages/jest/package.json @@ -1,7 +1,7 @@ { "name": "jest", "description": "Delightful JavaScript Testing.", - "version": "25.3.0", + "version": "25.4.0", "main": "build/jest.js", "types": "build/jest.d.ts", "typesVersions": { @@ -12,9 +12,9 @@ } }, "dependencies": { - "@jest/core": "^25.3.0", + "@jest/core": "^25.4.0", "import-local": "^3.0.2", - "jest-cli": "^25.3.0" + "jest-cli": "^25.4.0" }, "bin": "./bin/jest.js", "engines": { diff --git a/packages/pretty-format/package.json b/packages/pretty-format/package.json index 1c7a3624b2b4..30f154979fdf 100644 --- a/packages/pretty-format/package.json +++ b/packages/pretty-format/package.json @@ -1,6 +1,6 @@ { "name": "pretty-format", - "version": "25.3.0", + "version": "25.4.0", "repository": { "type": "git", "url": "https://github.com/facebook/jest.git", @@ -20,7 +20,7 @@ "browser": "build-es5/index.js", "author": "James Kyle ", "dependencies": { - "@jest/types": "^25.3.0", + "@jest/types": "^25.4.0", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" From 1039ed16d4864645939d985ab1041b6bccb1b2f4 Mon Sep 17 00:00:00 2001 From: Mikhail Bodrov Date: Mon, 20 Apr 2020 08:40:51 +0300 Subject: [PATCH 16/39] [jest-core] minor optimize matching paths (#9844) --- packages/jest-core/src/SearchSource.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/jest-core/src/SearchSource.ts b/packages/jest-core/src/SearchSource.ts index 7a2c6a863cc6..ba70f4ce021d 100644 --- a/packages/jest-core/src/SearchSource.ts +++ b/packages/jest-core/src/SearchSource.ts @@ -272,9 +272,14 @@ export default class SearchSource { const options = {nocase: true, windows: false}; paths = paths - .map(p => path.resolve(this._context.config.cwd, p)) - .map(p => micromatch(allFiles, p.replace(/\\/g, '\\\\'), options)[0]) - .filter(p => p); + .map(p => { + const relativePath = path + .resolve(this._context.config.cwd, p) + .replace(/\\/g, '\\\\'); + const match = micromatch(allFiles, relativePath, options); + return match[0]; + }) + .filter(Boolean); } if (globalConfig.runTestsByPath && paths && paths.length) { From 470ef2d29c576d6a10de344ec25d5a855f02d519 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Mon, 20 Apr 2020 11:00:25 +0300 Subject: [PATCH 17/39] feat(runtime): populate require.cache (#9841) --- CHANGELOG.md | 2 + .../__tests__/runtime_require_cache.test.js | 41 +++++++++++++++++++ packages/jest-runtime/src/index.ts | 18 +++++++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 packages/jest-runtime/src/__tests__/runtime_require_cache.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 839115831aea..de22b98fd823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Features +- `[jest-runtime]` Populate `require.cache` ([#9841](https://github.com/facebook/jest/pull/9841)) + ### Fixes ### Chore & Maintenance diff --git a/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js b/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js new file mode 100644 index 000000000000..ec06833c9d04 --- /dev/null +++ b/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js @@ -0,0 +1,41 @@ +/** + * 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. + * + */ + +'use strict'; + +let createRuntime; + +describe('Runtime require.cache', () => { + beforeEach(() => { + createRuntime = require('createRuntime'); + }); + + it('require.cache returns loaded module list as native Nodejs require does', () => + createRuntime(__filename).then(runtime => { + const regularModule = runtime.requireModule( + runtime.__mockRootPath, + 'RegularModule', + ).module; + + expect(regularModule.require.cache[regularModule.id]).toBe(regularModule); + })); + + it('require.cache is tolerant readonly', () => + createRuntime(__filename).then(runtime => { + const regularModule = runtime.requireModule( + runtime.__mockRootPath, + 'RegularModule', + ).module; + + delete regularModule.require.cache[regularModule.id]; + expect(regularModule.require.cache[regularModule.id]).toBe(regularModule); + + regularModule.require.cache[regularModule.id] = 'something'; + expect(regularModule.require.cache[regularModule.id]).toBe(regularModule); + })); +}); diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 4a7883aa260b..d516e903d1e6 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -80,6 +80,8 @@ type ResolveOptions = Parameters[1]; type BooleanObject = Record; type CacheFS = {[path: string]: string}; +type RequireCache = {[key: string]: Module}; + namespace Runtime { export type Context = JestContext; // ditch this export when moving to esm - for now we need it for to avoid faulty type elision @@ -1270,11 +1272,25 @@ class Runtime { this, from.filename, )) as LocalModuleRequire; - moduleRequire.cache = Object.create(null); moduleRequire.extensions = Object.create(null); moduleRequire.requireActual = this.requireActual.bind(this, from.filename); moduleRequire.requireMock = this.requireMock.bind(this, from.filename); moduleRequire.resolve = resolve; + moduleRequire.cache = (() => { + const notPermittedMethod = () => { + console.warn('`require.cache` modification is not permitted'); + return true; + }; + return new Proxy(Object.create(null), { + defineProperty: notPermittedMethod, + deleteProperty: notPermittedMethod, + get: (_target, key) => + typeof key === 'string' ? this._moduleRegistry.get(key) : undefined, + has: (_target, key) => + typeof key === 'string' && this._moduleRegistry.has(key), + set: notPermittedMethod, + }); + })(); Object.defineProperty(moduleRequire, 'main', { enumerable: true, From 5179604c792299a7e264763003de20f69fe5fa66 Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Mon, 20 Apr 2020 22:38:45 +0300 Subject: [PATCH 18/39] fix(runtime): make require.cache compatible with Object.keys() (#9848) --- .../src/__tests__/runtime_require_cache.test.js | 7 ++++++- packages/jest-runtime/src/index.ts | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js b/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js index ec06833c9d04..aab7ebdea903 100644 --- a/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js +++ b/packages/jest-runtime/src/__tests__/runtime_require_cache.test.js @@ -21,8 +21,13 @@ describe('Runtime require.cache', () => { runtime.__mockRootPath, 'RegularModule', ).module; + const id = regularModule.id; + const cache = regularModule.require.cache; - expect(regularModule.require.cache[regularModule.id]).toBe(regularModule); + expect(cache[id]).toBe(regularModule); + expect(id in cache).toBeTruthy(); + expect(Object.keys(cache).includes(id)).toBeTruthy(); + expect(Object.getOwnPropertyNames(cache).includes(id)).toBeTruthy(); })); it('require.cache is tolerant readonly', () => diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index d516e903d1e6..af6cc31ef0ec 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1286,8 +1286,15 @@ class Runtime { deleteProperty: notPermittedMethod, get: (_target, key) => typeof key === 'string' ? this._moduleRegistry.get(key) : undefined, + getOwnPropertyDescriptor() { + return { + configurable: true, + enumerable: true, + }; + }, has: (_target, key) => typeof key === 'string' && this._moduleRegistry.has(key), + ownKeys: () => Array.from(this._moduleRegistry.keys()), set: notPermittedMethod, }); })(); From 47e956f1686a106e1862587da70b237364d5301e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 20 Apr 2020 23:01:24 +0200 Subject: [PATCH 19/39] fix: support import cjs from mjs (#9850) --- CHANGELOG.md | 4 +- .../__snapshots__/nativeEsm.test.ts.snap | 2 +- e2e/native-esm/__tests__/native-esm.test.js | 5 ++ e2e/native-esm/fromCjs.mjs | 8 +++ packages/jest-resolve/src/shouldLoadAsEsm.ts | 4 +- packages/jest-runtime/src/index.ts | 49 +++++++++---------- 6 files changed, 41 insertions(+), 31 deletions(-) create mode 100644 e2e/native-esm/fromCjs.mjs diff --git a/CHANGELOG.md b/CHANGELOG.md index de22b98fd823..02728ab400e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ### Fixes +- `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) + ### Chore & Maintenance ### Performance @@ -19,8 +21,8 @@ ### Fixes - `[expect]` Restore support for passing functions to `toHaveLength` matcher ([#9796](https://github.com/facebook/jest/pull/9796)) -- `[jest-circus]` Throw on nested test definitions ([#9828](https://github.com/facebook/jest/pull/9828)) - `[jest-changed-files]` `--only-changed` should include staged files ([#9799](https://github.com/facebook/jest/pull/9799)) +- `[jest-circus]` Throw on nested test definitions ([#9828](https://github.com/facebook/jest/pull/9828)) - `[jest-each]` `each` will throw an error when called with too many arguments ([#9818](https://github.com/facebook/jest/pull/9818)) - `[jest-runner]` Don't print warning to stdout when using `--json` ([#9843](https://github.com/facebook/jest/pull/9843)) diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index 14cb786f3ddb..be56a4394e76 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -2,7 +2,7 @@ exports[`on node >=12.16.0 runs test with native ESM 1`] = ` Test Suites: 1 passed, 1 total -Tests: 8 passed, 8 total +Tests: 9 passed, 9 total Snapshots: 0 total Time: <> Ran all test suites. diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index 5a406a9137c7..8f1800e57c12 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -10,6 +10,7 @@ import {createRequire} from 'module'; import {dirname, resolve} from 'path'; import {fileURLToPath} from 'url'; import staticImportedStateful from '../stateful.mjs'; +import staticImportedStatefulFromCjs from '../fromCjs.mjs'; import {double} from '../index'; test('should have correct import.meta', () => { @@ -78,6 +79,10 @@ test('import from mjs and import(mjs) should share caches', async () => { expect(staticImportedStateful()).toBe(6); }); +test('import cjs via import statement', () => { + expect(staticImportedStatefulFromCjs(4)).toBe(2); +}); + test('handle unlinked dynamic imports', async () => { const {double: deepDouble} = await import('../dynamicImport'); diff --git a/e2e/native-esm/fromCjs.mjs b/e2e/native-esm/fromCjs.mjs new file mode 100644 index 000000000000..6f625f8ff51e --- /dev/null +++ b/e2e/native-esm/fromCjs.mjs @@ -0,0 +1,8 @@ +/** + * 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. + */ + +export {default} from './commonjs.cjs'; diff --git a/packages/jest-resolve/src/shouldLoadAsEsm.ts b/packages/jest-resolve/src/shouldLoadAsEsm.ts index ca49e3fdda75..a1938e70d5e6 100644 --- a/packages/jest-resolve/src/shouldLoadAsEsm.ts +++ b/packages/jest-resolve/src/shouldLoadAsEsm.ts @@ -7,11 +7,11 @@ import {dirname, extname} from 'path'; // @ts-ignore: experimental, not added to the types -import {SourceTextModule} from 'vm'; +import {SyntheticModule} from 'vm'; import type {Config} from '@jest/types'; import readPkgUp = require('read-pkg-up'); -const runtimeSupportsVmModules = typeof SourceTextModule === 'function'; +const runtimeSupportsVmModules = typeof SyntheticModule === 'function'; const cachedFileLookups = new Map(); const cachedDirLookups = new Map(); diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index af6cc31ef0ec..001de2f98ec9 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -112,7 +112,7 @@ const EVAL_RESULT_VARIABLE = 'Object.'; type RunScriptEvalResult = {[EVAL_RESULT_VARIABLE]: ModuleWrapper}; -const runtimeSupportsVmModules = typeof SourceTextModule === 'function'; +const runtimeSupportsVmModules = typeof SyntheticModule === 'function'; /* eslint-disable-next-line no-redeclare */ class Runtime { @@ -351,27 +351,7 @@ class Runtime { const module = new SourceTextModule(transformedFile.code, { context, identifier: modulePath, - importModuleDynamically: ( - specifier: string, - referencingModule: VMModule, - ) => { - const resolved = this._resolveModule( - referencingModule.identifier, - specifier, - ); - if ( - this._resolver.isCoreModule(resolved) || - this.unstable_shouldLoadAsEsm(resolved) - ) { - return this.loadEsmModule(resolved); - } - - return this.loadCjsAsEsm( - referencingModule.identifier, - resolved, - context, - ); - }, + importModuleDynamically: this.linkModules.bind(this), initializeImportMeta(meta: ImportMeta) { meta.url = pathToFileURL(modulePath).href; }, @@ -379,11 +359,7 @@ class Runtime { this._esmoduleRegistry.set(cacheKey, module); - await module.link((specifier: string, referencingModule: VMModule) => - this.loadEsmModule( - this._resolveModule(referencingModule.identifier, specifier), - ), - ); + await module.link(this.linkModules.bind(this)); await module.evaluate(); } @@ -395,6 +371,25 @@ class Runtime { return module; } + private async linkModules(specifier: string, referencingModule: VMModule) { + const resolved = this._resolveModule( + referencingModule.identifier, + specifier, + ); + if ( + this._resolver.isCoreModule(resolved) || + this.unstable_shouldLoadAsEsm(resolved) + ) { + return this.loadEsmModule(resolved); + } + + return this.loadCjsAsEsm( + referencingModule.identifier, + resolved, + referencingModule.context, + ); + } + async unstable_importModule( from: Config.Path, moduleName?: string, From 542959c6a371d8fdb29ed2e8eb1d148faf5253f9 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 21 Apr 2020 21:10:45 +0200 Subject: [PATCH 20/39] chore: skip mercurial tests when no hg installed (#9840) --- e2e/Utils.ts | 17 +++++++++++++++++ e2e/__tests__/jestChangedFiles.test.ts | 11 +---------- e2e/__tests__/onlyChanged.test.ts | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/e2e/Utils.ts b/e2e/Utils.ts index 614831acae17..52945c6f1041 100644 --- a/e2e/Utils.ts +++ b/e2e/Utils.ts @@ -14,6 +14,7 @@ import {ExecaReturnValue, sync as spawnSync} from 'execa'; import makeDir = require('make-dir'); import rimraf = require('rimraf'); import dedent = require('dedent'); +import which = require('which'); interface RunResult extends ExecaReturnValue { status: number; @@ -260,3 +261,19 @@ export const normalizeIcons = (str: string) => { .replace(new RegExp('\u00D7', 'g'), '\u2715') .replace(new RegExp('\u221A', 'g'), '\u2713'); }; + +// Certain environments (like CITGM and GH Actions) do not come with mercurial installed +let hgIsInstalled: boolean | null = null; + +export const testIfHg = (...args: Parameters) => { + if (hgIsInstalled === null) { + hgIsInstalled = which.sync('hg', {nothrow: true}) !== null; + } + + if (hgIsInstalled) { + test(...args); + } else { + console.warn('Mercurial (hg) is not installed - skipping some tests'); + test.skip(...args); + } +}; diff --git a/e2e/__tests__/jestChangedFiles.test.ts b/e2e/__tests__/jestChangedFiles.test.ts index 5b8e3014cd7b..480e1d966187 100644 --- a/e2e/__tests__/jestChangedFiles.test.ts +++ b/e2e/__tests__/jestChangedFiles.test.ts @@ -10,8 +10,7 @@ import * as path from 'path'; import {wrap} from 'jest-snapshot-serializer-raw'; import {findRepos, getChangedFilesForRoots} from 'jest-changed-files'; import {skipSuiteOnWindows} from '@jest/test-utils'; -import which = require('which'); -import {cleanup, run, writeFiles} from '../Utils'; +import {cleanup, run, testIfHg, writeFiles} from '../Utils'; import runJest from '../runJest'; skipSuiteOnWindows(); @@ -24,14 +23,6 @@ const HG = 'hg --config ui.username=jest_test'; beforeEach(() => cleanup(DIR)); afterEach(() => cleanup(DIR)); -// Certain environments (like CITGM and GH Actions) do not come with mercurial installed -const hgIsInstalled = which.sync('hg', {nothrow: true}) !== null; -const testIfHg = hgIsInstalled ? test : test.skip; - -if (!hgIsInstalled) { - console.warn('Mercurial (hg) is not installed - skipping some tests'); -} - testIfHg('gets hg SCM roots and dedupes them', async () => { writeFiles(DIR, { 'first-repo/file1.txt': 'file1', diff --git a/e2e/__tests__/onlyChanged.test.ts b/e2e/__tests__/onlyChanged.test.ts index 3a7ff38da596..52abdd6d0613 100644 --- a/e2e/__tests__/onlyChanged.test.ts +++ b/e2e/__tests__/onlyChanged.test.ts @@ -8,7 +8,7 @@ import {tmpdir} from 'os'; import * as path from 'path'; import runJest from '../runJest'; -import {cleanup, run, writeFiles} from '../Utils'; +import {cleanup, run, testIfHg, writeFiles} from '../Utils'; const DIR = path.resolve(tmpdir(), 'jest_only_changed'); const GIT = 'git -c user.name=jest_test -c user.email=jest_test@test.com'; @@ -252,7 +252,7 @@ test('onlyChanged in config is overwritten by --all or testPathPattern', () => { expect(stderr).toMatch(/PASS __tests__(\/|\\)file3.test.js/); }); -test('gets changed files for hg', async () => { +testIfHg('gets changed files for hg', async () => { if (process.env.CI) { // Circle and Travis have very old version of hg (v2, and current // version is v4.2) and its API changed since then and not compatible From fa4cbbf87cb3c97fe44f1fee30663715a9dbba71 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 21 Apr 2020 22:07:22 +0200 Subject: [PATCH 21/39] chore: fix symlink creation failures on windows in tests (#9852) --- e2e/Utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/Utils.ts b/e2e/Utils.ts index 52945c6f1041..f377c53e5916 100644 --- a/e2e/Utils.ts +++ b/e2e/Utils.ts @@ -48,7 +48,7 @@ export const linkJestPackage = (packageName: string, cwd: Config.Path) => { const destination = path.resolve(cwd, 'node_modules/', packageName); makeDir.sync(destination); rimraf.sync(destination); - fs.symlinkSync(packagePath, destination, 'dir'); + fs.symlinkSync(packagePath, destination, 'junction'); }; export const makeTemplate = ( @@ -106,6 +106,7 @@ export const writeSymlinks = ( fs.symlinkSync( path.resolve(directory, ...fileOrPath.split('/')), path.resolve(directory, ...symLinkPath.split('/')), + 'junction', ); }); }; From fc5a6ca863b8db090a1e61e9f1dd39f729e1bbc1 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 22 Apr 2020 10:06:54 +0200 Subject: [PATCH 22/39] chore(runtime): simplify `createJestObjectFor` (#9857) --- .../src/lib/__tests__/dependencyExtractor.test.js | 6 +++--- packages/jest-runtime/src/index.ts | 14 ++++---------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js index 516b5741b598..6ce7e444fae9 100644 --- a/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js +++ b/packages/jest-haste-map/src/lib/__tests__/dependencyExtractor.test.js @@ -232,7 +232,7 @@ describe('dependencyExtractor', () => { "dep2", ); if (jest.requireActual(\`dep3\`).cond) {} - require + jest .requireActual('dep4'); // Bad @@ -252,7 +252,7 @@ describe('dependencyExtractor', () => { "dep2", ); if (jest.requireMock(\`dep3\`).cond) {} - require + jest .requireMock('dep4'); // Bad @@ -272,7 +272,7 @@ describe('dependencyExtractor', () => { "dep2", ); if (jest.genMockFromModule(\`dep3\`).cond) {} - require + jest .requireMock('dep4'); // Bad diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 001de2f98ec9..92a46b78b914 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -990,10 +990,7 @@ class Runtime { dirname, // __dirname filename, // __filename this._environment.global, // global object - this._createJestObjectFor( - filename, - localModule.require as LocalModuleRequire, - ), // jest object + this._createJestObjectFor(filename), // jest object ...this._config.extraGlobals.map(globalVariable => { if (this._environment.global[globalVariable]) { return this._environment.global[globalVariable]; @@ -1311,10 +1308,7 @@ class Runtime { return moduleRequire; } - private _createJestObjectFor( - from: Config.Path, - localRequire: LocalModuleRequire, - ): Jest { + private _createJestObjectFor(from: Config.Path): Jest { const disableAutomock = () => { this._shouldAutoMock = false; return jestObject; @@ -1445,8 +1439,8 @@ class Runtime { isMockFunction: this._moduleMocker.isMockFunction, isolateModules, mock, - requireActual: localRequire.requireActual, - requireMock: localRequire.requireMock, + requireActual: this.requireActual.bind(this, from), + requireMock: this.requireMock.bind(this, from), resetAllMocks, resetModuleRegistry: resetModules, resetModules, From 6a0f070e0210eb11408a7c8ebb003ff73d62e420 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 22 Apr 2020 12:38:15 +0200 Subject: [PATCH 23/39] chore: bump resolve package (#9859) --- packages/jest-resolve/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index 822e452b9b57..ad7c5822dfe2 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -23,7 +23,7 @@ "jest-pnp-resolver": "^1.2.1", "read-pkg-up": "^7.0.1", "realpath-native": "^2.0.0", - "resolve": "^1.15.1", + "resolve": "^1.16.1", "slash": "^3.0.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 5263a63044e8..8f72804d1d06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12708,10 +12708,10 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.0, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.0, resolve@^1.15.1, resolve@^1.16.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: + version "1.16.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" + integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== dependencies: path-parse "^1.0.6" From 7a7710d2c9cdc7da97a3674c36f1ca46f7068f78 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 22 Apr 2020 16:01:43 +0200 Subject: [PATCH 24/39] =?UTF-8?q?feat:=20add=20`@jest/globals`=20package?= =?UTF-8?q?=20for=20importing=20globals=20explici=E2=80=A6=20(#9849)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + docs/GlobalAPI.md | 2 +- docs/JestObjectAPI.md | 2 +- .../__snapshots__/nativeEsm.test.ts.snap | 2 +- e2e/__tests__/importedGlobals.test.ts | 13 ++ e2e/imported-globals/__tests__/env.test.js | 22 ++++ e2e/imported-globals/babel.config.js | 8 ++ e2e/imported-globals/package.json | 5 + e2e/native-esm/__tests__/native-esm.test.js | 5 + packages/jest-globals/.npmignore | 5 + packages/jest-globals/package.json | 30 +++++ packages/jest-globals/src/__tests__/index.ts | 12 ++ packages/jest-globals/src/index.ts | 31 +++++ packages/jest-globals/tsconfig.json | 14 +++ packages/jest-runtime/package.json | 1 + packages/jest-runtime/src/index.ts | 116 ++++++++++++++++-- packages/jest-runtime/tsconfig.json | 1 + 17 files changed, 254 insertions(+), 16 deletions(-) create mode 100644 e2e/__tests__/importedGlobals.test.ts create mode 100644 e2e/imported-globals/__tests__/env.test.js create mode 100644 e2e/imported-globals/babel.config.js create mode 100644 e2e/imported-globals/package.json create mode 100644 packages/jest-globals/.npmignore create mode 100644 packages/jest-globals/package.json create mode 100644 packages/jest-globals/src/__tests__/index.ts create mode 100644 packages/jest-globals/src/index.ts create mode 100644 packages/jest-globals/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 02728ab400e6..09845f3dadb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Features +- `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) - `[jest-runtime]` Populate `require.cache` ([#9841](https://github.com/facebook/jest/pull/9841)) ### Fixes diff --git a/docs/GlobalAPI.md b/docs/GlobalAPI.md index d01f975884b8..bbbc7d526b05 100644 --- a/docs/GlobalAPI.md +++ b/docs/GlobalAPI.md @@ -3,7 +3,7 @@ id: api title: Globals --- -In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them. +In your test files, Jest puts each of these methods and objects into the global environment. You don't have to require or import anything to use them. However, if you prefer explicit imports, you can do `import {describe, expect, it} from '@jest/globals'`. ## Methods diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index 638e16f38550..784c5c3370f1 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -3,7 +3,7 @@ id: jest-object title: The Jest Object --- -The `jest` object is automatically in scope within every test file. The methods in the `jest` object help create mocks and let you control Jest's overall behavior. +The `jest` object is automatically in scope within every test file. The methods in the `jest` object help create mocks and let you control Jest's overall behavior. It can also be imported explicitly by via `import {jest} from '@jest/globals'`. ## Mock Modules diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index be56a4394e76..ca20b5785769 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -2,7 +2,7 @@ exports[`on node >=12.16.0 runs test with native ESM 1`] = ` Test Suites: 1 passed, 1 total -Tests: 9 passed, 9 total +Tests: 10 passed, 10 total Snapshots: 0 total Time: <> Ran all test suites. diff --git a/e2e/__tests__/importedGlobals.test.ts b/e2e/__tests__/importedGlobals.test.ts new file mode 100644 index 000000000000..146ed6544715 --- /dev/null +++ b/e2e/__tests__/importedGlobals.test.ts @@ -0,0 +1,13 @@ +/** + * 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 runJest from '../runJest'; + +test('imported globals', () => { + const result = runJest('imported-globals'); + expect(result.exitCode).toBe(0); +}); diff --git a/e2e/imported-globals/__tests__/env.test.js b/e2e/imported-globals/__tests__/env.test.js new file mode 100644 index 000000000000..e81a1db5a6d5 --- /dev/null +++ b/e2e/imported-globals/__tests__/env.test.js @@ -0,0 +1,22 @@ +/** + * 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 as importedExpect, + jest as importedJest, + test as importedTest, +} from '@jest/globals'; + +importedTest('they match the globals', () => { + importedExpect(importedExpect).toBe(expect); + importedExpect(importedJest).toBe(jest); + importedExpect(importedTest).toBe(test); + + expect(importedExpect).toBe(expect); + expect(importedJest).toBe(jest); + expect(importedTest).toBe(test); +}); diff --git a/e2e/imported-globals/babel.config.js b/e2e/imported-globals/babel.config.js new file mode 100644 index 000000000000..9be036106918 --- /dev/null +++ b/e2e/imported-globals/babel.config.js @@ -0,0 +1,8 @@ +/** + * 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. + */ + +module.exports = require('../../babel.config'); diff --git a/e2e/imported-globals/package.json b/e2e/imported-globals/package.json new file mode 100644 index 000000000000..148788b25446 --- /dev/null +++ b/e2e/imported-globals/package.json @@ -0,0 +1,5 @@ +{ + "jest": { + "testEnvironment": "node" + } +} diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index 8f1800e57c12..6cf48b3811ec 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -9,6 +9,7 @@ import {readFileSync} from 'fs'; import {createRequire} from 'module'; import {dirname, resolve} from 'path'; import {fileURLToPath} from 'url'; +import {jest as jestObject} from '@jest/globals'; import staticImportedStateful from '../stateful.mjs'; import staticImportedStatefulFromCjs from '../fromCjs.mjs'; import {double} from '../index'; @@ -90,3 +91,7 @@ test('handle unlinked dynamic imports', async () => { expect(deepDouble(4)).toBe(8); }); + +test('can import `jest` object', () => { + expect(jestObject).toBeDefined(); +}); diff --git a/packages/jest-globals/.npmignore b/packages/jest-globals/.npmignore new file mode 100644 index 000000000000..3ee5d55b0b89 --- /dev/null +++ b/packages/jest-globals/.npmignore @@ -0,0 +1,5 @@ +**/__mocks__/** +**/__tests__/** +src +tsconfig.json +tsconfig.tsbuildinfo diff --git a/packages/jest-globals/package.json b/packages/jest-globals/package.json new file mode 100644 index 000000000000..c216d3beda23 --- /dev/null +++ b/packages/jest-globals/package.json @@ -0,0 +1,30 @@ +{ + "name": "@jest/globals", + "version": "25.4.0", + "repository": { + "type": "git", + "url": "https://github.com/facebook/jest.git", + "directory": "packages/jest-globals" + }, + "engines": { + "node": ">= 8.3" + }, + "license": "MIT", + "main": "build/index.js", + "types": "build/index.d.ts", + "typesVersions": { + "<3.8": { + "build/*": [ + "build/ts3.4/*" + ] + } + }, + "dependencies": { + "@jest/environment": "^25.4.0", + "@jest/types": "^25.4.0", + "expect": "^25.4.0" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/jest-globals/src/__tests__/index.ts b/packages/jest-globals/src/__tests__/index.ts new file mode 100644 index 000000000000..cb0af7398581 --- /dev/null +++ b/packages/jest-globals/src/__tests__/index.ts @@ -0,0 +1,12 @@ +/** + * 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. + */ + +test('throw when directly imported', () => { + expect(() => require('../')).toThrowError( + 'Do not import `@jest/globals` outside of the Jest test environment', + ); +}); diff --git a/packages/jest-globals/src/index.ts b/packages/jest-globals/src/index.ts new file mode 100644 index 000000000000..82bc15a3b522 --- /dev/null +++ b/packages/jest-globals/src/index.ts @@ -0,0 +1,31 @@ +/** + * 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 importedExpect = require('expect'); +import type {Jest} from '@jest/environment'; +import type {Global} from '@jest/types'; + +export declare type jest = Jest; + +export declare type expect = typeof importedExpect; + +export declare type it = Global.GlobalAdditions['it']; +export declare type test = Global.GlobalAdditions['test']; +export declare type fit = Global.GlobalAdditions['fit']; +export declare type xit = Global.GlobalAdditions['xit']; +export declare type xtest = Global.GlobalAdditions['xtest']; +export declare type describe = Global.GlobalAdditions['describe']; +export declare type xdescribe = Global.GlobalAdditions['xdescribe']; +export declare type fdescribe = Global.GlobalAdditions['fdescribe']; +export declare type beforeAll = Global.GlobalAdditions['beforeAll']; +export declare type beforeEach = Global.GlobalAdditions['beforeEach']; +export declare type afterEach = Global.GlobalAdditions['afterEach']; +export declare type afterAll = Global.GlobalAdditions['afterAll']; + +throw new Error( + 'Do not import `@jest/globals` outside of the Jest test environment', +); diff --git a/packages/jest-globals/tsconfig.json b/packages/jest-globals/tsconfig.json new file mode 100644 index 000000000000..b6678e5f0aed --- /dev/null +++ b/packages/jest-globals/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + // we don't want `@types/jest` to be referenced + "types": ["node"], + "rootDir": "src", + "outDir": "build" + }, + "references": [ + {"path": "../expect"}, + {"path": "../jest-environment"}, + {"path": "../jest-types"} + ] +} diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index bcbe8cc534c7..856194f2d8fc 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -19,6 +19,7 @@ "dependencies": { "@jest/console": "^25.4.0", "@jest/environment": "^25.4.0", + "@jest/globals": "^25.4.0", "@jest/source-map": "^25.2.6", "@jest/test-result": "^25.4.0", "@jest/transform": "^25.4.0", diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 92a46b78b914..39f0cbcb3cc8 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -19,7 +19,7 @@ import { compileFunction, } from 'vm'; import * as nativeModule from 'module'; -import type {Config} from '@jest/types'; +import type {Config, Global} from '@jest/types'; import type { Jest, JestEnvironment, @@ -27,6 +27,7 @@ import type { Module, ModuleWrapper, } from '@jest/environment'; +import type * as JestGlobals from '@jest/globals'; import type {SourceMapRegistry} from '@jest/source-map'; import {formatStackTrace, separateMessageFromStack} from 'jest-message-util'; import {createDirectory, deepCyclicCopy} from 'jest-util'; @@ -52,6 +53,11 @@ import Resolver = require('jest-resolve'); import Snapshot = require('jest-snapshot'); import stripBOM = require('strip-bom'); +interface JestGlobalsValues extends Global.TestFrameworkGlobals { + jest: JestGlobals.jest; + expect: JestGlobals.expect; +} + type HasteMapOptions = { console?: Console; maxWorkers: number; @@ -148,6 +154,7 @@ class Runtime { private _unmockList: RegExp | undefined; private _virtualMocks: BooleanObject; private _moduleImplementation?: typeof nativeModule.Module; + private jestObjectCaches: Map; constructor( config: Config.ProjectConfig, @@ -185,6 +192,7 @@ class Runtime { this._sourceMapRegistry = Object.create(null); this._fileTransforms = new Map(); this._virtualMocks = Object.create(null); + this.jestObjectCaches = new Map(); this._mockMetaDataCache = Object.create(null); this._shouldMockModuleCache = Object.create(null); @@ -317,13 +325,6 @@ class Runtime { modulePath: Config.Path, query = '', ): Promise { - if (modulePath === '@jest/globals') { - // TODO: create a Synthetic Module for this. Will need to create a `jest` object without a `LocalModuleRequire` - throw new Error( - 'Importing `@jest/globals` is not supported from ESM yet', - ); - } - const cacheKey = modulePath + query; if (!this._esmoduleRegistry.has(cacheKey)) { @@ -371,11 +372,27 @@ class Runtime { return module; } - private async linkModules(specifier: string, referencingModule: VMModule) { + private linkModules(specifier: string, referencingModule: VMModule) { + if (specifier === '@jest/globals') { + const fromCache = this._esmoduleRegistry.get('@jest/globals'); + + if (fromCache) { + return fromCache; + } + const globals = this.getGlobalsForEsm( + referencingModule.identifier, + referencingModule.context, + ); + this._esmoduleRegistry.set('@jest/globals', globals); + + return globals; + } + const resolved = this._resolveModule( referencingModule.identifier, specifier, ); + if ( this._resolver.isCoreModule(resolved) || this.unstable_shouldLoadAsEsm(resolved) @@ -649,12 +666,18 @@ class Runtime { }; } - requireModuleOrMock(from: Config.Path, moduleName: string): unknown { + requireModuleOrMock(from: Config.Path, moduleName: string): T { + // this module is unmockable + if (moduleName === '@jest/globals') { + // @ts-ignore: we don't care that it's not assignable to T + return this.getGlobalsForCjs(from); + } + try { if (this._shouldMock(from, moduleName)) { - return this.requireMock(from, moduleName); + return this.requireMock(from, moduleName); } else { - return this.requireModule(from, moduleName); + return this.requireModule(from, moduleName); } } catch (e) { const moduleNotFound = Resolver.tryCastModuleNotFoundError(e); @@ -981,6 +1004,10 @@ class Runtime { return; } + const jestObject = this._createJestObjectFor(filename); + + this.jestObjectCaches.set(filename, jestObject); + try { compiledFunction.call( localModule.exports, @@ -990,7 +1017,7 @@ class Runtime { dirname, // __dirname filename, // __filename this._environment.global, // global object - this._createJestObjectFor(filename), // jest object + jestObject, // jest object ...this._config.extraGlobals.map(globalVariable => { if (this._environment.global[globalVariable]) { return this._environment.global[globalVariable]; @@ -1520,6 +1547,69 @@ class Runtime { throw e; } + + private getGlobalsForCjs(from: Config.Path): JestGlobalsValues { + const jest = this.jestObjectCaches.get(from); + + invariant(jest, 'There should always be a Jest object already'); + + return {...this.getGlobalsFromEnvironment(), jest}; + } + + private async getGlobalsForEsm( + from: Config.Path, + context: VMContext, + ): Promise { + let jest = this.jestObjectCaches.get(from); + + if (!jest) { + jest = this._createJestObjectFor(from); + + this.jestObjectCaches.set(from, jest); + } + + const globals: JestGlobalsValues = { + ...this.getGlobalsFromEnvironment(), + jest, + }; + + const module = new SyntheticModule( + Object.keys(globals), + function () { + Object.entries(globals).forEach(([key, value]) => { + // @ts-ignore: TS doesn't know what `this` is + this.setExport(key, value); + }); + }, + {context, identifier: '@jest/globals'}, + ); + + await module.link(() => { + throw new Error('This should never happen'); + }); + + await module.evaluate(); + + return module; + } + + private getGlobalsFromEnvironment(): Omit { + return { + afterAll: this._environment.global.afterAll, + afterEach: this._environment.global.afterEach, + beforeAll: this._environment.global.beforeAll, + beforeEach: this._environment.global.beforeEach, + describe: this._environment.global.describe, + expect: this._environment.global.expect, + fdescribe: this._environment.global.fdescribe, + fit: this._environment.global.fit, + it: this._environment.global.it, + test: this._environment.global.test, + xdescribe: this._environment.global.xdescribe, + xit: this._environment.global.xit, + xtest: this._environment.global.xtest, + }; + } } function invariant(condition: unknown, message?: string): asserts condition { diff --git a/packages/jest-runtime/tsconfig.json b/packages/jest-runtime/tsconfig.json index 08abc7a9ddfc..2955d779d6b1 100644 --- a/packages/jest-runtime/tsconfig.json +++ b/packages/jest-runtime/tsconfig.json @@ -9,6 +9,7 @@ {"path": "../jest-console"}, {"path": "../jest-environment"}, {"path": "../jest-environment-node"}, + {"path": "../jest-globals"}, {"path": "../jest-haste-map"}, {"path": "../jest-message-util"}, {"path": "../jest-mock"}, From e7ff5b4713d971064d14af0403f349f9770da61d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 22 Apr 2020 16:55:45 +0200 Subject: [PATCH 25/39] chore: run CI on Node 14 (#9861) --- .github/workflows/nodejs.yml | 2 +- .../__snapshots__/nativeEsm.test.ts.snap | 2 +- e2e/__tests__/nativeEsm.test.ts | 2 +- .../jest-cli/src/init/__tests__/init.test.js | 19 ++++++++----------- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index e7da849d85fe..78c1927a0e6f 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -57,7 +57,7 @@ jobs: fail-fast: false matrix: # https://github.com/actions/setup-node/issues/27 - node-version: [8.17.0, 10.x, 12.x, 13.x] + node-version: [8.17.0, 10.x, 12.x, 13.x, 14.x] os: [ubuntu-latest, macOS-latest, windows-latest] runs-on: ${{ matrix.os }} diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index ca20b5785769..174a63b361ea 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`on node >=12.16.0 runs test with native ESM 1`] = ` +exports[`on node ^12.16.0 || >=13.2.0 runs test with native ESM 1`] = ` Test Suites: 1 passed, 1 total Tests: 10 passed, 10 total Snapshots: 0 total diff --git a/e2e/__tests__/nativeEsm.test.ts b/e2e/__tests__/nativeEsm.test.ts index 405547a39743..e8addfb934f3 100644 --- a/e2e/__tests__/nativeEsm.test.ts +++ b/e2e/__tests__/nativeEsm.test.ts @@ -21,7 +21,7 @@ test('test config is without transform', () => { }); // The versions vm.Module was introduced -onNodeVersions('>=12.16.0', () => { +onNodeVersions('^12.16.0 || >=13.2.0', () => { test('runs test with native ESM', () => { const {exitCode, stderr, stdout} = runJest(DIR, [], { nodeOptions: '--experimental-vm-modules', diff --git a/packages/jest-cli/src/init/__tests__/init.test.js b/packages/jest-cli/src/init/__tests__/init.test.js index afc2acdca315..874a6d958c75 100644 --- a/packages/jest-cli/src/init/__tests__/init.test.js +++ b/packages/jest-cli/src/init/__tests__/init.test.js @@ -11,7 +11,6 @@ import * as path from 'path'; import prompts from 'prompts'; import {constants} from 'jest-config'; import init from '../'; -import {onNodeVersions} from '@jest/test-utils'; const {JEST_CONFIG_EXT_ORDER} = constants; @@ -56,20 +55,18 @@ describe('init', () => { expect(evaluatedConfig).toEqual({}); }); - onNodeVersions('^13.2.0', () => { - it('should generate empty config with mjs extension', async () => { - prompts.mockReturnValueOnce({}); + it('should generate empty config with mjs extension', async () => { + prompts.mockReturnValueOnce({}); - await init(resolveFromFixture('type_module')); + await init(resolveFromFixture('type_module')); - const writtenJestConfigFilename = fs.writeFileSync.mock.calls[0][0]; - const writtenJestConfig = fs.writeFileSync.mock.calls[0][1]; + const writtenJestConfigFilename = fs.writeFileSync.mock.calls[0][0]; + const writtenJestConfig = fs.writeFileSync.mock.calls[0][1]; - expect(writtenJestConfigFilename.endsWith('.mjs')).toBe(true); + expect(writtenJestConfigFilename.endsWith('.mjs')).toBe(true); - expect(typeof writtenJestConfig).toBe('string'); - expect(writtenJestConfig.split('\n')[3]).toBe('export default {'); - }); + expect(typeof writtenJestConfig).toBe('string'); + expect(writtenJestConfig.split('\n')[3]).toBe('export default {'); }); }); From 32aaff83f02c347ccd591727544002490fb4ee9a Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 22 Apr 2020 16:56:37 +0200 Subject: [PATCH 26/39] fix(esm): handle parallel imports (#9858) --- CHANGELOG.md | 1 + .../__snapshots__/nativeEsm.test.ts.snap | 2 +- e2e/native-esm/__tests__/native-esm.test.js | 10 ++++++++++ e2e/native-esm/anotherDynamicImport.js | 8 ++++++++ packages/jest-runtime/src/index.ts | 17 +++++++++++------ 5 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 e2e/native-esm/anotherDynamicImport.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 09845f3dadb5..7f1165f46273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixes - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) +- `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) ### Chore & Maintenance diff --git a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap index 174a63b361ea..c16d98c7fafb 100644 --- a/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap +++ b/e2e/__tests__/__snapshots__/nativeEsm.test.ts.snap @@ -2,7 +2,7 @@ exports[`on node ^12.16.0 || >=13.2.0 runs test with native ESM 1`] = ` Test Suites: 1 passed, 1 total -Tests: 10 passed, 10 total +Tests: 11 passed, 11 total Snapshots: 0 total Time: <> Ran all test suites. diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index 6cf48b3811ec..05dc9e5fc328 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -95,3 +95,13 @@ test('handle unlinked dynamic imports', async () => { test('can import `jest` object', () => { expect(jestObject).toBeDefined(); }); + +test('handle dynamic imports of the same module in parallel', async () => { + const [{double: first}, {double: second}] = await Promise.all([ + import('../anotherDynamicImport.js'), + import('../anotherDynamicImport.js'), + ]); + + expect(first).toBe(second); + expect(first(2)).toBe(4); +}); diff --git a/e2e/native-esm/anotherDynamicImport.js b/e2e/native-esm/anotherDynamicImport.js new file mode 100644 index 000000000000..84b87a513c85 --- /dev/null +++ b/e2e/native-esm/anotherDynamicImport.js @@ -0,0 +1,8 @@ +/** + * 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. + */ + +export * from './index'; diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 39f0cbcb3cc8..33df2ba5dbe6 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -139,7 +139,7 @@ class Runtime { private _moduleMocker: typeof jestMock; private _isolatedModuleRegistry: ModuleRegistry | null; private _moduleRegistry: ModuleRegistry; - private _esmoduleRegistry: Map; + private _esmoduleRegistry: Map>; private _needsCoverageMapped: Set; private _resolver: Resolver; private _shouldAutoMock: boolean; @@ -358,11 +358,16 @@ class Runtime { }, }); - this._esmoduleRegistry.set(cacheKey, module); - - await module.link(this.linkModules.bind(this)); - - await module.evaluate(); + this._esmoduleRegistry.set( + cacheKey, + // we wanna put the linking promise in the cache so modules loaded in + // parallel can all await it. We then await it synchronously below, so + // we shouldn't get any unhandled rejections + module + .link(this.linkModules.bind(this)) + .then(() => module.evaluate()) + .then(() => module), + ); } const module = this._esmoduleRegistry.get(cacheKey); From 554e1ac96a71d2459100a42d46ec81409e191e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 22 Apr 2020 23:30:12 +0200 Subject: [PATCH 27/39] Add an option to vscode settings to always use workspace TS (#9869) --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0478de9c2561..0dcce386c953 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,6 @@ "jest.pathToJest": "yarn jest --", "editor.codeActionsOnSave": { "source.fixAll.eslint": true - } + }, + "typescript.tsdk": "node_modules/typescript/lib" } From a154014ca45d47c3b707d21091fac4c2d33a82d2 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 10:53:39 +0200 Subject: [PATCH 28/39] chore: run CircleCI on node 14 (#9870) --- .circleci/config.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 33113f6c43b2..fcee3ee8e014 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,6 +90,20 @@ jobs: - store_test_results: path: reports/junit + test-node-14: + working_directory: ~/jest + docker: + - image: circleci/node:14 + steps: + - checkout + - restore-cache: *restore-cache + - run: *install + - save-cache: *save-cache + - run: + command: yarn test-ci-partial + - store_test_results: + path: reports/junit + test-browser: working_directory: ~/jest docker: @@ -123,7 +137,8 @@ workflows: - test-node-8 - test-node-10 - test-node-12 - - test-node-13 # current + - test-node-13 + - test-node-14 # current - test-jest-circus - test-browser - test-or-deploy-website: From 9443889a945182e9dee592f4473289d664c6cee0 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 10:54:38 +0200 Subject: [PATCH 29/39] chore: update resolve (#9872) --- CHANGELOG.md | 2 + packages/jest-resolve/package.json | 2 +- packages/jest-resolve/src/defaultResolver.ts | 39 +++++++++++++------- yarn.lock | 8 ++-- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f1165f46273..ec36a2f6f407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ ### Performance +- `[jest-resolve]` Update `resolve` to a version using native `realpath`, which is faster than the default JS implementation ([#9872](https://github.com/facebook/jest/pull/9872)) + ## 25.4.0 - `[expect]` Support `async function`s in `toThrow` ([#9817](https://github.com/facebook/jest/pull/9817)) diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index ad7c5822dfe2..7dc336af75c3 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -23,7 +23,7 @@ "jest-pnp-resolver": "^1.2.1", "read-pkg-up": "^7.0.1", "realpath-native": "^2.0.0", - "resolve": "^1.16.1", + "resolve": "^1.17.0", "slash": "^3.0.0" }, "devDependencies": { diff --git a/packages/jest-resolve/src/defaultResolver.ts b/packages/jest-resolve/src/defaultResolver.ts index 4e990f8b65c1..2481a8c606c4 100644 --- a/packages/jest-resolve/src/defaultResolver.ts +++ b/packages/jest-resolve/src/defaultResolver.ts @@ -41,21 +41,13 @@ export default function defaultResolver( moduleDirectory: options.moduleDirectory, paths: options.paths, preserveSymlinks: false, + // @ts-ignore: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/44137 + realpathSync, }); - try { - // Dereference symlinks to ensure we don't create a separate - // module instance depending on how it was referenced. - const resolved = realpath(result); - - if (resolved) { - return resolved; - } - } catch { - // ignore - } - - return result; + // Dereference symlinks to ensure we don't create a separate + // module instance depending on how it was referenced. + return realpathSync(result); } export function clearDefaultResolverCache(): void { @@ -97,6 +89,23 @@ function statSyncCached(path: string): IPathType { return IPathType.OTHER; } +function tolerantRealpath(path: Config.Path): Config.Path { + let result: Config.Path | undefined = undefined; + try { + result = realpath(path); + } catch (error) { + if (error.code !== 'ENOENT') { + throw error; + } + } + + if (!result) { + result = path; + } + + return result; +} + /* * helper functions */ @@ -107,3 +116,7 @@ function isFile(file: Config.Path): boolean { function isDirectory(dir: Config.Path): boolean { return statSyncCached(dir) === IPathType.DIRECTORY; } + +function realpathSync(file: Config.Path): Config.Path { + return tolerantRealpath(file); +} diff --git a/yarn.lock b/yarn.lock index 8f72804d1d06..5cdbc006208c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12708,10 +12708,10 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.0, resolve@^1.15.1, resolve@^1.16.1, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.16.1.tgz#49fac5d8bacf1fd53f200fa51247ae736175832c" - integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.0, resolve@^1.15.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" From 1e2ac3048ded6d5092d1884ecb6617f711d8a04e Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 11:47:10 +0200 Subject: [PATCH 30/39] chore: mock stealthy-require in tests (#9855) --- packages/jest-runtime/src/index.ts | 9 ++++++++- testSetupFile.js | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 33df2ba5dbe6..8df6447e8b00 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -155,6 +155,7 @@ class Runtime { private _virtualMocks: BooleanObject; private _moduleImplementation?: typeof nativeModule.Module; private jestObjectCaches: Map; + private _hasWarnedAboutRequireCacheModification = false; constructor( config: Config.ProjectConfig, @@ -1302,7 +1303,13 @@ class Runtime { moduleRequire.resolve = resolve; moduleRequire.cache = (() => { const notPermittedMethod = () => { - console.warn('`require.cache` modification is not permitted'); + if (!this._hasWarnedAboutRequireCacheModification) { + this._environment.global.console.warn( + '`require.cache` modification is not permitted', + ); + + this._hasWarnedAboutRequireCacheModification = true; + } return true; }; return new Proxy(Object.create(null), { diff --git a/testSetupFile.js b/testSetupFile.js index ef9ed18680f6..7f73aec1ef96 100644 --- a/testSetupFile.js +++ b/testSetupFile.js @@ -8,3 +8,6 @@ // Some of the `jest-runtime` tests are very slow and cause // timeouts on travis jest.setTimeout(70000); + +// this module does some funky stuff with `require.cache`, flooding the terminal with output +jest.mock('stealthy-require', () => (_, m) => m()); From bc1c6841f536bc17f1287ca0e54f0b4ec38b00c5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 17:40:12 +0200 Subject: [PATCH 31/39] fix: pass custom cached realpath function to `resolve` (#9873) --- CHANGELOG.md | 1 + packages/jest-resolve/src/defaultResolver.ts | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec36a2f6f407..9be830431972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ### Performance - `[jest-resolve]` Update `resolve` to a version using native `realpath`, which is faster than the default JS implementation ([#9872](https://github.com/facebook/jest/pull/9872)) +- `[jest-resolve]` Pass custom cached `realpath` function to `resolve` ([#9873](https://github.com/facebook/jest/pull/9873)) ## 25.4.0 diff --git a/packages/jest-resolve/src/defaultResolver.ts b/packages/jest-resolve/src/defaultResolver.ts index 2481a8c606c4..0e20699364ba 100644 --- a/packages/jest-resolve/src/defaultResolver.ts +++ b/packages/jest-resolve/src/defaultResolver.ts @@ -52,6 +52,7 @@ export default function defaultResolver( export function clearDefaultResolverCache(): void { checkedPaths.clear(); + checkedRealpathPaths.clear(); } enum IPathType { @@ -89,8 +90,14 @@ function statSyncCached(path: string): IPathType { return IPathType.OTHER; } -function tolerantRealpath(path: Config.Path): Config.Path { - let result: Config.Path | undefined = undefined; +const checkedRealpathPaths = new Map(); +function realpathCached(path: Config.Path): Config.Path { + let result = checkedRealpathPaths.get(path); + + if (result !== undefined) { + return result; + } + try { result = realpath(path); } catch (error) { @@ -103,6 +110,13 @@ function tolerantRealpath(path: Config.Path): Config.Path { result = path; } + checkedRealpathPaths.set(path, result); + + if (path !== result) { + // also cache the result in case it's ever referenced directly - no reason to `realpath` that as well + checkedRealpathPaths.set(result, result); + } + return result; } @@ -118,5 +132,5 @@ function isDirectory(dir: Config.Path): boolean { } function realpathSync(file: Config.Path): Config.Path { - return tolerantRealpath(file); + return realpathCached(file); } From 1c2011dbce785ba05f006d1f6636dc378daa7329 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 20:19:29 +0200 Subject: [PATCH 32/39] chore: verify all packages have the same engine requirement (#9871) --- .eslintrc.js | 2 +- babel.config.js | 11 ++++-- e2e/__tests__/__snapshots__/each.test.ts.snap | 20 +++++----- .../errorOnDeprecated.test.ts.snap | 2 +- .../expectAsyncMatcher.test.ts.snap | 2 +- .../toMatchInlineSnapshot.test.ts.snap | 14 +++---- ...owErrorMatchingInlineSnapshot.test.ts.snap | 2 +- e2e/coverage-handlebars/__tests__/greet.js | 2 +- e2e/coverage-report/notRequiredInTestSuite.js | 2 +- .../testSequencerAsync.js | 2 +- e2e/each/__tests__/describeOnly.test.js | 2 +- e2e/each/__tests__/eachException.test.js | 4 +- e2e/each/__tests__/eachOnly.test.js | 2 +- e2e/each/__tests__/eachSkip.test.js | 2 +- e2e/each/__tests__/failure.test.js | 10 ++--- e2e/each/__tests__/success.test.js | 2 +- .../jasmine.objectContaining.test.js | 2 +- .../__tests__/failure.test.js | 2 +- .../__tests__/success.test.js | 2 +- e2e/expect-async-matcher/matchers.js | 2 +- .../__tests__/expect-in-vm.test.js | 4 +- .../__tests__/promiseBeforeAll.test.js | 2 +- .../__tests__/promiseBeforeEach.test.js | 2 +- e2e/jasmine-async/__tests__/promiseIt.test.js | 6 +-- e2e/native-esm/__tests__/native-esm.test.js | 2 +- .../__tests__/resetModules.test.js | 2 +- .../__tests__/resolveWithPaths.test.js | 10 ++--- e2e/resolve/__tests__/resolve.test.js | 6 +-- e2e/snapshot/__tests__/snapshot.test.js | 2 +- .../typescriptPreprocessor.js | 2 +- examples/angular/app.component.spec.ts | 4 +- examples/angular/setupJest.js | 2 +- examples/async/__mocks__/request.js | 2 +- examples/async/__tests__/user.test.js | 2 +- .../__tests__/file_summarizer.test.js | 2 +- examples/react-native/__tests__/intro.test.js | 2 +- .../__tests__/CheckboxWithLabel-test.js | 2 +- .../react/__tests__/CheckboxWithLabel-test.js | 2 +- .../snapshot/__tests__/link.react.test.js | 2 +- .../__tests__/CheckboxWithLabel-test.tsx | 2 +- package.json | 17 +------- packages/test-utils/package.json | 3 ++ scripts/babel-plugin-jest-native-globals.js | 2 +- ...ugin-jest-replace-ts-require-assignment.js | 2 +- scripts/browserBuild.js | 4 +- scripts/build.js | 10 ++--- scripts/buildTs.js | 39 +++++++++---------- scripts/buildUtils.js | 22 ++++++++++- scripts/checkCopyrightHeaders.js | 2 +- scripts/mapCoverage.js | 6 +-- scripts/verifyOldTs.js | 6 +-- scripts/watch.js | 10 ++--- 52 files changed, 143 insertions(+), 129 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 075a0c763dfd..49eafb955758 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -132,7 +132,7 @@ module.exports = { '**/__mocks__/**', '**/?(*.)(spec|test).js?(x)', 'scripts/**', - 'eslintImportResolver.js', + 'babel.config.js', 'testSetupFile.js', ], }, diff --git a/babel.config.js b/babel.config.js index f062b0d8739f..b01524bb0f50 100644 --- a/babel.config.js +++ b/babel.config.js @@ -5,6 +5,11 @@ * LICENSE file in the root directory of this source tree. */ +const semver = require('semver'); +const pkg = require('./package.json'); + +const supportedNodeVersion = semver.minVersion(pkg.engines.node).version; + module.exports = { babelrcRoots: ['examples/*'], // we don't wanna run the transforms in this file over react native @@ -15,7 +20,7 @@ module.exports = { 'babel-plugin-typescript-strip-namespaces', 'babel-plugin-replace-ts-export-assignment', require.resolve( - './scripts/babel-plugin-jest-replace-ts-require-assignment.js' + './scripts/babel-plugin-jest-replace-ts-require-assignment.js', ), ], presets: ['@babel/preset-typescript'], @@ -31,7 +36,7 @@ module.exports = { { exclude: ['@babel/plugin-proposal-dynamic-import'], shippedProposals: true, - targets: {node: '8.3'}, + targets: {node: supportedNodeVersion}, }, ], ], @@ -48,7 +53,7 @@ module.exports = { '@babel/preset-env', { shippedProposals: true, - targets: {node: '8.3'}, + targets: {node: supportedNodeVersion}, }, ], ], diff --git a/e2e/__tests__/__snapshots__/each.test.ts.snap b/e2e/__tests__/__snapshots__/each.test.ts.snap index 188a2727b2b9..98edb0ecb406 100644 --- a/e2e/__tests__/__snapshots__/each.test.ts.snap +++ b/e2e/__tests__/__snapshots__/each.test.ts.snap @@ -205,7 +205,7 @@ FAIL __tests__/failure.test.js 28 | ({left, right}) => { > 29 | expect(left).toBe(right); | ^ - 30 | } + 30 | }, 31 | ); 32 | @@ -222,7 +222,7 @@ FAIL __tests__/failure.test.js 39 | ({left, right}) => { > 40 | expect(left).toBe(right); | ^ - 41 | } + 41 | }, 42 | ); 43 | @@ -239,7 +239,7 @@ FAIL __tests__/failure.test.js 39 | ({left, right}) => { > 40 | expect(left).toBe(right); | ^ - 41 | } + 41 | }, 42 | ); 43 | @@ -256,7 +256,7 @@ FAIL __tests__/failure.test.js 46 | word => { > 47 | expect(/z/.test(word)).toBe(true); | ^ - 48 | } + 48 | }, 49 | ); 50 | @@ -273,7 +273,7 @@ FAIL __tests__/failure.test.js 46 | word => { > 47 | expect(/z/.test(word)).toBe(true); | ^ - 48 | } + 48 | }, 49 | ); 50 | @@ -290,7 +290,7 @@ FAIL __tests__/failure.test.js 46 | word => { > 47 | expect(/z/.test(word)).toBe(true); | ^ - 48 | } + 48 | }, 49 | ); 50 | @@ -308,7 +308,7 @@ FAIL __tests__/failure.test.js > 59 | expect(left).toBe(right); | ^ 60 | }); - 61 | } + 61 | }, 62 | ); at Object.toBe (__tests__/failure.test.js:59:20) @@ -325,7 +325,7 @@ FAIL __tests__/failure.test.js > 59 | expect(left).toBe(right); | ^ 60 | }); - 61 | } + 61 | }, 62 | ); at Object.toBe (__tests__/failure.test.js:59:20) @@ -342,7 +342,7 @@ FAIL __tests__/failure.test.js > 71 | expect(left).toBe(right); | ^ 72 | }); - 73 | } + 73 | }, 74 | ); at Object.toBe (__tests__/failure.test.js:71:20) @@ -359,7 +359,7 @@ FAIL __tests__/failure.test.js > 71 | expect(left).toBe(right); | ^ 72 | }); - 73 | } + 73 | }, 74 | ); at Object.toBe (__tests__/failure.test.js:71:20) diff --git a/e2e/__tests__/__snapshots__/errorOnDeprecated.test.ts.snap b/e2e/__tests__/__snapshots__/errorOnDeprecated.test.ts.snap index 613a80ca77b8..ab3b25ed0f25 100644 --- a/e2e/__tests__/__snapshots__/errorOnDeprecated.test.ts.snap +++ b/e2e/__tests__/__snapshots__/errorOnDeprecated.test.ts.snap @@ -138,7 +138,7 @@ FAIL __tests__/jasmine.objectContaining.test.js 9 | test('jasmine.objectContaining', () => { 10 | expect({input: 'trash', output: 'trash'}).toEqual( - > 11 | jasmine.objectContaining({output: 'trash'}) + > 11 | jasmine.objectContaining({output: 'trash'}), | ^ 12 | ); 13 | }); diff --git a/e2e/__tests__/__snapshots__/expectAsyncMatcher.test.ts.snap b/e2e/__tests__/__snapshots__/expectAsyncMatcher.test.ts.snap index b7d07fa98db9..0c2dd06fe47c 100644 --- a/e2e/__tests__/__snapshots__/expectAsyncMatcher.test.ts.snap +++ b/e2e/__tests__/__snapshots__/expectAsyncMatcher.test.ts.snap @@ -77,7 +77,7 @@ FAIL __tests__/failure.test.js 21 | it('fail with expected promise values and not', () => > 22 | expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync( | ^ - 23 | Promise.resolve(2) + 23 | Promise.resolve(2), 24 | )); 25 | diff --git a/e2e/__tests__/__snapshots__/toMatchInlineSnapshot.test.ts.snap b/e2e/__tests__/__snapshots__/toMatchInlineSnapshot.test.ts.snap index 1abfcc0e03ad..a64fb6a82fde 100644 --- a/e2e/__tests__/__snapshots__/toMatchInlineSnapshot.test.ts.snap +++ b/e2e/__tests__/__snapshots__/toMatchInlineSnapshot.test.ts.snap @@ -71,7 +71,7 @@ test('handles property matchers', () => { Object { "createdAt": Any, } - \` + \`, ); }); @@ -85,7 +85,7 @@ expect({createdAt: "string"}).toMatchInlineSnapshot( Object { "createdAt": Any, } -\` +\`, ); }); `; @@ -98,7 +98,7 @@ test('handles property matchers', () => { Object { "createdAt": Any, } - \` + \`, ); }); @@ -112,7 +112,7 @@ test('handles property matchers', () => { Object { "createdAt": Any, } - \` + \`, ); }); @@ -192,7 +192,7 @@ test('removes obsolete external snapshots', () => { exports[`supports async matchers 1`] = ` test('inline snapshots', async () => { expect(Promise.resolve('success')).resolves.toMatchInlineSnapshot( - \`"success"\` + \`"success"\`, ); expect(Promise.reject('fail')).rejects.toMatchInlineSnapshot(\`"fail"\`); }); @@ -221,7 +221,7 @@ expect.extend({ createdAt: expect.any(Date), id: expect.any(Number), }, - ...args + ...args, ); }, }); @@ -242,7 +242,7 @@ test('inline snapshots', () => { "id": Any, "name": "LeBron James", } - \` + \`, ); expect(user).toMatchUserInlineSnapshot(\` Object { diff --git a/e2e/__tests__/__snapshots__/toThrowErrorMatchingInlineSnapshot.test.ts.snap b/e2e/__tests__/__snapshots__/toThrowErrorMatchingInlineSnapshot.test.ts.snap index eb1a037f29aa..7e68215ed3f3 100644 --- a/e2e/__tests__/__snapshots__/toThrowErrorMatchingInlineSnapshot.test.ts.snap +++ b/e2e/__tests__/__snapshots__/toThrowErrorMatchingInlineSnapshot.test.ts.snap @@ -3,7 +3,7 @@ exports[`should support rejecting promises 1`] = ` test('should support rejecting promises', async () => { await expect( - Promise.reject(new Error('octopus')) + Promise.reject(new Error('octopus')), ).rejects.toThrowErrorMatchingInlineSnapshot(\`"octopus"\`); }); diff --git a/e2e/coverage-handlebars/__tests__/greet.js b/e2e/coverage-handlebars/__tests__/greet.js index f5775645112e..ac8485e7e7a2 100644 --- a/e2e/coverage-handlebars/__tests__/greet.js +++ b/e2e/coverage-handlebars/__tests__/greet.js @@ -8,6 +8,6 @@ const greet = require('../greet.hbs'); test('am', () => { expect(greet({am: true, name: 'Joe'})).toEqual( - '

Good\n morning\nJoe!

\n' + '

Good\n morning\nJoe!

\n', ); }); diff --git a/e2e/coverage-report/notRequiredInTestSuite.js b/e2e/coverage-report/notRequiredInTestSuite.js index 8bbc209edb50..7d3ca5a4b994 100644 --- a/e2e/coverage-report/notRequiredInTestSuite.js +++ b/e2e/coverage-report/notRequiredInTestSuite.js @@ -7,7 +7,7 @@ throw new Error( `this error should not be a problem because` + - `this file is never required or executed` + `this file is never required or executed`, ); // Flow annotations to make sure istanbul can instrument non ES6 source diff --git a/e2e/custom-test-sequencer/testSequencerAsync.js b/e2e/custom-test-sequencer/testSequencerAsync.js index cf379c64752d..15b562b85d8d 100644 --- a/e2e/custom-test-sequencer/testSequencerAsync.js +++ b/e2e/custom-test-sequencer/testSequencerAsync.js @@ -13,7 +13,7 @@ class CustomSequencer extends Sequencer { setTimeout(() => { const copyTests = Array.from(tests); resolve( - copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1)) + copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1)), ); }, 50); }); diff --git a/e2e/each/__tests__/describeOnly.test.js b/e2e/each/__tests__/describeOnly.test.js index 854ecd89d8b3..577c4e25bdcb 100644 --- a/e2e/each/__tests__/describeOnly.test.js +++ b/e2e/each/__tests__/describeOnly.test.js @@ -23,5 +23,5 @@ describe.each([[false, true]])( it('fails', () => { expect(left).toBe(right); }); - } + }, ); diff --git a/e2e/each/__tests__/eachException.test.js b/e2e/each/__tests__/eachException.test.js index 4e017576ac68..1cb350067c4e 100644 --- a/e2e/each/__tests__/eachException.test.js +++ b/e2e/each/__tests__/eachException.test.js @@ -13,7 +13,7 @@ it.each` 'throws exception when one argument too few are supplied $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); it.each` @@ -23,5 +23,5 @@ it.each` 'throws exception when not enough arguments are supplied $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); diff --git a/e2e/each/__tests__/eachOnly.test.js b/e2e/each/__tests__/eachOnly.test.js index 9be757e5b1ab..ea6a8cf19d18 100644 --- a/e2e/each/__tests__/eachOnly.test.js +++ b/e2e/each/__tests__/eachOnly.test.js @@ -37,5 +37,5 @@ it.each` 'Should not be ran: fails all rows expected $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); diff --git a/e2e/each/__tests__/eachSkip.test.js b/e2e/each/__tests__/eachSkip.test.js index 3ca62df48835..fa4f7ed1cac7 100644 --- a/e2e/each/__tests__/eachSkip.test.js +++ b/e2e/each/__tests__/eachSkip.test.js @@ -35,7 +35,7 @@ it.skip.each` 'Should not be ran: fails all rows expected $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); describe.skip.each([ diff --git a/e2e/each/__tests__/failure.test.js b/e2e/each/__tests__/failure.test.js index 7175885bb7ad..ee25783ee553 100644 --- a/e2e/each/__tests__/failure.test.js +++ b/e2e/each/__tests__/failure.test.js @@ -27,7 +27,7 @@ it.each` 'template table fails on one row expected: $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); it.each` @@ -38,14 +38,14 @@ it.each` 'template table fails on all rows expected: $left == $right', ({left, right}) => { expect(left).toBe(right); - } + }, ); test.each(['red', 'green', 'bean'])( "The word %s contains the letter 'z'", word => { expect(/z/.test(word)).toBe(true); - } + }, ); describe.each` @@ -58,7 +58,7 @@ describe.each` it('fails ', () => { expect(left).toBe(right); }); - } + }, ); describe.each([ @@ -70,5 +70,5 @@ describe.each([ it('fails', () => { expect(left).toBe(right); }); - } + }, ); diff --git a/e2e/each/__tests__/success.test.js b/e2e/each/__tests__/success.test.js index 523a4542e513..da26207f78d1 100644 --- a/e2e/each/__tests__/success.test.js +++ b/e2e/each/__tests__/success.test.js @@ -9,7 +9,7 @@ test.each(['red', 'green', 'bean'])( "The word %s contains the letter 'e'", word => { expect(/e/.test(word)).toBe(true); - } + }, ); it.each([ diff --git a/e2e/error-on-deprecated/__tests__/jasmine.objectContaining.test.js b/e2e/error-on-deprecated/__tests__/jasmine.objectContaining.test.js index 3b9683aba277..993a375b1a41 100644 --- a/e2e/error-on-deprecated/__tests__/jasmine.objectContaining.test.js +++ b/e2e/error-on-deprecated/__tests__/jasmine.objectContaining.test.js @@ -8,6 +8,6 @@ test('jasmine.objectContaining', () => { expect({input: 'trash', output: 'trash'}).toEqual( - jasmine.objectContaining({output: 'trash'}) + jasmine.objectContaining({output: 'trash'}), ); }); diff --git a/e2e/expect-async-matcher/__tests__/failure.test.js b/e2e/expect-async-matcher/__tests__/failure.test.js index 206948d90a9b..5f9a4880e173 100644 --- a/e2e/expect-async-matcher/__tests__/failure.test.js +++ b/e2e/expect-async-matcher/__tests__/failure.test.js @@ -20,5 +20,5 @@ it('fail with expected promise values', () => it('fail with expected promise values and not', () => expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync( - Promise.resolve(2) + Promise.resolve(2), )); diff --git a/e2e/expect-async-matcher/__tests__/success.test.js b/e2e/expect-async-matcher/__tests__/success.test.js index 8f597b9788ea..ed4a169f6a08 100644 --- a/e2e/expect-async-matcher/__tests__/success.test.js +++ b/e2e/expect-async-matcher/__tests__/success.test.js @@ -20,5 +20,5 @@ it('works with expected promise values', () => it('works with expected promise values and not', () => expect(Promise.resolve([1, 2])).resolves.not.toHaveLengthAsync( - Promise.resolve(1) + Promise.resolve(1), )); diff --git a/e2e/expect-async-matcher/matchers.js b/e2e/expect-async-matcher/matchers.js index 842139ca1ba6..b148b807b44b 100644 --- a/e2e/expect-async-matcher/matchers.js +++ b/e2e/expect-async-matcher/matchers.js @@ -8,7 +8,7 @@ export async function toHaveLengthAsync( received: any, - lengthPromise: Promise + lengthPromise: Promise, ) { const length = await lengthPromise; diff --git a/e2e/expect-in-vm/__tests__/expect-in-vm.test.js b/e2e/expect-in-vm/__tests__/expect-in-vm.test.js index 32b9ce2d7754..183364245d92 100644 --- a/e2e/expect-in-vm/__tests__/expect-in-vm.test.js +++ b/e2e/expect-in-vm/__tests__/expect-in-vm.test.js @@ -14,7 +14,7 @@ it('correctly expects RegExp inside a new VM context', () => { `(function(require, module, exports, __dirname, __filename, expect) { expect('ab12cd').toMatch(/ab12cd/); })`, - global + global, ); const module = { @@ -28,6 +28,6 @@ it('correctly expects RegExp inside a new VM context', () => { module.exports, __dirname, __filename, - expect + expect, ); }); diff --git a/e2e/jasmine-async/__tests__/promiseBeforeAll.test.js b/e2e/jasmine-async/__tests__/promiseBeforeAll.test.js index 42ce500c408c..f3a40d8f9159 100644 --- a/e2e/jasmine-async/__tests__/promiseBeforeAll.test.js +++ b/e2e/jasmine-async/__tests__/promiseBeforeAll.test.js @@ -15,7 +15,7 @@ describe('promise beforeAll', () => { process.nextTick(resolve); }).then(() => { flag = 1; - }) + }), ); beforeAll(() => new Promise(resolve => setTimeout(resolve, 10)), 500); diff --git a/e2e/jasmine-async/__tests__/promiseBeforeEach.test.js b/e2e/jasmine-async/__tests__/promiseBeforeEach.test.js index 846eeb8e6636..45c16c2ef6de 100644 --- a/e2e/jasmine-async/__tests__/promiseBeforeEach.test.js +++ b/e2e/jasmine-async/__tests__/promiseBeforeEach.test.js @@ -13,7 +13,7 @@ describe('promise beforeEach', () => { process.nextTick(resolve); }).then(() => { this.flag = 1; - }) + }), ); // passing tests diff --git a/e2e/jasmine-async/__tests__/promiseIt.test.js b/e2e/jasmine-async/__tests__/promiseIt.test.js index aa688659a7d9..c02d38788494 100644 --- a/e2e/jasmine-async/__tests__/promiseIt.test.js +++ b/e2e/jasmine-async/__tests__/promiseIt.test.js @@ -31,7 +31,7 @@ describe('promise it', () => { new Promise(resolve => { if (this.someContextValue !== 'value') { throw new Error( - 'expected this.someContextValue to be set: ' + this.someContextValue + 'expected this.someContextValue to be set: ' + this.someContextValue, ); } resolve(); @@ -90,13 +90,13 @@ describe('promise it', () => { it( 'succeeds if the test finishes in time', () => new Promise(resolve => setTimeout(resolve, 10)), - 250 + 250, ); // failing tests it( 'fails if a custom timeout is exceeded', () => new Promise(resolve => setTimeout(resolve, 100)), - 10 + 10, ); }); diff --git a/e2e/native-esm/__tests__/native-esm.test.js b/e2e/native-esm/__tests__/native-esm.test.js index 05dc9e5fc328..0603e5d67e1d 100644 --- a/e2e/native-esm/__tests__/native-esm.test.js +++ b/e2e/native-esm/__tests__/native-esm.test.js @@ -21,7 +21,7 @@ test('should have correct import.meta', () => { url: expect.any(String), }); expect( - import.meta.url.endsWith('/e2e/native-esm/__tests__/native-esm.test.js') + import.meta.url.endsWith('/e2e/native-esm/__tests__/native-esm.test.js'), ).toBe(true); }); diff --git a/e2e/reset-modules/__tests__/resetModules.test.js b/e2e/reset-modules/__tests__/resetModules.test.js index 01eea7be6e20..f0d09ff11d8c 100644 --- a/e2e/reset-modules/__tests__/resetModules.test.js +++ b/e2e/reset-modules/__tests__/resetModules.test.js @@ -12,7 +12,7 @@ global.testObject = new Proxy( get: function getter(target, key) { return key; }, - } + }, ); test('jest.resetModules should not error when _isMockFunction is defined but not boolean', () => { jest.resetModules(); diff --git a/e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js b/e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js index 43a4dd97402e..f6891ea61742 100644 --- a/e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js +++ b/e2e/resolve-with-paths/__tests__/resolveWithPaths.test.js @@ -10,19 +10,19 @@ import {resolve} from 'path'; test('finds a module relative to one of the given paths', () => { expect(require.resolve('./mod.js', {paths: ['../dir']})).toEqual( - resolve(__dirname, '..', 'dir', 'mod.js') + resolve(__dirname, '..', 'dir', 'mod.js'), ); }); test('finds a module without a leading "./" relative to one of the given paths', () => { expect(require.resolve('mod.js', {paths: ['../dir']})).toEqual( - resolve(__dirname, '..', 'dir', 'mod.js') + resolve(__dirname, '..', 'dir', 'mod.js'), ); }); test('finds a node_module above one of the given paths', () => { expect(require.resolve('mod', {paths: ['../dir']})).toEqual( - resolve(__dirname, '..', 'node_modules', 'mod', 'index.js') + resolve(__dirname, '..', 'node_modules', 'mod', 'index.js'), ); }); @@ -32,12 +32,12 @@ test('finds a native node module when paths are given', () => { test('throws an error if the module cannot be found from given paths', () => { expect(() => require.resolve('./mod.js', {paths: ['..']})).toThrowError( - "Cannot resolve module './mod.js' from paths ['..'] from " + "Cannot resolve module './mod.js' from paths ['..'] from ", ); }); test('throws module not found error if the module cannot be found from given paths', () => { expect(() => require.resolve('./mod.js', {paths: ['..']})).toThrow( - expect.objectContaining({code: 'MODULE_NOT_FOUND'}) + expect.objectContaining({code: 'MODULE_NOT_FOUND'}), ); }); diff --git a/e2e/resolve/__tests__/resolve.test.js b/e2e/resolve/__tests__/resolve.test.js index bd993a99f8aa..e3d3500d6b8c 100644 --- a/e2e/resolve/__tests__/resolve.test.js +++ b/e2e/resolve/__tests__/resolve.test.js @@ -66,7 +66,7 @@ test('should resolve filename.json', () => { test('should preserve identity for symlinks', () => { expect(require('../../../packages/jest-resolve')).toBe( - require('jest-resolve') + require('jest-resolve'), ); }); @@ -113,7 +113,7 @@ test('should throw module not found error if the module has dependencies that ca Test7.js __tests__/resolve.test.js\n `, - }) + }), ); }); @@ -122,6 +122,6 @@ test('should throw module not found error if the module cannot be found', () => expect.objectContaining({ code: 'MODULE_NOT_FOUND', message: "Cannot find module 'Test8' from 'resolve.test.js'", - }) + }), ); }); diff --git a/e2e/snapshot/__tests__/snapshot.test.js b/e2e/snapshot/__tests__/snapshot.test.js index 22722a34f77d..280d16caba18 100644 --- a/e2e/snapshot/__tests__/snapshot.test.js +++ b/e2e/snapshot/__tests__/snapshot.test.js @@ -30,7 +30,7 @@ describe('snapshot', () => { it('cannot be used with .not', () => { expect(() => expect('').not.toMatchSnapshot()).toThrow( - 'Snapshot matchers cannot be used with not' + 'Snapshot matchers cannot be used with not', ); }); diff --git a/e2e/typescript-coverage/typescriptPreprocessor.js b/e2e/typescript-coverage/typescriptPreprocessor.js index f70981612673..8633bdab5a95 100644 --- a/e2e/typescript-coverage/typescriptPreprocessor.js +++ b/e2e/typescript-coverage/typescriptPreprocessor.js @@ -17,7 +17,7 @@ module.exports = { module: tsc.ModuleKind.CommonJS, }, path, - [] + [], ); } return src; diff --git a/examples/angular/app.component.spec.ts b/examples/angular/app.component.spec.ts index acd80ab8fd2d..86136edd82f6 100644 --- a/examples/angular/app.component.spec.ts +++ b/examples/angular/app.component.spec.ts @@ -8,7 +8,7 @@ const getTitleFn = jest.fn().mockReturnValue(title); const dataServiceSpy = jest.fn().mockImplementation( (): Partial => ({ getTitle: getTitleFn, - }) + }), ); describe('AppComponent', () => { @@ -36,7 +36,7 @@ describe('AppComponent', () => { fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; expect(compiled.querySelector('h1').textContent).toContain( - `Welcome to ${title}!` + `Welcome to ${title}!`, ); }); }); diff --git a/examples/angular/setupJest.js b/examples/angular/setupJest.js index c8a41202d6e7..64db898071a7 100644 --- a/examples/angular/setupJest.js +++ b/examples/angular/setupJest.js @@ -14,5 +14,5 @@ const testingModule = require('@angular/platform-browser-dynamic/testing'); getTestBed().initTestEnvironment( testingModule.BrowserDynamicTestingModule, - testingModule.platformBrowserDynamicTesting() + testingModule.platformBrowserDynamicTesting(), ); diff --git a/examples/async/__mocks__/request.js b/examples/async/__mocks__/request.js index 51784974d8fa..e593301d672f 100644 --- a/examples/async/__mocks__/request.js +++ b/examples/async/__mocks__/request.js @@ -15,7 +15,7 @@ export default function request(url) { ? resolve(users[userID]) : reject({ error: 'User with ' + userID + ' not found.', - }) + }), ); }); } diff --git a/examples/async/__tests__/user.test.js b/examples/async/__tests__/user.test.js index 2e02f9e727dc..a81de93b1cd4 100644 --- a/examples/async/__tests__/user.test.js +++ b/examples/async/__tests__/user.test.js @@ -45,7 +45,7 @@ test('tests error with promises', async () => { return user.getUserName(2).catch(e => expect(e).toEqual({ error: 'User with 2 not found.', - }) + }), ); }); diff --git a/examples/manual-mocks/__tests__/file_summarizer.test.js b/examples/manual-mocks/__tests__/file_summarizer.test.js index d097ab7cdb73..2429e47acf5c 100644 --- a/examples/manual-mocks/__tests__/file_summarizer.test.js +++ b/examples/manual-mocks/__tests__/file_summarizer.test.js @@ -18,7 +18,7 @@ describe('listFilesInDirectorySync', () => { it('includes all files in the directory in the summary', () => { const FileSummarizer = require('../FileSummarizer'); const fileSummary = FileSummarizer.summarizeFilesInDirectorySync( - '/path/to' + '/path/to', ); expect(fileSummary.length).toBe(2); diff --git a/examples/react-native/__tests__/intro.test.js b/examples/react-native/__tests__/intro.test.js index ebb1100b6d2c..a1d246799fe1 100644 --- a/examples/react-native/__tests__/intro.test.js +++ b/examples/react-native/__tests__/intro.test.js @@ -52,7 +52,7 @@ it('renders the FlatList component', () => { data={['apple', 'banana', 'kiwi']} keyExtractor={item => item} renderItem={({item}) => {item}} - /> + />, ) .toJSON(); expect(tree).toMatchSnapshot(); diff --git a/examples/react-testing-library/__tests__/CheckboxWithLabel-test.js b/examples/react-testing-library/__tests__/CheckboxWithLabel-test.js index 73aeeb99f4e6..cfc95680c90b 100644 --- a/examples/react-testing-library/__tests__/CheckboxWithLabel-test.js +++ b/examples/react-testing-library/__tests__/CheckboxWithLabel-test.js @@ -10,7 +10,7 @@ afterEach(cleanup); it('CheckboxWithLabel changes the text after click', () => { const {queryByLabelText, getByLabelText} = render( - + , ); expect(queryByLabelText(/off/i)).toBeTruthy(); diff --git a/examples/react/__tests__/CheckboxWithLabel-test.js b/examples/react/__tests__/CheckboxWithLabel-test.js index 494504ca9cc5..b887304d42aa 100644 --- a/examples/react/__tests__/CheckboxWithLabel-test.js +++ b/examples/react/__tests__/CheckboxWithLabel-test.js @@ -15,7 +15,7 @@ it('CheckboxWithLabel changes the text after click', () => { inputRef={checkboxInputRef} labelOn="On" labelOff="Off" - /> + />, ); const labelNode = checkboxLabelRef.current; diff --git a/examples/snapshot/__tests__/link.react.test.js b/examples/snapshot/__tests__/link.react.test.js index fd9b87115c42..1d9300b82772 100644 --- a/examples/snapshot/__tests__/link.react.test.js +++ b/examples/snapshot/__tests__/link.react.test.js @@ -27,7 +27,7 @@ it('properly escapes quotes', () => { it('changes the class when hovered', () => { const component = renderer.create( - Facebook + Facebook, ); let tree = component.toJSON(); expect(tree).toMatchSnapshot(); diff --git a/examples/typescript/__tests__/CheckboxWithLabel-test.tsx b/examples/typescript/__tests__/CheckboxWithLabel-test.tsx index 59afe50a027f..85159d2d4b15 100644 --- a/examples/typescript/__tests__/CheckboxWithLabel-test.tsx +++ b/examples/typescript/__tests__/CheckboxWithLabel-test.tsx @@ -15,7 +15,7 @@ it('CheckboxWithLabel changes the text after click', () => { inputRef={checkboxInputRef} labelOn="On" labelOff="Off" - /> + />, ); const labelNode = checkboxLabelRef.current; diff --git a/package.json b/package.json index 337123a5d1f9..3e5841ea2d8c 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "realpath-native": "^2.0.0", "resolve": "^1.15.0", "rimraf": "^3.0.0", + "semver": "^6.3.0", "slash": "^3.0.0", "string-length": "^3.1.0", "strip-ansi": "^6.0.0", @@ -126,22 +127,8 @@ "arrowParens": "avoid", "overrides": [ { - "excludeFiles": [ - "e2e/__tests__/**/*", - "website/versioned_docs/**/*.md" - ], - "files": [ - "examples/**/*", - "scripts/**/*", - "e2e/*/**/*", - "website/*.js", - "website/*/**/*", - "eslintImportResolver.js", - "babel.config.js" - ], + "files": "website/**/*.js", "options": { - "printWidth": 80, - "singleQuote": true, "trailingComma": "es5" } } diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 5bf8cb86877e..763858ae640b 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -19,5 +19,8 @@ "ansi-regex": "^5.0.0", "ansi-styles": "^4.1.0", "semver": "^6.3.0" + }, + "engines": { + "node": ">= 8.3" } } diff --git a/scripts/babel-plugin-jest-native-globals.js b/scripts/babel-plugin-jest-native-globals.js index c1e60921917a..148a8eeb22e3 100644 --- a/scripts/babel-plugin-jest-native-globals.js +++ b/scripts/babel-plugin-jest-native-globals.js @@ -70,7 +70,7 @@ module.exports = ({template}) => { path.node.name === 'fs' && path.parent.property && ['readFileSync', 'writeFileSync', 'existsSync'].includes( - path.parent.property.name + path.parent.property.name, ) ) { if ( diff --git a/scripts/babel-plugin-jest-replace-ts-require-assignment.js b/scripts/babel-plugin-jest-replace-ts-require-assignment.js index 72451255239b..aeb5ddd2aaf1 100644 --- a/scripts/babel-plugin-jest-replace-ts-require-assignment.js +++ b/scripts/babel-plugin-jest-replace-ts-require-assignment.js @@ -23,7 +23,7 @@ module.exports = ({template}) => { moduleExportsDeclaration({ IMPORT: node.moduleReference.expression, NAME: node.id, - }) + }), ); }, }, diff --git a/scripts/browserBuild.js b/scripts/browserBuild.js index a335d47ca206..4c3257380c71 100644 --- a/scripts/browserBuild.js +++ b/scripts/browserBuild.js @@ -62,7 +62,7 @@ function browserBuild(pkgName, entryPath, destination) { alias: { chalk: path.resolve( __dirname, - '../packages/expect/build/fakeChalk.js' + '../packages/expect/build/fakeChalk.js', ), }, extensions: ['.js', '.json', '.ts'], @@ -78,7 +78,7 @@ function browserBuild(pkgName, entryPath, destination) { return; } resolve(stats); - } + }, ); }); } diff --git a/scripts/build.js b/scripts/build.js index ff06ba44adf0..7c5e0f5c3ba7 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -84,7 +84,7 @@ function buildBrowserPackage(p) { if (browser) { if (browser.indexOf(BUILD_ES5_DIR) !== 0) { throw new Error( - `browser field for ${pkgJsonPath} should start with "${BUILD_ES5_DIR}"` + `browser field for ${pkgJsonPath} should start with "${BUILD_ES5_DIR}"`, ); } let indexFile = path.resolve(srcDir, 'index.js'); @@ -113,7 +113,7 @@ function buildFile(file, silent) { process.stdout.write( chalk.dim(' \u2022 ') + path.relative(PACKAGES_DIR, file) + - ' (ignore)\n' + ' (ignore)\n', ); return; } @@ -131,7 +131,7 @@ function buildFile(file, silent) { chalk.red(' \u21D2 ') + path.relative(PACKAGES_DIR, destPath) + ' (copy)' + - '\n' + '\n', ); } else { const options = Object.assign({}, transformOptions); @@ -141,7 +141,7 @@ function buildFile(file, silent) { // The modules in the blacklist are injected into the user's sandbox // We need to guard some globals there. options.plugins.push( - require.resolve('./babel-plugin-jest-native-globals') + require.resolve('./babel-plugin-jest-native-globals'), ); } else { options.plugins = options.plugins.map(plugin => { @@ -174,7 +174,7 @@ function buildFile(file, silent) { path.relative(PACKAGES_DIR, file) + chalk.green(' \u21D2 ') + path.relative(PACKAGES_DIR, destPath) + - '\n' + '\n', ); } } diff --git a/scripts/buildTs.js b/scripts/buildTs.js index cf734188267e..af57239ed718 100644 --- a/scripts/buildTs.js +++ b/scripts/buildTs.js @@ -7,6 +7,7 @@ 'use strict'; +const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); @@ -20,25 +21,23 @@ const {getPackages} = require('./buildUtils'); const packages = getPackages(); const packagesWithTs = packages.filter(p => - fs.existsSync(path.resolve(p, 'tsconfig.json')) + fs.existsSync(path.resolve(p, 'tsconfig.json')), ); packagesWithTs.forEach(pkgDir => { const pkg = require(pkgDir + '/package.json'); - if (!pkg.types) { - throw new Error(`Package ${pkg.name} is missing \`types\` field`); - } - - if (!pkg.typesVersions) { - throw new Error(`Package ${pkg.name} is missing \`typesVersions\` field`); - } + assert.ok(pkg.types, `Package ${pkg.name} is missing \`types\` field`); + assert.ok( + pkg.typesVersions, + `Package ${pkg.name} is missing \`typesVersions\` field`, + ); - if (pkg.main.replace(/\.js$/, '.d.ts') !== pkg.types) { - throw new Error( - `\`main\` and \`types\` field of ${pkg.name} does not match` - ); - } + assert.equal( + pkg.types, + pkg.main.replace(/\.js$/, '.d.ts'), + `\`main\` and \`types\` field of ${pkg.name} does not match`, + ); }); const args = [ @@ -54,11 +53,11 @@ console.log(chalk.inverse(' Building TypeScript definition files ')); try { execa.sync('yarn', args, {stdio: 'inherit'}); console.log( - chalk.inverse.green(' Successfully built TypeScript definition files ') + chalk.inverse.green(' Successfully built TypeScript definition files '), ); } catch (e) { console.error( - chalk.inverse.red(' Unable to build TypeScript definition files ') + chalk.inverse.red(' Unable to build TypeScript definition files '), ); console.error(e.stack); process.exitCode = 1; @@ -79,19 +78,19 @@ Promise.all( rimraf.sync(path.resolve(pkgDir, 'build/ts3.4')); return execa('yarn', downlevelArgs, {cwd: pkgDir, stdio: 'inherit'}); - }) - ) + }), + ), ) .then(() => { console.log( chalk.inverse.green( - ' Successfully downleveled TypeScript definition files ' - ) + ' Successfully downleveled TypeScript definition files ', + ), ); }) .catch(e => { console.error( - chalk.inverse.red(' Unable to downlevel TypeScript definition files ') + chalk.inverse.red(' Unable to downlevel TypeScript definition files '), ); console.error(e.stack); process.exitCode = 1; diff --git a/scripts/buildUtils.js b/scripts/buildUtils.js index 0e0775795cc4..90e9bb71bc4a 100644 --- a/scripts/buildUtils.js +++ b/scripts/buildUtils.js @@ -5,10 +5,14 @@ * LICENSE file in the root directory of this source tree. */ +'use strict'; + +const assert = require('assert'); const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const stringLength = require('string-length'); +const rootPackage = require('../package.json'); const PACKAGES_DIR = path.resolve(__dirname, '../packages'); @@ -16,10 +20,26 @@ const OK = chalk.reset.inverse.bold.green(' DONE '); // Get absolute paths of all directories under packages/* module.exports.getPackages = function getPackages() { - return fs + const packages = fs .readdirSync(PACKAGES_DIR) .map(file => path.resolve(PACKAGES_DIR, file)) .filter(f => fs.lstatSync(path.resolve(f)).isDirectory()); + + const nodeEngineRequiremnt = rootPackage.engines.node; + + packages.forEach(packageDir => { + const pkg = require(`${packageDir}/package.json`); + + assert.ok(pkg.engines, `Engine requirement in ${pkg.name} should exist`); + + assert.equal( + pkg.engines.node, + nodeEngineRequiremnt, + `Engine requirement in ${pkg.name} should match root`, + ); + }); + + return packages; }; module.exports.adjustToTerminalWidth = function adjustToTerminalWidth(str) { diff --git a/scripts/checkCopyrightHeaders.js b/scripts/checkCopyrightHeaders.js index 12d4eb78be3c..762d0581003c 100755 --- a/scripts/checkCopyrightHeaders.js +++ b/scripts/checkCopyrightHeaders.js @@ -140,7 +140,7 @@ function check() { !IGNORED_PATTERNS.some(pattern => pattern.test(file)) && !isDirectory(file) && !isBinaryFileSync(file) && - needsCopyrightHeader(file) + needsCopyrightHeader(file), ); if (invalidFiles.length > 0) { diff --git a/scripts/mapCoverage.js b/scripts/mapCoverage.js index deab981034f4..ce146ce8c855 100644 --- a/scripts/mapCoverage.js +++ b/scripts/mapCoverage.js @@ -35,17 +35,17 @@ const map = istanbulCoverage.createCoverageMap(); const mapFileCoverage = fileCoverage => { fileCoverage.path = fileCoverage.path.replace( /(.*packages\/.*\/)(build)(\/.*)/, - '$1src$3' + '$1src$3', ); return fileCoverage; }; Object.keys(coverage).forEach(filename => - map.addFileCoverage(mapFileCoverage(coverage[filename])) + map.addFileCoverage(mapFileCoverage(coverage[filename])), ); const context = istanbulReport.createContext({coverageMap: map}); ['json', 'lcov', 'text'].forEach(reporter => - istanbulReports.create(reporter, {}).execute(context) + istanbulReports.create(reporter, {}).execute(context), ); diff --git a/scripts/verifyOldTs.js b/scripts/verifyOldTs.js index 34fbbd670a6b..e1d864cd77ca 100644 --- a/scripts/verifyOldTs.js +++ b/scripts/verifyOldTs.js @@ -35,16 +35,16 @@ try { execa.sync('yarn', ['add', 'typescript@~3.4'], {cwd, stdio: 'inherit'}); fs.writeFileSync( path.join(cwd, 'tsconfig.json'), - JSON.stringify(tsConfig, null, 2) + JSON.stringify(tsConfig, null, 2), ); fs.writeFileSync( path.join(cwd, 'index.ts'), - `import jest = require('${jestDirectory}');` + `import jest = require('${jestDirectory}');`, ); execa.sync('yarn', ['tsc', '--project', '.'], {cwd, stdio: 'inherit'}); console.log( - chalk.inverse.green(' Successfully compiled Jest with TypeScript 3.4 ') + chalk.inverse.green(' Successfully compiled Jest with TypeScript 3.4 '), ); } finally { rimraf.sync(cwd); diff --git a/scripts/watch.js b/scripts/watch.js index 0f04a8342d3a..5af9c3ee9b50 100644 --- a/scripts/watch.js +++ b/scripts/watch.js @@ -34,7 +34,7 @@ chokidar { ignoreInitial: true, ignored: /(^|[\/\\])\../, // ignore dotfiles - } + }, ) .on('all', (event, filePath) => { if ( @@ -43,7 +43,7 @@ chokidar ) { console.log( chalk.green('->'), - `${event}: ${path.relative(PACKAGES_DIR, filePath)}` + `${event}: ${path.relative(PACKAGES_DIR, filePath)}`, ); rebuild(filePath); } else { @@ -51,7 +51,7 @@ chokidar const buildFile = filePath .replace( path.join(path.sep, 'src', path.sep), - path.join(path.sep, 'build', path.sep) + path.join(path.sep, 'build', path.sep), ) .replace(/\.ts$/, '.js'); try { @@ -59,8 +59,8 @@ chokidar process.stdout.write( `${chalk.red(' \u2022 ')}${path.relative( PACKAGES_DIR, - buildFile - )} (deleted)\n` + buildFile, + )} (deleted)\n`, ); } catch (e) {} } From 70bf93c32d243e0856157f563629f2a875272fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Thu, 23 Apr 2020 22:26:40 +0200 Subject: [PATCH 33/39] Update .vscode/launch.json settings (#9868) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update .vscode/launch.json settings * Update .vscode/launch.json Co-authored-by: Michał Pierzchała --- .vscode/launch.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f4106b4f6605..5de4feacd272 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,10 +7,15 @@ { "type": "node", "request": "launch", - "name": "Debug Jest with current test file", - "program": "${workspaceFolder}/packages/jest-cli/bin/jest.js", - "args": ["--runInBand", "${file}"], - "runtimeArgs": ["-r", "flow-remove-types/register"] + "name": "Jest Current File", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["${fileBasenameNoExtension}"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest/bin/jest" + } } ] } From 2e454103365885534ae86f7f9bbf1bf6ae171133 Mon Sep 17 00:00:00 2001 From: mbpreble Date: Thu, 23 Apr 2020 15:36:02 -0500 Subject: [PATCH 34/39] Improve source map handling when instrumenting transformed code (#9811) --- CHANGELOG.md | 1 + ...ckTraceSourceMapsWithCoverage.test.ts.snap | 20 +++++ .../stackTraceSourceMapsWithCoverage.test.ts | 22 +++++ .../__tests__/fails.ts | 11 +++ .../lib.ts | 14 ++++ .../package.json | 13 +++ .../preprocessor.js | 21 +++++ .../yarn.lock | 8 ++ .../jest-reporters/src/coverage_reporter.ts | 29 ------- .../src/generateEmptyCoverage.ts | 10 +-- packages/jest-runner/src/runTest.ts | 1 - packages/jest-runtime/src/index.ts | 22 +---- packages/jest-test-result/src/types.ts | 1 + .../jest-transform/src/ScriptTransformer.ts | 63 ++++++++------ .../script_transformer.test.js.snap | 12 ++- .../src/__tests__/script_transformer.test.js | 84 +++++++++++++++++++ packages/jest-transform/src/types.ts | 1 + packages/jest-types/src/Transform.ts | 2 +- 18 files changed, 249 insertions(+), 86 deletions(-) create mode 100644 e2e/__tests__/__snapshots__/stackTraceSourceMapsWithCoverage.test.ts.snap create mode 100644 e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts create mode 100644 e2e/stack-trace-source-maps-with-coverage/__tests__/fails.ts create mode 100644 e2e/stack-trace-source-maps-with-coverage/lib.ts create mode 100644 e2e/stack-trace-source-maps-with-coverage/package.json create mode 100644 e2e/stack-trace-source-maps-with-coverage/preprocessor.js create mode 100644 e2e/stack-trace-source-maps-with-coverage/yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 9be830431972..c318022f32db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) - `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) +- `[jest-transform]` Improve source map handling when instrumenting transformed code ([#9811](https://github.com/facebook/jest/pull/9811)) ### Chore & Maintenance diff --git a/e2e/__tests__/__snapshots__/stackTraceSourceMapsWithCoverage.test.ts.snap b/e2e/__tests__/__snapshots__/stackTraceSourceMapsWithCoverage.test.ts.snap new file mode 100644 index 000000000000..fa3a2f7871ab --- /dev/null +++ b/e2e/__tests__/__snapshots__/stackTraceSourceMapsWithCoverage.test.ts.snap @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`processes stack traces and code frames with source maps with coverage 1`] = ` +FAIL __tests__/fails.ts + ✕ fails + + ● fails + + This did not work! + + 11 | + 12 | export function error() { + > 13 | throw new Error('This did not work!'); + | ^ + 14 | } + 15 | + + at Object.error (lib.ts:13:9) + at Object. (__tests__/fails.ts:10:3) +`; diff --git a/e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts b/e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts new file mode 100644 index 000000000000..4ac65f38e890 --- /dev/null +++ b/e2e/__tests__/stackTraceSourceMapsWithCoverage.test.ts @@ -0,0 +1,22 @@ +/** + * 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 * as path from 'path'; +import wrap from 'jest-snapshot-serializer-raw'; +import {extractSummary, run} from '../Utils'; +import runJest from '../runJest'; + +it('processes stack traces and code frames with source maps with coverage', () => { + const dir = path.resolve( + __dirname, + '../stack-trace-source-maps-with-coverage', + ); + run('yarn', dir); + const {stderr} = runJest(dir, ['--no-cache', '--coverage']); + + // Should report an error at source line 13 in lib.ts at line 10 of the test + expect(wrap(extractSummary(stderr).rest)).toMatchSnapshot(); +}); diff --git a/e2e/stack-trace-source-maps-with-coverage/__tests__/fails.ts b/e2e/stack-trace-source-maps-with-coverage/__tests__/fails.ts new file mode 100644 index 000000000000..583175c89ed7 --- /dev/null +++ b/e2e/stack-trace-source-maps-with-coverage/__tests__/fails.ts @@ -0,0 +1,11 @@ +/** + * 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 {error} from '../lib'; + +it('fails', () => { + error(); +}); diff --git a/e2e/stack-trace-source-maps-with-coverage/lib.ts b/e2e/stack-trace-source-maps-with-coverage/lib.ts new file mode 100644 index 000000000000..9fffd6978ab1 --- /dev/null +++ b/e2e/stack-trace-source-maps-with-coverage/lib.ts @@ -0,0 +1,14 @@ +/** + * 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. + */ +interface NotUsedButTakesUpLines { + a: number; + b: string; +} + +export function error() { + throw new Error('This did not work!'); +} diff --git a/e2e/stack-trace-source-maps-with-coverage/package.json b/e2e/stack-trace-source-maps-with-coverage/package.json new file mode 100644 index 000000000000..f8fbad2d8bca --- /dev/null +++ b/e2e/stack-trace-source-maps-with-coverage/package.json @@ -0,0 +1,13 @@ +{ + "jest": { + "rootDir": "./", + "transform": { + "^.+\\.(ts)$": "/preprocessor.js" + }, + "testEnvironment": "node", + "testRegex": "fails" + }, + "dependencies": { + "typescript": "^3.7.4" + } +} diff --git a/e2e/stack-trace-source-maps-with-coverage/preprocessor.js b/e2e/stack-trace-source-maps-with-coverage/preprocessor.js new file mode 100644 index 000000000000..133d42ec44a2 --- /dev/null +++ b/e2e/stack-trace-source-maps-with-coverage/preprocessor.js @@ -0,0 +1,21 @@ +/** + * 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. + */ + +const tsc = require('typescript'); + +module.exports = { + process(src, path) { + return tsc.transpileModule(src, { + compilerOptions: { + inlineSourceMap: true, + module: tsc.ModuleKind.CommonJS, + target: 'es5', + }, + fileName: path, + }).outputText; + }, +}; diff --git a/e2e/stack-trace-source-maps-with-coverage/yarn.lock b/e2e/stack-trace-source-maps-with-coverage/yarn.lock new file mode 100644 index 000000000000..e9f19f98faf0 --- /dev/null +++ b/e2e/stack-trace-source-maps-with-coverage/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +typescript@^3.7.4: + version "3.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" + integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== diff --git a/packages/jest-reporters/src/coverage_reporter.ts b/packages/jest-reporters/src/coverage_reporter.ts index b769743e2ff6..4ec8d75961ac 100644 --- a/packages/jest-reporters/src/coverage_reporter.ts +++ b/packages/jest-reporters/src/coverage_reporter.ts @@ -71,28 +71,6 @@ export default class CoverageReporter extends BaseReporter { if (testResult.coverage) { this._coverageMap.merge(testResult.coverage); } - - const sourceMaps = testResult.sourceMaps; - if (sourceMaps) { - Object.keys(sourceMaps).forEach(sourcePath => { - let inputSourceMap: RawSourceMap | undefined; - try { - const coverage: istanbulCoverage.FileCoverage = this._coverageMap.fileCoverageFor( - sourcePath, - ); - inputSourceMap = (coverage.toJSON() as any).inputSourceMap; - } finally { - if (inputSourceMap) { - this._sourceMapStore.registerMap(sourcePath, inputSourceMap); - } else { - this._sourceMapStore.registerURL( - sourcePath, - sourceMaps[sourcePath], - ); - } - } - }); - } } async onRunComplete( @@ -215,13 +193,6 @@ export default class CoverageReporter extends BaseReporter { ]); } else { this._coverageMap.addFileCoverage(result.coverage); - - if (result.sourceMapPath) { - this._sourceMapStore.registerURL( - filename, - result.sourceMapPath, - ); - } } } } catch (error) { diff --git a/packages/jest-reporters/src/generateEmptyCoverage.ts b/packages/jest-reporters/src/generateEmptyCoverage.ts index 62ab4c023f2c..b6c270060fdd 100644 --- a/packages/jest-reporters/src/generateEmptyCoverage.ts +++ b/packages/jest-reporters/src/generateEmptyCoverage.ts @@ -18,7 +18,6 @@ export type CoverageWorkerResult = | { kind: 'BabelCoverage'; coverage: FileCoverage; - sourceMapPath?: string | null; } | { kind: 'V8Coverage'; @@ -66,9 +65,11 @@ export default function ( } // Transform file with instrumentation to make sure initial coverage data is well mapped to original code. - const {code, mapCoverage, sourceMapPath} = new ScriptTransformer( - config, - ).transformSource(filename, source, true); + const {code} = new ScriptTransformer(config).transformSource( + filename, + source, + true, + ); // TODO: consider passing AST const extracted = readInitialCoverage(code); // Check extracted initial coverage is not null, this can happen when using /* istanbul ignore file */ @@ -76,7 +77,6 @@ export default function ( coverageWorkerResult = { coverage: createFileCoverage(extracted.coverageData), kind: 'BabelCoverage', - sourceMapPath: mapCoverage ? sourceMapPath : null, }; } } diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 36754d3f086e..fb3e93ea0eda 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -275,7 +275,6 @@ async function runTestInternal( const coverageKeys = Object.keys(coverage); if (coverageKeys.length) { result.coverage = coverage; - result.sourceMaps = runtime.getSourceMapInfo(new Set(coverageKeys)); } } diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 8df6447e8b00..363c18ba846f 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -140,7 +140,6 @@ class Runtime { private _isolatedModuleRegistry: ModuleRegistry | null; private _moduleRegistry: ModuleRegistry; private _esmoduleRegistry: Map>; - private _needsCoverageMapped: Set; private _resolver: Resolver; private _shouldAutoMock: boolean; private _shouldMockModuleCache: BooleanObject; @@ -186,7 +185,6 @@ class Runtime { this._isolatedMockRegistry = null; this._moduleRegistry = new Map(); this._esmoduleRegistry = new Map(); - this._needsCoverageMapped = new Set(); this._resolver = resolver; this._scriptTransformer = new ScriptTransformer(config); this._shouldAutoMock = config.automock; @@ -794,20 +792,9 @@ class Runtime { }); } - getSourceMapInfo(coveredFiles: Set): Record { - return Object.keys(this._sourceMapRegistry).reduce>( - (result, sourcePath) => { - if ( - coveredFiles.has(sourcePath) && - this._needsCoverageMapped.has(sourcePath) && - fs.existsSync(this._sourceMapRegistry[sourcePath]) - ) { - result[sourcePath] = this._sourceMapRegistry[sourcePath]; - } - return result; - }, - {}, - ); + // TODO - remove in Jest 26 + getSourceMapInfo(_coveredFiles: Set): Record { + return {}; } getSourceMaps(): SourceMapRegistry { @@ -1056,9 +1043,6 @@ class Runtime { if (transformedFile.sourceMapPath) { this._sourceMapRegistry[filename] = transformedFile.sourceMapPath; - if (transformedFile.mapCoverage) { - this._needsCoverageMapped.add(filename); - } } return transformedFile; } diff --git a/packages/jest-test-result/src/types.ts b/packages/jest-test-result/src/types.ts index 304b358c143b..ffd9c23735b6 100644 --- a/packages/jest-test-result/src/types.ts +++ b/packages/jest-test-result/src/types.ts @@ -104,6 +104,7 @@ export type TestResult = { unmatched: number; updated: number; }; + // TODO - Remove in Jest 26 sourceMaps?: { [sourcePath: string]: string; }; diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index 1ad4109cd83a..46ae3afb049f 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -205,11 +205,15 @@ export default class ScriptTransformer { private _instrumentFile( filename: Config.Path, - content: string, + input: TransformedSource, supportsDynamicImport: boolean, supportsStaticESM: boolean, - ): string { - const result = babelTransform(content, { + canMapToInput: boolean, + ): TransformedSource { + const inputCode = typeof input === 'string' ? input : input.code; + const inputMap = typeof input === 'string' ? null : input.map; + + const result = babelTransform(inputCode, { auxiliaryCommentBefore: ' istanbul ignore next ', babelrc: false, caller: { @@ -228,21 +232,19 @@ export default class ScriptTransformer { cwd: this._config.rootDir, exclude: [], extension: false, + inputSourceMap: inputMap, useInlineSourceMaps: false, }, ], ], + sourceMaps: canMapToInput ? 'both' : false, }); - if (result) { - const {code} = result; - - if (code) { - return code; - } + if (result && result.code) { + return result as TransformResult; } - return content; + return input; } private _getRealPath(filepath: Config.Path): Config.Path { @@ -287,10 +289,6 @@ export default class ScriptTransformer { const transformWillInstrument = shouldCallTransform && transform && transform.canInstrument; - // If we handle the coverage instrumentation, we should try to map code - // coverage against original source with any provided source map - const mapCoverage = instrument && !transformWillInstrument; - if (code) { // This is broken: we return the code, and a path for the source map // directly from the cache. But, nothing ensures the source map actually @@ -298,7 +296,6 @@ export default class ScriptTransformer { // two separate processes write concurrently to the same cache files. return { code, - mapCoverage, originalCode: content, sourceMapPath, }; @@ -333,9 +330,8 @@ export default class ScriptTransformer { //Could be a potential freeze here. //See: https://github.com/facebook/jest/pull/5177#discussion_r158883570 const inlineSourceMap = sourcemapFromSource(transformed.code); - if (inlineSourceMap) { - transformed.map = inlineSourceMap.toJSON(); + transformed.map = inlineSourceMap.toObject(); } } catch (e) { const transformPath = this._getTransformPath(filename); @@ -347,22 +343,39 @@ export default class ScriptTransformer { } } + // Apply instrumentation to the code if necessary, keeping the instrumented code and new map + let map = transformed.map; if (!transformWillInstrument && instrument) { - code = this._instrumentFile( + /** + * We can map the original source code to the instrumented code ONLY if + * - the process of transforming the code produced a source map e.g. ts-jest + * - we did not transform the source code + * + * Otherwise we cannot make any statements about how the instrumented code corresponds to the original code, + * and we should NOT emit any source maps + * + */ + const shouldEmitSourceMaps = + (transform != null && map != null) || transform == null; + + const instrumented = this._instrumentFile( filename, - transformed.code, + transformed, supportsDynamicImport, supportsStaticESM, + shouldEmitSourceMaps, ); + + code = + typeof instrumented === 'string' ? instrumented : instrumented.code; + map = typeof instrumented === 'string' ? null : instrumented.map; } else { code = transformed.code; } - if (transformed.map) { + if (map) { const sourceMapContent = - typeof transformed.map === 'string' - ? transformed.map - : JSON.stringify(transformed.map); + typeof map === 'string' ? map : JSON.stringify(map); writeCacheFile(sourceMapPath, sourceMapContent); } else { sourceMapPath = null; @@ -372,7 +385,6 @@ export default class ScriptTransformer { return { code, - mapCoverage, originalCode: content, sourceMapPath, }; @@ -396,7 +408,6 @@ export default class ScriptTransformer { let code = content; let sourceMapPath: string | null = null; - let mapCoverage = false; const willTransform = !isInternalModule && @@ -415,12 +426,10 @@ export default class ScriptTransformer { code = transformedSource.code; sourceMapPath = transformedSource.sourceMapPath; - mapCoverage = transformedSource.mapCoverage; } return { code, - mapCoverage, originalCode: content, sourceMapPath, }; diff --git a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap index 19c563f8e376..13584d3f6693 100644 --- a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap +++ b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap @@ -80,7 +80,7 @@ exports[`ScriptTransformer transforms a file properly 1`] = ` /* istanbul ignore next */ function cov_25u22311x4() { var path = "/fruits/banana.js"; - var hash = "4be0f6184160be573fc43f7c2a5877c28b7ce249"; + var hash = "3f8e915bed83285455a8a16aa04dc0cf5242d755"; var global = new Function("return this")(); var gcv = "__coverage__"; var coverageData = { @@ -104,8 +104,9 @@ function cov_25u22311x4() { }, f: {}, b: {}, + inputSourceMap: null, _coverageSchema: "1a1c01bbd47fc00a2c39e90264f33305004495a9", - hash: "4be0f6184160be573fc43f7c2a5877c28b7ce249" + hash: "3f8e915bed83285455a8a16aa04dc0cf5242d755" }; var coverage = global[gcv] || (global[gcv] = {}); @@ -125,13 +126,14 @@ function cov_25u22311x4() { cov_25u22311x4(); cov_25u22311x4().s[0]++; module.exports = "banana"; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImJhbmFuYS5qcyJdLCJuYW1lcyI6WyJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQUEsTUFBTSxDQUFDQyxPQUFQLEdBQWlCLFFBQWpCIiwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSBcImJhbmFuYVwiOyJdfQ== `; exports[`ScriptTransformer transforms a file properly 2`] = ` /* istanbul ignore next */ function cov_23yvu8etmu() { var path = "/fruits/kiwi.js"; - var hash = "7705dd5fcfbc884dcea7062944cfb8cc5d141d1a"; + var hash = "8b5afd38d79008f13ebc229b89ef82b12ee9447a"; var global = new Function("return this")(); var gcv = "__coverage__"; var coverageData = { @@ -193,8 +195,9 @@ function cov_23yvu8etmu() { "0": 0 }, b: {}, + inputSourceMap: null, _coverageSchema: "1a1c01bbd47fc00a2c39e90264f33305004495a9", - hash: "7705dd5fcfbc884dcea7062944cfb8cc5d141d1a" + hash: "8b5afd38d79008f13ebc229b89ef82b12ee9447a" }; var coverage = global[gcv] || (global[gcv] = {}); @@ -220,6 +223,7 @@ module.exports = () => { cov_23yvu8etmu().s[1]++; return "kiwi"; }; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImtpd2kuanMiXSwibmFtZXMiOlsibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUFBLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQixNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBTSxDQUE3QiIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gKCkgPT4gXCJraXdpXCI7Il19 `; exports[`ScriptTransformer uses multiple preprocessors 1`] = ` diff --git a/packages/jest-transform/src/__tests__/script_transformer.test.js b/packages/jest-transform/src/__tests__/script_transformer.test.js index 9069861c2420..b6570ee1c404 100644 --- a/packages/jest-transform/src/__tests__/script_transformer.test.js +++ b/packages/jest-transform/src/__tests__/script_transformer.test.js @@ -535,6 +535,90 @@ describe('ScriptTransformer', () => { expect(writeFileAtomic.sync).toHaveBeenCalledTimes(1); }); + it('should write a source map for the instrumented file when transformed', () => { + const transformerConfig = { + ...config, + transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], + }; + const scriptTransformer = new ScriptTransformer(transformerConfig); + + const map = { + mappings: ';AAAA', + version: 3, + }; + + // A map from the original source to the instrumented output + /* eslint-disable sort-keys */ + const instrumentedCodeMap = { + version: 3, + sources: ['banana.js'], + names: ['content'], + mappings: ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAAA,OAAO', + sourcesContent: ['content'], + }; + /* eslint-enable */ + + require('preprocessor-with-sourcemaps').process.mockReturnValue({ + code: 'content', + map, + }); + + const result = scriptTransformer.transform( + '/fruits/banana.js', + makeGlobalConfig({ + collectCoverage: true, + }), + ); + expect(result.sourceMapPath).toEqual(expect.any(String)); + expect(writeFileAtomic.sync).toBeCalledTimes(2); + expect(writeFileAtomic.sync).toBeCalledWith( + result.sourceMapPath, + JSON.stringify(instrumentedCodeMap), + expect.anything(), + ); + + // Inline source map allows debugging of original source when running instrumented code + expect(result.code).toContain('//# sourceMappingURL'); + }); + + it('should write a source map for the instrumented file when not transformed', () => { + const scriptTransformer = new ScriptTransformer(config); + + // A map from the original source to the instrumented output + /* eslint-disable sort-keys */ + const instrumentedCodeMap = { + version: 3, + sources: ['banana.js'], + names: ['module', 'exports'], + mappings: + ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAAA,MAAM,CAACC,OAAP,GAAiB,QAAjB', + sourcesContent: ['module.exports = "banana";'], + }; + /* eslint-enable */ + + require('preprocessor-with-sourcemaps').process.mockReturnValue({ + code: 'content', + map: null, + }); + + const result = scriptTransformer.transform( + '/fruits/banana.js', + makeGlobalConfig({ + collectCoverage: true, + }), + ); + expect(result.sourceMapPath).toEqual(expect.any(String)); + expect(writeFileAtomic.sync).toBeCalledTimes(2); + expect(writeFileAtomic.sync).toBeCalledWith( + result.sourceMapPath, + JSON.stringify(instrumentedCodeMap), + expect.anything(), + ); + + // Inline source map allows debugging of original source when running instrumented code + expect(result.code).toContain('//# sourceMappingURL'); + }); + it('passes expected transform options to getCacheKey', () => { config = {...config, transform: [['^.+\\.js$', 'test_preprocessor']]}; const scriptTransformer = new ScriptTransformer(config); diff --git a/packages/jest-transform/src/types.ts b/packages/jest-transform/src/types.ts index 30075298bc26..138bab7f5406 100644 --- a/packages/jest-transform/src/types.ts +++ b/packages/jest-transform/src/types.ts @@ -34,6 +34,7 @@ interface FixedRawSourceMap extends SourceMapWithVersion { version: number; } +// TODO: For Jest 26 normalize this (always structured data, never a string) export type TransformedSource = | {code: string; map?: FixedRawSourceMap | string | null} | string; diff --git a/packages/jest-types/src/Transform.ts b/packages/jest-types/src/Transform.ts index 9c59e7b34489..2e60af1e489d 100644 --- a/packages/jest-types/src/Transform.ts +++ b/packages/jest-types/src/Transform.ts @@ -9,6 +9,6 @@ export type TransformResult = { code: string; originalCode: string; - mapCoverage: boolean; + mapCoverage?: boolean; // TODO - Remove in Jest 26 sourceMapPath: string | null; }; From 58d199d97d084d76aebea9f6b6fb5970a6765635 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 23 Apr 2020 22:44:47 +0200 Subject: [PATCH 35/39] chore: update example to react-native@0.62 (#9746) --- .eslintrc.js | 3 + .../__snapshots__/intro.test.js.snap | 12 - examples/react-native/__tests__/intro.test.js | 16 +- examples/react-native/package.json | 8 +- yarn.lock | 551 ++++++++---------- 5 files changed, 250 insertions(+), 340 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 49eafb955758..d04c2f900797 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -146,4 +146,7 @@ module.exports = { 'prettier/prettier': 2, 'sort-imports': [2, {ignoreDeclarationSort: true}], }, + settings: { + 'import/ignore': ['react-native'], + }, }; diff --git a/examples/react-native/__tests__/__snapshots__/intro.test.js.snap b/examples/react-native/__tests__/__snapshots__/intro.test.js.snap index a66c7c754b14..206581daf942 100644 --- a/examples/react-native/__tests__/__snapshots__/intro.test.js.snap +++ b/examples/react-native/__tests__/__snapshots__/intro.test.js.snap @@ -61,7 +61,6 @@ exports[`renders the FlatList component 1`] = ` initialNumToRender={10} keyExtractor={[Function]} maxToRenderPerBatch={10} - numColumns={1} onContentSizeChange={[Function]} onEndReachedThreshold={2} onLayout={[Function]} @@ -106,17 +105,6 @@ exports[`renders the FlatList component 1`] = ` `; -exports[`renders the Image component 1`] = ` - -`; - exports[`renders the TextInput component 1`] = ` { expect(tree).toMatchSnapshot(); }); -it('renders the Image component', done => { - Image.getSize('path.jpg', (width, height) => { - const tree = renderer.create().toJSON(); - expect(tree).toMatchSnapshot(); - done(); - }); -}); - it('renders the TextInput component', () => { const tree = renderer .create() diff --git a/examples/react-native/package.json b/examples/react-native/package.json index c98a8cbc51db..dc50dbedb875 100644 --- a/examples/react-native/package.json +++ b/examples/react-native/package.json @@ -7,15 +7,15 @@ "test": "jest" }, "dependencies": { - "react": "16.9.0", - "react-native": "0.61.5" + "react": "16.11.0", + "react-native": "0.62.0" }, "devDependencies": { "@babel/core": "*", "@babel/preset-env": "*", "babel-jest": "*", "jest": "*", - "metro-react-native-babel-preset": "*", - "react-test-renderer": "16.9.0" + "metro-react-native-babel-preset": "^0.58.0", + "react-test-renderer": "16.11.0" } } diff --git a/yarn.lock b/yarn.lock index 5cdbc006208c..6f5facb08f43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -77,7 +77,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": +"@babel/generator@^7.5.0", "@babel/generator@^7.9.0", "@babel/generator@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== @@ -846,7 +846,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-typescript@^7.0.0", "@babel/plugin-transform-typescript@^7.9.0": +"@babel/plugin-transform-typescript@^7.5.0", "@babel/plugin-transform-typescript@^7.9.0": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.4.tgz#4bb4dde4f10bbf2d787fce9707fb09b483e33359" integrity sha512-yeWeUkKx2auDbSxRe8MusAG+n4m9BFY/v+lPjmQDgOFX5qnySkUY5oXzkp6FwPdsYqnKay6lorXYdC0n3bZO7w== @@ -2006,89 +2006,93 @@ dependencies: "@types/node" ">= 8" -"@react-native-community/cli-debugger-ui@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-3.0.0.tgz#d01d08d1e5ddc1633d82c7d84d48fff07bd39416" - integrity sha512-m3X+iWLsK/H7/b7PpbNO33eQayR/+M26la4ZbYe1KRke5Umg4PIWsvg21O8Tw4uJcY8LA5hsP+rBi/syBkBf0g== +"@react-native-community/cli-debugger-ui@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-4.7.0.tgz#4a8689f56b99378b24bbbf0ff6a89869d667f013" + integrity sha512-Z/xJ08Wz3J2fKDPrwxtQ44XSHnWsF6dnT0H2AANw63bWjnrR0E3sh8Nk8/oO+j9R7LH8S0+NHJdlniXYtL/bNg== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-platform-android@^3.0.0": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-3.1.4.tgz#61f964dc311623e60b0fb29c5f3732cc8a6f076f" - integrity sha512-ClSdY20F0gzWVLTqCv7vHjnUqOcuq10jd9GgHX6lGSc2GI+Ql3/aQg3tmG4uY3KXNNwAv3U8QCoYgg1WGfwiHA== +"@react-native-community/cli-platform-android@^4.2.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-4.7.0.tgz#aace6b8004b8d3aae40d6affaad1c472e0310a25" + integrity sha512-Lb6D0ipmFwYLJeQy5/NI4uJpeSHw85rd84C40wwpoUfsCgZhA93WUJdFkuQEIDkfTqs5Yqgl+/szhIZdnIXPxw== dependencies: - "@react-native-community/cli-tools" "^3.0.0" - chalk "^2.4.2" + "@react-native-community/cli-tools" "^4.7.0" + chalk "^3.0.0" execa "^1.0.0" + fs-extra "^8.1.0" + glob "^7.1.3" jetifier "^1.6.2" + lodash "^4.17.15" logkitty "^0.6.0" slash "^3.0.0" xmldoc "^1.1.2" -"@react-native-community/cli-platform-ios@^3.0.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-3.2.0.tgz#c469444f5993c9e6737a4b16d78cf033e3702f00" - integrity sha512-pzEnx68H6+mHBq5jsMrr3UmAmkrLSMlC9BZ4yoUdfUXCQq6/R70zNYvH4hjUw8h2Al7Kgq53UzHUsM0ph8TSWQ== +"@react-native-community/cli-platform-ios@^4.2.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-4.7.0.tgz#471dcdbd2645c5650f16c0eddcca50e47ca78398" + integrity sha512-XqnxP6H6+PG/wn4+Pwas5jaTSr5n7x6v8trkPY8iO37b8sq7tJLNYznaBMROF43i0NqO48JdhquYOqnDN8FdBA== dependencies: - "@react-native-community/cli-tools" "^3.0.0" - chalk "^2.4.2" + "@react-native-community/cli-tools" "^4.7.0" + chalk "^3.0.0" + glob "^7.1.3" js-yaml "^3.13.1" + lodash "^4.17.15" + plist "^3.0.1" xcode "^2.0.0" -"@react-native-community/cli-tools@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-3.0.0.tgz#fe48b80822ed7e49b8af051f9fe41e22a2a710b1" - integrity sha512-8IhQKZdf3E4CR8T7HhkPGgorot/cLkRDgneJFDSWk/wCYZAuUh4NEAdumQV7N0jLSMWX7xxiWUPi94lOBxVY9g== +"@react-native-community/cli-tools@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-4.7.0.tgz#83d49277e7f56fef87bdfd0ba55d2cfa20190689" + integrity sha512-llNWJEWXhGMsaHLWoieraPeWuva3kRsIEPi8oRVTybyz82JjR71mN0OFs41o1OnAR6+TR9d5cJPN+mIOESugEA== dependencies: - chalk "^2.4.2" - lodash "^4.17.5" + chalk "^3.0.0" + lodash "^4.17.15" mime "^2.4.1" - node-fetch "^2.5.0" + node-fetch "^2.6.0" -"@react-native-community/cli-types@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-3.0.0.tgz#488d46605cb05e88537e030f38da236eeda74652" - integrity sha512-ng6Tm537E/M42GjE4TRUxQyL8sRfClcL7bQWblOCoxPZzJ2J3bdALsjeG3vDnVCIfI/R0AeFalN9KjMt0+Z/Zg== +"@react-native-community/cli-types@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-4.7.0.tgz#871905753f8ff83cf10c48e8df3fdd63cd7667a0" + integrity sha512-Pw05Rsh/ENFs/Utv1SVRFfdMAn+W9yy1AOhyIKB36JX0Xw00sIZQDyZVsVfmaLSOpRpJ/qUdKWXB/WYV4XYELw== -"@react-native-community/cli@^3.0.0": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-3.2.1.tgz#2a466801eb6080a1f73358c5d740c53c24ed8c6f" - integrity sha512-bZ/bfZ+9r1gQSxp6t7+00DcpC6vmbVYSvzUCFM/yo5k8bhsDdcy8aocscIaXXVGG+v9Edri/Q7hH9ks7L18/Rg== +"@react-native-community/cli@^4.2.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-4.7.0.tgz#be692631356d14fd1ffe23f25b479dca9e8e7c95" + integrity sha512-DbpxcPC7lFCJ112dPXL4DBKh5TfH0QK2OTG7uEGjfsApT4c01Lae6OMTNSssXgXTcNJApqIT5a6GXK2vSE0CEQ== dependencies: "@hapi/joi" "^15.0.3" - "@react-native-community/cli-debugger-ui" "^3.0.0" - "@react-native-community/cli-tools" "^3.0.0" - "@react-native-community/cli-types" "^3.0.0" - chalk "^2.4.2" + "@react-native-community/cli-debugger-ui" "^4.7.0" + "@react-native-community/cli-tools" "^4.7.0" + "@react-native-community/cli-types" "^4.7.0" + chalk "^3.0.0" command-exists "^1.2.8" commander "^2.19.0" compression "^1.7.1" connect "^3.6.5" cosmiconfig "^5.1.0" deepmerge "^3.2.0" - didyoumean "^1.2.1" envinfo "^7.1.0" errorhandler "^1.5.0" execa "^1.0.0" find-up "^4.1.0" - fs-extra "^7.0.1" - glob "^7.1.1" + fs-extra "^8.1.0" + glob "^7.1.3" graceful-fs "^4.1.3" inquirer "^3.0.6" - lodash "^4.17.5" - metro "^0.56.0" - metro-config "^0.56.0" - metro-core "^0.56.0" - metro-react-native-babel-transformer "^0.56.0" + leven "^3.1.0" + lodash "^4.17.15" + metro "^0.58.0" + metro-config "^0.58.0" + metro-core "^0.58.0" + metro-react-native-babel-transformer "^0.58.0" minimist "^1.2.0" mkdirp "^0.5.1" - morgan "^1.9.0" - node-notifier "^5.2.1" + node-stream-zip "^1.9.1" open "^6.2.0" ora "^3.4.0" - plist "^3.0.0" - pretty-format "^25.1.0" + pretty-format "^25.2.0" semver "^6.3.0" serve-static "^1.13.1" shell-quote "1.6.1" @@ -2945,6 +2949,11 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +anser@^1.4.9: + version "1.4.9" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" + integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== + ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" @@ -3255,11 +3264,6 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -art@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2" - integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ== - asap@^2.0.0, asap@~2.0.3, asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -3480,7 +3484,7 @@ babel-preset-current-node-syntax@^0.1.2: "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -babel-preset-fbjs@^3.1.2, babel-preset-fbjs@^3.2.0: +babel-preset-fbjs@^3.2.0, babel-preset-fbjs@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541" integrity sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw== @@ -3569,13 +3573,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" - integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== - dependencies: - safe-buffer "5.1.2" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -4348,15 +4345,6 @@ clipboard@^2.0.0: select "^1.1.2" tiny-emitter "^2.0.0" -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - cliui@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" @@ -4529,9 +4517,9 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: delayed-stream "~1.0.0" command-exists@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" - integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== commander@^2.11.0, commander@^2.19.0, commander@^2.20.0, commander@~2.20.3: version "2.20.3" @@ -5200,9 +5188,9 @@ dateformat@^3.0.0: integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== dayjs@^1.8.15: - version "1.8.24" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.24.tgz#2ef8a2ab9425eaf3318fe78825be1c571027488d" - integrity sha512-bImQZbBv86zcOWOq6fLg7r4aqMx8fScdmykA7cSh+gH1Yh8AM0Dbw0gHYrsOrza6oBBnkK+/OaR+UAa9UsMrDw== + version "1.8.25" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.25.tgz#d09a8696cee7191bc1289e739f96626391b9c73c" + integrity sha512-Pk36juDfQQGDCgr0Lqd1kw15w3OS6xt21JaLPE3lCfsEf8KrERGwDNwvK1tRjrjqFC0uZBJncT4smZQ4F+uV5g== debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -5252,7 +5240,7 @@ decamelize-keys@^1.0.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -5408,11 +5396,6 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -depd@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -5467,11 +5450,6 @@ diacritics-map@^0.1.0: resolved "https://registry.yarnpkg.com/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af" integrity sha1-bfwP+dAQAKLt8oZTccrDFulJd68= -didyoumean@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.1.tgz#e92edfdada6537d484d73c0172fd1eba0c4976ff" - integrity sha1-6S7f2tplN9SE1zwBcv0eugxJdv8= - diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -6175,6 +6153,13 @@ eslint-plugin-react@^7.1.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" +eslint-plugin-relay@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-relay/-/eslint-plugin-relay-1.4.1.tgz#5af2ac13e24bd01ad17b6a4014204918d65021cd" + integrity sha512-yb+p+4AxZTi2gXN7cZRfXMBFlRa5j6TtiVeq3yHXyy+tlgYNpxi/dDrP1+tcUTNP9vdaJovnfGZ5jp6kMiH9eg== + dependencies: + graphql "^14.0.0" + eslint-rule-composer@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" @@ -7445,6 +7430,13 @@ graphql-request@^1.8.2: dependencies: cross-fetch "2.2.2" +graphql@^14.0.0: + version "14.6.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.6.0.tgz#57822297111e874ea12f5cd4419616930cd83e49" + integrity sha512-VKzfvHEKybTKjQVpTFrA5yUq2S9ihcZvfJAtsDBBCuV6wauPu1xl/f9ehgVf0FcEJJs4vz6ysb/ZMkGigQZseg== + dependencies: + iterall "^1.2.2" + gray-matter@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-2.1.1.tgz#3042d9adec2a1ded6a7707a9ed2380f8a17a430e" @@ -7618,10 +7610,10 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -hermes-engine@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.2.1.tgz#25c0f1ff852512a92cb5c5cc47cf967e1e722ea2" - integrity sha512-eNHUQHuadDMJARpaqvlCZoK/Nitpj6oywq3vQ3wCwEsww5morX34mW5PmKWQTO7aU0ck0hgulxR+EVDlXygGxQ== +hermes-engine@~0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.4.1.tgz#2d02b295596298643c4d24b86687eb554db9e950" + integrity sha512-Y3JFC8PD7eN3KpnrzrmvMAqp0IwnZrmP/oGOptvaSu33d7Zq/8b/2lHlZZkNvRl7/I1Q0umTX8TByK7zzLfTXA== hex-color-regex@^1.1.0: version "1.1.0" @@ -8135,11 +8127,6 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" @@ -8690,6 +8677,11 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +iterall@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + jest-get-type@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" @@ -9125,13 +9117,6 @@ lazy-cache@^2.0.2: dependencies: set-getter "^0.1.0" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -9694,13 +9679,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -9804,10 +9782,10 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -metro-babel-register@^0.56.0, metro-babel-register@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.56.4.tgz#b0c627a1cfdd1bdd768f81af79481754e833a902" - integrity sha512-Phm6hMluOWYqfykftjJ1jsTpWvbgb49AC/1taxEctxUdRCZlFgZwBleJZAhQYxJD5J+ikFkEbHDzePEXb29KVA== +metro-babel-register@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.58.0.tgz#5c44786d49a044048df56cf476a2263491d4f53a" + integrity sha512-P5+G3ufhSYL6cA3a7xkbSJzzFBvtivj/PhWvGXFXnuFssDlMAX1CTktff+0gpka5Cd6B6QLt0UAMWulUAAE4Eg== dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -9822,68 +9800,68 @@ metro-babel-register@^0.56.0, metro-babel-register@^0.56.4: core-js "^2.2.2" escape-string-regexp "^1.0.5" -metro-babel-transformer@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.56.4.tgz#fe1d0dc600fcf90201a5bea4d42caea10b801057" - integrity sha512-IOi4ILgZvaX7GCGHBJp79paNVOq5QxhhbyqAdEJgDP8bHfl/OVHoVKSypfrsMSKSiBrqxhIjyc4XjkXsQtkx5g== +metro-babel-transformer@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.58.0.tgz#317c83b863cceb0573943815f1711fbcbe69b106" + integrity sha512-yBX3BkRhw2TCNPhe+pmLSgsAEA3huMvnX08UwjFqSXXI1aiqzRQobn92uKd1U5MM1Vx8EtXVomlJb95ZHNAv6A== dependencies: "@babel/core" "^7.0.0" - metro-source-map "^0.56.4" + metro-source-map "0.58.0" -metro-cache@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.56.4.tgz#542f9f8a35f8fb9d5576f46fd3ab4d4f42851a7e" - integrity sha512-d1hiUSKwtRsuMxUhHVJ3tjK2BbpUlJGvTyMWohK8Wxx+0GbnWRWWFcI4vlCzlZfoK0VtZK2MJEl5t7Du1mIniQ== +metro-cache@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.58.0.tgz#630ea0a4626dfb9591c71fdb85dce14b5e9a04ec" + integrity sha512-jjW9zCTKxhgKcVkyQ6LHyna9Zdf4TK/45vvT1fPyyTk1RY82ZYjU1qs+84ycKEd08Ka4YcK9xcUew9SIDJYI8Q== dependencies: jest-serializer "^24.4.0" - metro-core "^0.56.4" + metro-core "0.58.0" mkdirp "^0.5.1" rimraf "^2.5.4" -metro-config@^0.56.0, metro-config@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.56.4.tgz#338fd8165fba59424cec427c1a881757945e57e9" - integrity sha512-O85QDHwWdMn/8ERe13y4a6vbZL0AHyO8atTvL+9BCulLEO+FQBi1iJjr3+ViLa8cf0m5dRftDsa7P47m5euk4A== +metro-config@0.58.0, metro-config@^0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.58.0.tgz#1e24b43a5a00971d75662b1a0d3c04a13d4a1746" + integrity sha512-4vgBliXwL56vjUlYplvGMVSNrJJpkHuLcD+O20trV3FvPxKg4ZsvuOcNSxqDSMU26FCtIEJ15ojcuCbRL7KY0w== dependencies: cosmiconfig "^5.0.5" jest-validate "^24.7.0" - metro "^0.56.4" - metro-cache "^0.56.4" - metro-core "^0.56.4" + metro "0.58.0" + metro-cache "0.58.0" + metro-core "0.58.0" pretty-format "^24.7.0" -metro-core@^0.56.0, metro-core@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.56.4.tgz#67cc41b3c0bf66e9c2306f50239a1080b1e82312" - integrity sha512-hMzkBdgPt5Zm9nr/1KtIT+A6H7TNiLVCEGG5OiAXj8gTRsA2yy7wAdQpwy0xbE+zi88t/pLOzXpd3ClG/YxyWg== +metro-core@0.58.0, metro-core@^0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.58.0.tgz#ad9f6645a2b439a3fbce7ce4e19b01b00375768a" + integrity sha512-RzXUjGFmCLOyzUqcKDvr91AldGtIOxnzNZrWUIiG8uC3kerVLo0mQp4YH3+XVm6fMNiLMg6iER7HLqD+MbpUjQ== dependencies: jest-haste-map "^24.7.1" lodash.throttle "^4.1.1" - metro-resolver "^0.56.4" + metro-resolver "0.58.0" wordwrap "^1.0.0" -metro-inspector-proxy@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.56.4.tgz#7343ff3c5908af4fd99e96b6d646e24e99816be4" - integrity sha512-E1S3MO25mWKmcLn1UQuCDiS0hf9P2Fwq8sEAX5lBLoZbehepNH+4xJ3xXSY51JX4dozBrE8GGoKL4ll3II40LA== +metro-inspector-proxy@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.58.0.tgz#6fefb0cdf25655919d56c82ebe09cd26eb00e636" + integrity sha512-oFqTyNTJdCdvcw1Ha6SKE7ITbSaoTbO4xpYownIoJR+WZ0ZfxbWpp225JkHuBJm9UcBAnG9c0CME924m3uBbaw== dependencies: connect "^3.6.5" debug "^2.2.0" rxjs "^5.4.3" ws "^1.1.5" - yargs "^9.0.0" + yargs "^14.2.0" -metro-minify-uglify@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.56.4.tgz#13589dfb1d43343608aacb7f78ddfcc052daa63c" - integrity sha512-BHgj7+BKEK2pHvWHUR730bIrsZwl8DPtr49x9L0j2grPZ5/UROWXzEr8VZgIss7fl64t845uu1HXNNyuSj2EhA== +metro-minify-uglify@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.58.0.tgz#7e1066954bfd4f767ba6aca7feef676ca44c68b8" + integrity sha512-vRHsA7bCi7eCn3LXLm20EfY2NoWDyYOnmWaq/N8LB0OxL2L5DXRqMYAQK+prWGJ5S1yvVnDuuNVP+peQ9851TA== dependencies: uglify-es "^3.1.9" -metro-react-native-babel-preset@*, metro-react-native-babel-preset@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.56.4.tgz#dcedc64b7ff5c0734839458e70eb0ebef6d063a8" - integrity sha512-CzbBDM9Rh6w8s1fq+ZqihAh7DDqUAcfo9pPww25+N/eJ7UK436Q7JdfxwdIPpBwLFn6o6MyYn+uwL9OEWBJarA== +metro-react-native-babel-preset@0.58.0, metro-react-native-babel-preset@^0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.58.0.tgz#18f48d33fe124280ffabc000ab8b42c488d762a2" + integrity sha512-MRriNW+fF6jxABsgPphocUY6mIhmCm8idcrQZ58fT3Iti2vCdtkaK32TyCGUNUptzhUe2/cbE57j4aC+eaodAA== dependencies: "@babel/plugin-proposal-class-properties" "^7.0.0" "@babel/plugin-proposal-export-default-from" "^7.0.0" @@ -9916,60 +9894,61 @@ metro-react-native-babel-preset@*, metro-react-native-babel-preset@^0.56.4: "@babel/plugin-transform-spread" "^7.0.0" "@babel/plugin-transform-sticky-regex" "^7.0.0" "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typescript" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" "@babel/plugin-transform-unicode-regex" "^7.0.0" "@babel/template" "^7.0.0" react-refresh "^0.4.0" -metro-react-native-babel-transformer@^0.56.0: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.56.4.tgz#3c6e48b605c305362ee624e45ff338656e35fc1d" - integrity sha512-ng74eutuy1nyGI9+TDzzVAVfEmNPDlapV4msTQMKPi4EFqo/fBn7Ct33ME9l5E51pQBBnxt/UwcpTvd13b29kQ== +metro-react-native-babel-transformer@0.58.0, metro-react-native-babel-transformer@^0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.58.0.tgz#5da0e5a1b83c01d11626905fa59f34fda53a21a5" + integrity sha512-3A73+cRq1eUPQ8g+hPNGgMUMCGmtQjwqHfoG1DwinAoJ/kr4WOXWWbGZo0xHJNBe/zdHGl0uHcDCp2knPglTdQ== dependencies: "@babel/core" "^7.0.0" - babel-preset-fbjs "^3.1.2" - metro-babel-transformer "^0.56.4" - metro-react-native-babel-preset "^0.56.4" - metro-source-map "^0.56.4" + babel-preset-fbjs "^3.3.0" + metro-babel-transformer "0.58.0" + metro-react-native-babel-preset "0.58.0" + metro-source-map "0.58.0" -metro-resolver@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.56.4.tgz#9876f57bca37fd1bfcffd733541e2ee4a89fad7f" - integrity sha512-Ug4ulVfpkKZ1Wu7mdYj9XLGuOqZTuWCqEhyx3siKTc/2eBwKZQXmiNo5d/IxWNvmwL/87Abeb724I6CMzMfjiQ== +metro-resolver@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.58.0.tgz#4d03edc52e2e25d45f16688adf3b3f268ea60df9" + integrity sha512-XFbAKvCHN2iWqKeiRARzEXn69eTDdJVJC7lu16S4dPQJ+Dy82dZBr5Es12iN+NmbJuFgrAuIHbpWrdnA9tOf6Q== dependencies: absolute-path "^0.0.0" -metro-source-map@^0.56.0, metro-source-map@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.56.4.tgz#868ccac3f3519fe14eca358bc186f63651b2b9bc" - integrity sha512-f1P9/rpFmG3Z0Jatiw2zvLItx1TwR7mXTSDj4qLDCWeVMB3kEXAr3R0ucumTW8c6HfpJljeRBWzYFXF33fd81g== +metro-source-map@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.58.0.tgz#e951b99f4c653239ce9323bb08339c6f1978a112" + integrity sha512-yvN1YPmejmgiiS7T1aKBiiUTHPw2Vcm3r2TZ+DY92z/9PR4alysIywrCs/fTHs8rbDcKM5VfPCKGLpkBrbKeOw== dependencies: "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" invariant "^2.2.4" - metro-symbolicate "^0.56.4" - ob1 "^0.56.4" + metro-symbolicate "0.58.0" + ob1 "0.58.0" source-map "^0.5.6" vlq "^1.0.0" -metro-symbolicate@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.56.4.tgz#53e9d40beac9049fa75a3e620ddd47d4907ff015" - integrity sha512-8mCNNn6zV5FFKCIcRgI7736Xl+owgvYuy8qanPxZN36f7utiWRYeB+PirEBPcglBk4qQvoy2lT6oPULNXZQbbQ== +metro-symbolicate@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.58.0.tgz#ba9fd52549c41fc1b656adaad7c8875726dd5abe" + integrity sha512-uIVxUQC1E26qOMj13dKROhwAa2FmZk5eR0NcBqej/aXmQhpr8LjJg2sondkoLKUp827Tf/Fm9+pS4icb5XiqCw== dependencies: invariant "^2.2.4" - metro-source-map "^0.56.4" + metro-source-map "0.58.0" source-map "^0.5.6" through2 "^2.0.1" vlq "^1.0.0" -metro@^0.56.0, metro@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/metro/-/metro-0.56.4.tgz#be7e1380ee6ac3552c25ead8098eab261029e4d7" - integrity sha512-Kt3OQJQtQdts0JrKnyGdLpKHDjqYBgIfzvYrvfhmFCkKuZ8aqRlVnvpfjQ4/OBm0Fmm9NyyxbNRD9VIbj7WjnA== +metro@0.58.0, metro@^0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.58.0.tgz#c037318c112f80dc96199780c8b401ab72cfd142" + integrity sha512-yi/REXX+/s4r7RjzXht+E+qE6nzvFIrEXO5Q61h+70Q7RODMU8EnlpXx04JYk7DevHuMhFaX+NWhCtRINzR4zA== dependencies: + "@babel/code-frame" "^7.0.0" "@babel/core" "^7.0.0" - "@babel/generator" "^7.0.0" + "@babel/generator" "^7.5.0" "@babel/parser" "^7.0.0" "@babel/plugin-external-helpers" "^7.0.0" "@babel/template" "^7.0.0" @@ -9977,9 +9956,10 @@ metro@^0.56.0, metro@^0.56.4: "@babel/types" "^7.0.0" absolute-path "^0.0.0" async "^2.4.0" - babel-preset-fbjs "^3.1.2" + babel-preset-fbjs "^3.3.0" buffer-crc32 "^0.2.13" chalk "^2.4.1" + ci-info "^2.0.0" concat-stream "^1.6.0" connect "^3.6.5" debug "^2.2.0" @@ -9995,32 +9975,33 @@ metro@^0.56.0, metro@^0.56.4: json-stable-stringify "^1.0.1" lodash.throttle "^4.1.1" merge-stream "^1.0.1" - metro-babel-register "^0.56.4" - metro-babel-transformer "^0.56.4" - metro-cache "^0.56.4" - metro-config "^0.56.4" - metro-core "^0.56.4" - metro-inspector-proxy "^0.56.4" - metro-minify-uglify "^0.56.4" - metro-react-native-babel-preset "^0.56.4" - metro-resolver "^0.56.4" - metro-source-map "^0.56.4" - metro-symbolicate "^0.56.4" + metro-babel-register "0.58.0" + metro-babel-transformer "0.58.0" + metro-cache "0.58.0" + metro-config "0.58.0" + metro-core "0.58.0" + metro-inspector-proxy "0.58.0" + metro-minify-uglify "0.58.0" + metro-react-native-babel-preset "0.58.0" + metro-resolver "0.58.0" + metro-source-map "0.58.0" + metro-symbolicate "0.58.0" mime-types "2.1.11" mkdirp "^0.5.1" node-fetch "^2.2.0" - nullthrows "^1.1.0" + nullthrows "^1.1.1" resolve "^1.5.0" rimraf "^2.5.4" serialize-error "^2.1.0" source-map "^0.5.6" + strip-ansi "^4.0.0" temp "0.8.3" throat "^4.1.0" wordwrap "^1.0.0" write-file-atomic "^1.2.0" ws "^1.1.5" xpipe "^1.0.5" - yargs "^9.0.0" + yargs "^14.2.0" microevent.ts@~0.1.1: version "0.1.1" @@ -10303,17 +10284,6 @@ moo@^0.5.0: resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== -morgan@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" - integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== - dependencies: - basic-auth "~2.0.1" - debug "2.6.9" - depd "~2.0.0" - on-finished "~2.3.0" - on-headers "~1.0.2" - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -10466,7 +10436,7 @@ node-fetch@^1.0.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0: +node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== @@ -10527,17 +10497,6 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-notifier@^5.2.1: - version "5.4.3" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" - integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== - dependencies: - growly "^1.3.0" - is-wsl "^1.1.0" - semver "^5.5.0" - shellwords "^0.1.1" - which "^1.3.0" - node-notifier@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-6.0.0.tgz#cea319e06baa16deec8ce5cd7f133c4a46b68e12" @@ -10554,6 +10513,11 @@ node-releases@^1.1.29, node-releases@^1.1.53: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== +node-stream-zip@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/node-stream-zip/-/node-stream-zip-1.9.1.tgz#66d210204da7c60e2d6d685eb21a11d016981fd0" + integrity sha512-7/Xs9gkuYF0WBimz5OrSc6UVKLDTxvBG2yLGtEK8PSx94d86o/6iQLvIe/140ATz35JDqHKWIxh3GcA3u5hB0w== + nopt@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" @@ -10696,7 +10660,7 @@ nth-check@^1.0.2, nth-check@~1.0.1: dependencies: boolbase "~1.0.0" -nullthrows@^1.1.0: +nullthrows@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== @@ -10721,10 +10685,10 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -ob1@^0.56.4: - version "0.56.4" - resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.56.4.tgz#c4acb3baa42f4993a44b35b2da7c8ef443dcccec" - integrity sha512-URgFof9z2wotiYFsqlydXtQfGV81gvBI2ODy64xfd3vPo+AYom5PVDX4t4zn23t/O+S2IxqApSQM8uJAybmz7w== +ob1@0.58.0: + version "0.58.0" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.58.0.tgz#484a1e9a63a8b79d9ea6f3a83b2a42110faac973" + integrity sha512-uZP44cbowAfHafP1k4skpWItk5iHCoRevMfrnUvYCfyNNPPJd3rfDCyj0exklWi2gDXvjlj2ObsfiqP/bs/J7Q== object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" @@ -10957,15 +10921,6 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -11452,7 +11407,7 @@ platform@^1.3.3: resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444" integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q== -plist@^3.0.0, plist@^3.0.1: +plist@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/plist/-/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" integrity sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ== @@ -12153,67 +12108,69 @@ react-dev-utils@^9.1.0: strip-ansi "5.2.0" text-table "0.2.0" -react-devtools-core@^3.6.3: - version "3.6.3" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-3.6.3.tgz#977d95b684c6ad28205f0c62e1e12c5f16675814" - integrity sha512-+P+eFy/yo8Z/UH9J0DqHZuUM5+RI2wl249TNvMx3J2jpUomLQa4Zxl56GEotGfw3PIP1eI+hVf1s53FlUONStQ== +react-devtools-core@^4.0.6: + version "4.6.0" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.6.0.tgz#2443b3c6fac78b801702af188abc6d83d56224e6" + integrity sha512-sjR3KC5VvGV7X6vzR3OTutPT5VeBcSKwoIXUwihpl1Nb4dkmweEbzCTPx2PYMVAqc+NZ5tPGhqBzXV+iGg5CNA== dependencies: shell-quote "^1.6.1" - ws "^3.3.1" + ws "^7" react-dom@*, react-dom@^16.8.4: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.9.0.tgz#5e65527a5e26f22ae3701131bcccaee9fb0d3962" - integrity sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ== + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.11.0.tgz#7e7c4a5a85a569d565c2462f5d345da2dd849af5" + integrity sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" prop-types "^15.6.2" - scheduler "^0.15.0" + scheduler "^0.17.0" react-error-overlay@^6.0.3: version "6.0.7" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108" integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA== -react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-native@0.61.5: - version "0.61.5" - resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.61.5.tgz#6e21acb56cbd75a3baeb1f70201a66f42600bba8" - integrity sha512-MXqE3NoGO0T3dUKIKkIppijBhRRMpfN6ANbhMXHDuyfA+fSilRWgCwYgR/YNCC7ntECoJYikKaNTUBB0DeQy6Q== +react-native@0.62.0: + version "0.62.0" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.62.0.tgz#166dcab76f0b5ae36a4d7046de2cbfecfdc610f1" + integrity sha512-P21YHLaRkXTiS4xuC0BAdpwIJc8r0acYWUAOCBApqG3H4eiBe/d3b0oADz8EwTu6jBtoebydabJlScu0b/59bg== dependencies: "@babel/runtime" "^7.0.0" - "@react-native-community/cli" "^3.0.0" - "@react-native-community/cli-platform-android" "^3.0.0" - "@react-native-community/cli-platform-ios" "^3.0.0" + "@react-native-community/cli" "^4.2.0" + "@react-native-community/cli-platform-android" "^4.2.0" + "@react-native-community/cli-platform-ios" "^4.2.0" abort-controller "^3.0.0" - art "^0.10.0" + anser "^1.4.9" base64-js "^1.1.2" connect "^3.6.5" create-react-class "^15.6.3" escape-string-regexp "^1.0.5" + eslint-plugin-relay "1.4.1" event-target-shim "^5.0.1" fbjs "^1.0.0" fbjs-scripts "^1.1.0" - hermes-engine "^0.2.1" + hermes-engine "~0.4.0" invariant "^2.2.4" jsc-android "^245459.0.0" - metro-babel-register "^0.56.0" - metro-react-native-babel-transformer "^0.56.0" - metro-source-map "^0.56.0" - nullthrows "^1.1.0" + metro-babel-register "0.58.0" + metro-react-native-babel-transformer "0.58.0" + metro-source-map "0.58.0" + nullthrows "^1.1.1" pretty-format "^24.7.0" promise "^7.1.1" prop-types "^15.7.2" - react-devtools-core "^3.6.3" + react-devtools-core "^4.0.6" react-refresh "^0.4.0" regenerator-runtime "^0.13.2" - scheduler "0.15.0" + scheduler "0.17.0" stacktrace-parser "^0.1.3" + use-subscription "^1.0.0" whatwg-fetch "^3.0.0" react-refresh@^0.4.0: @@ -12221,20 +12178,20 @@ react-refresh@^0.4.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.4.2.tgz#54a277a6caaac2803d88f1d6f13c1dcfbd81e334" integrity sha512-kv5QlFFSZWo7OlJFNYbxRtY66JImuP2LcrFgyJfQaf85gSP+byzG21UbDQEYjU7f//ny8rwiEkO6py2Y+fEgAQ== -react-test-renderer@*, react-test-renderer@16.9.0, react-test-renderer@^16.0.0-0: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.9.0.tgz#7ed657a374af47af88f66f33a3ef99c9610c8ae9" - integrity sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ== +react-test-renderer@*, react-test-renderer@16.11.0, react-test-renderer@^16.0.0-0: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.11.0.tgz#72574566496462c808ac449b0287a4c0a1a7d8f8" + integrity sha512-nh9gDl8R4ut+ZNNb2EeKO5VMvTKxwzurbSMuGBoKtjpjbg8JK/u3eVPVNi1h1Ue+eYK9oSzJjb+K3lzLxyA4ag== dependencies: object-assign "^4.1.1" prop-types "^15.6.2" - react-is "^16.9.0" - scheduler "^0.15.0" + react-is "^16.8.6" + scheduler "^0.17.0" -react@*, react@16.9.0, react@^16.8.4: - version "16.9.0" - resolved "https://registry.yarnpkg.com/react/-/react-16.9.0.tgz#40ba2f9af13bc1a38d75dbf2f4359a5185c4f7aa" - integrity sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w== +react@*, react@16.11.0, react@^16.8.4: + version "16.11.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.11.0.tgz#d294545fe62299ccee83363599bf904e4a07fdbb" + integrity sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -12916,10 +12873,10 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" -scheduler@0.15.0, scheduler@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.15.0.tgz#6bfcf80ff850b280fed4aeecc6513bc0b4f17f8e" - integrity sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg== +scheduler@0.17.0, scheduler@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.17.0.tgz#7c9c673e4ec781fac853927916d1c426b6f3ddfe" + integrity sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" @@ -14630,6 +14587,13 @@ urlgrey@0.4.4: resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= +use-subscription@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.4.1.tgz#edcbcc220f1adb2dd4fa0b2f61b6cc308e620069" + integrity sha512-7+IIwDG/4JICrWHL/Q/ZPK5yozEnvRm6vHImu0LKwQlmWGKeiF7mbAenLlK/cTNXrTtXHU/SFASQHzB6+oSJMQ== + dependencies: + object-assign "^4.1.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -14938,7 +14902,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1, which@^1.2.1, which@^1.2.9, which@^1.3.0, which@^1.3.1: +which@1.3.1, which@^1.2.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -15106,7 +15070,12 @@ ws@^1.1.0, ws@^1.1.5: options ">=0.0.5" ultron "1.0.x" -ws@^3.3.1, ws@~3.3.1: +ws@^7, ws@^7.0.0: + version "7.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" + integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== + +ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== @@ -15115,11 +15084,6 @@ ws@^3.3.1, ws@~3.3.1: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^7.0.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" - integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== - x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" @@ -15199,11 +15163,6 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -15266,13 +15225,6 @@ yargs-parser@^18.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - integrity sha1-jQrELxbqVd69MyyvTEA4s+P139k= - dependencies: - camelcase "^4.1.0" - yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" @@ -15316,7 +15268,7 @@ yargs@^12.0.5: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^14.2.2: +yargs@^14.2.0, yargs@^14.2.2: version "14.2.3" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== @@ -15357,25 +15309,6 @@ yargs@^2.3.0: dependencies: wordwrap "0.0.2" -yargs@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-9.0.1.tgz#52acc23feecac34042078ee78c0c007f5085db4c" - integrity sha1-UqzCP+7Kw0BCB47njAwAf1CF20w= - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From 6cbd3cbbb4a6d261b65f8eec034146e4be426ff2 Mon Sep 17 00:00:00 2001 From: ychi Date: Thu, 23 Apr 2020 22:56:18 +0200 Subject: [PATCH 36/39] noCodeFrame respects noStackTrace (#9866) --- CHANGELOG.md | 1 + .../__snapshots__/messages.test.ts.snap | 21 +++++ .../src/__tests__/messages.test.ts | 78 ++++++++++++++++++- packages/jest-message-util/src/index.ts | 3 +- 4 files changed, 100 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c318022f32db..811c9fde335c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +- `[jest-message-util]` Code frame printing should respect `--noStackTrace` flag ([#9866](https://github.com/facebook/jest/pull/9866)) - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) - `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) - `[jest-transform]` Improve source map handling when instrumenting transformed code ([#9811](https://github.com/facebook/jest/pull/9811)) diff --git a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap index 490db062e6fb..99256df0436c 100644 --- a/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap +++ b/packages/jest-message-util/src/__tests__/__snapshots__/messages.test.ts.snap @@ -35,6 +35,27 @@ exports[`formatStackTrace should strip node internals 1`] = ` " `; +exports[`getConsoleOutput does not print code frame when noCodeFrame = true 1`] = ` +" + at Object. (file.js:1:7) + " +`; + +exports[`getConsoleOutput does not print codeframe when noStackTrace = true 1`] = ` +" + at Object. (file.js:1:7) + " +`; + +exports[`getConsoleOutput prints code frame and stacktrace 1`] = ` +" + > 1 | throw new Error(\\"Whoops!\\"); + | ^ + + at Object. (file.js:1:7) + " +`; + exports[`no codeframe 1`] = ` " ● Test suite failed to run diff --git a/packages/jest-message-util/src/__tests__/messages.test.ts b/packages/jest-message-util/src/__tests__/messages.test.ts index 41a14d0100da..e4b3d3bf8dad 100644 --- a/packages/jest-message-util/src/__tests__/messages.test.ts +++ b/packages/jest-message-util/src/__tests__/messages.test.ts @@ -9,7 +9,7 @@ import {readFileSync} from 'fs'; import slash = require('slash'); import tempy = require('tempy'); -import {formatExecError, formatResultsErrors} from '..'; +import {formatExecError, formatResultsErrors, formatStackTrace} from '..'; const rootDir = tempy.directory(); @@ -289,3 +289,79 @@ it('no stack', () => { expect(message).toMatchSnapshot(); }); + +describe('getConsoleOutput', () => { + it('prints code frame and stacktrace', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + const message = formatStackTrace( + ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + `, + { + rootDir, + testMatch: [], + }, + { + noCodeFrame: false, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); + }); + + it('does not print code frame when noCodeFrame = true', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + const message = formatStackTrace( + ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + `, + { + rootDir, + testMatch: [], + }, + { + noCodeFrame: true, + noStackTrace: false, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); + }); + + it('does not print codeframe when noStackTrace = true', () => { + readFileSync.mockImplementationOnce(() => 'throw new Error("Whoops!");'); + const message = formatStackTrace( + ` + at Object. (${slash(rootDir)}/file.js:1:7) + at Module._compile (internal/modules/cjs/loader.js:1158:30) + at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10) + at Module.load (internal/modules/cjs/loader.js:1002:32) + at Function.Module._load (internal/modules/cjs/loader.js:901:14) + at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12) + `, + { + rootDir, + testMatch: [], + }, + { + noStackTrace: true, + }, + 'path_test', + ); + + expect(message).toMatchSnapshot(); + }); +}); diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index b3c1fbb5967b..e205c823d648 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -283,9 +283,8 @@ export const formatStackTrace = ( ? slash(path.relative(config.rootDir, testPath)) : null; - if (!options.noCodeFrame) { + if (!options.noStackTrace && !options.noCodeFrame) { const topFrame = getTopFrame(lines); - if (topFrame) { const {column, file: filename, line} = topFrame; From c024dec130d9914dcc3418ea74c26f667db3dbfa Mon Sep 17 00:00:00 2001 From: Jack Bates Date: Fri, 24 Apr 2020 00:53:25 -0700 Subject: [PATCH 37/39] fix: don't /// (#9875) --- CHANGELOG.md | 1 + package.json | 1 + packages/jest-environment/tsconfig.json | 2 + scripts/buildTs.js | 65 +++++++++++++++--- yarn.lock | 89 +++++++++++++++++++++++-- 5 files changed, 145 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811c9fde335c..29ccfffca4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixes +- `[@jest/environment]` Make sure not to reference Jest types ([#9875](https://github.com/facebook/jest/pull/9875)) - `[jest-message-util]` Code frame printing should respect `--noStackTrace` flag ([#9866](https://github.com/facebook/jest/pull/9866)) - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) - `[jest-runtime]` Support importing parallel dynamic `import`s ([#9858](https://github.com/facebook/jest/pull/9858)) diff --git a/package.json b/package.json index 3e5841ea2d8c..8658d7699537 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "fast-check": "^1.13.0", "find-process": "^1.4.1", "glob": "^7.1.1", + "globby": "^10.0.2", "graceful-fs": "^4.2.3", "isbinaryfile": "^4.0.0", "istanbul-lib-coverage": "^3.0.0", diff --git a/packages/jest-environment/tsconfig.json b/packages/jest-environment/tsconfig.json index 658545960324..efa01e2b2db4 100644 --- a/packages/jest-environment/tsconfig.json +++ b/packages/jest-environment/tsconfig.json @@ -1,6 +1,8 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + // we don't want `@types/jest` to be referenced + "types": ["node"], "rootDir": "src", "outDir": "build" }, diff --git a/scripts/buildTs.js b/scripts/buildTs.js index af57239ed718..9f8ed9c3c7cb 100644 --- a/scripts/buildTs.js +++ b/scripts/buildTs.js @@ -11,13 +11,17 @@ const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); +const util = require('util'); const chalk = require('chalk'); const execa = require('execa'); +const globby = require('globby'); const rimraf = require('rimraf'); const throat = require('throat'); const {getPackages} = require('./buildUtils'); +const readFilePromise = util.promisify(fs.readFile); + const packages = getPackages(); const packagesWithTs = packages.filter(p => @@ -64,23 +68,66 @@ try { return; } -const downlevelArgs = ['--silent', 'downlevel-dts', 'build', 'build/ts3.4']; - -console.log(chalk.inverse(' Downleveling TypeScript definition files ')); - // we want to limit the number of processes we spawn const cpus = Math.max(1, os.cpus().length - 1); Promise.all( packagesWithTs.map( - throat(cpus, pkgDir => { - // otherwise we get nested `ts3.4` directories - rimraf.sync(path.resolve(pkgDir, 'build/ts3.4')); - - return execa('yarn', downlevelArgs, {cwd: pkgDir, stdio: 'inherit'}); + throat(cpus, async pkgDir => { + const buildDir = path.resolve(pkgDir, 'build/**/*.d.ts'); + const ts3dot4 = path.resolve(pkgDir, 'build/ts3.4'); + + const globbed = await globby([buildDir, `!${ts3dot4}`]); + + const files = await Promise.all( + globbed.map(file => Promise.all([file, readFilePromise(file, 'utf8')])), + ); + + const filesWithReferences = files + .filter(([, content]) => content.includes('/// [ + name, + content + .split('\n') + .filter(line => line !== '/// ') + .filter(line => line.includes('/// content.length > 0) + .filter(hit => hit.length > 0) + .map(([file, references]) => + chalk.red( + `${chalk.bold( + file, + )} has the following non-node type references:\n\n${references}\n`, + ), + ) + .join('\n\n'); + + if (filesWithReferences) { + console.error(filesWithReferences); + + process.exit(1); + } }), ), ) + .then(() => { + const downlevelArgs = ['--silent', 'downlevel-dts', 'build', 'build/ts3.4']; + + console.log(chalk.inverse(' Downleveling TypeScript definition files ')); + + return Promise.all( + packagesWithTs.map( + throat(cpus, pkgDir => { + // otherwise we get nested `ts3.4` directories + rimraf.sync(path.resolve(pkgDir, 'build/ts3.4')); + + return execa('yarn', downlevelArgs, {cwd: pkgDir, stdio: 'inherit'}); + }), + ), + ); + }) .then(() => { console.log( chalk.inverse.green( diff --git a/yarn.lock b/yarn.lock index 6f5facb08f43..3f604de1b915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1899,11 +1899,32 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@octokit/auth-token@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.0.tgz#b64178975218b99e4dfe948253f0673cbbb59d9f" @@ -3228,6 +3249,11 @@ array-union@^1.0.1, array-union@^1.0.2: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -5484,6 +5510,13 @@ dir-glob@^2.2.2: dependencies: path-type "^3.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + discontinuous-range@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" @@ -6576,6 +6609,18 @@ fast-glob@^2.0.2, fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.0.3: + version "3.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" + integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -6586,6 +6631,13 @@ fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" + integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ== + dependencies: + reusify "^1.0.4" + faye-websocket@~0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -7263,7 +7315,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -7340,6 +7392,20 @@ globby@8.0.2, globby@^8.0.1: pify "^3.0.0" slash "^1.0.0" +globby@^10.0.2: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -7819,7 +7885,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.5: +ignore@^5.0.5, ignore@^5.1.1: version "5.1.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== @@ -9772,7 +9838,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3: +merge2@^1.2.3, merge2@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== @@ -11314,6 +11380,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -11335,7 +11406,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -12705,6 +12776,11 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rfdc@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" @@ -12774,6 +12850,11 @@ run-async@^2.2.0, run-async@^2.4.0: dependencies: is-promise "^2.1.0" +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" From 3f107a33775cdff94cab6993741e3a1a22e00aa0 Mon Sep 17 00:00:00 2001 From: "Yi-Shan, Chen" Date: Sun, 26 Apr 2020 17:17:25 +0800 Subject: [PATCH 38/39] Show coverage of sources related to tests in changed files (#9769) * Add findRelatdSourcesFromTestsInChangedFiles in SearchSource * check sourcesRelatedToTestsInChangedFiles in shouldInstrument * Add tests for findRelatedSourcesFromTestsInChangedFiles * Update CHANGELOG.md * Address code review suggestion * Use hasSCM utility in SearchSource.findTestRelatedToChangeFiles * Create searchSources at first for reuse in runJest * Create and keep DependencyResolver in SearchSource for reuse * Address code review suggestion --- CHANGELOG.md | 1 + e2e/__tests__/onlyChanged.test.ts | 33 ++++++++++ packages/jest-core/src/SearchSource.ts | 59 ++++++++++++++---- packages/jest-core/src/TestScheduler.ts | 13 +++- .../src/__tests__/SearchSource.test.ts | 60 +++++++++++++++++++ packages/jest-core/src/runJest.ts | 29 ++++++--- .../src/__tests__/coverage_worker.test.js | 1 + .../jest-reporters/src/coverage_reporter.ts | 3 + .../jest-reporters/src/coverage_worker.ts | 4 +- .../src/generateEmptyCoverage.ts | 2 + packages/jest-reporters/src/types.ts | 2 + packages/jest-runner/src/runTest.ts | 4 +- packages/jest-runner/src/types.ts | 1 + packages/jest-runtime/src/index.ts | 1 + .../jest-transform/src/shouldInstrument.ts | 7 ++- packages/jest-transform/src/types.ts | 1 + 16 files changed, 195 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29ccfffca4ae..9dcacb217199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Features - `[@jest/globals]` New package so Jest's globals can be explicitly imported ([#9801](https://github.com/facebook/jest/pull/9801)) +- `[jest-core]` Show coverage of sources related to tests in changed files ([#9769](https://github.com/facebook/jest/pull/9769)) - `[jest-runtime]` Populate `require.cache` ([#9841](https://github.com/facebook/jest/pull/9841)) ### Fixes diff --git a/e2e/__tests__/onlyChanged.test.ts b/e2e/__tests__/onlyChanged.test.ts index 52abdd6d0613..947a11d50ddc 100644 --- a/e2e/__tests__/onlyChanged.test.ts +++ b/e2e/__tests__/onlyChanged.test.ts @@ -137,6 +137,39 @@ test('report test coverage for only changed files', () => { expect(stdout).not.toMatch('b.js'); }); +test('report test coverage of source on test file change under only changed files', () => { + writeFiles(DIR, { + '__tests__/a.test.js': ` + require('../a'); + test('a1', () => expect(1).toBe(1)); + `, + 'a.js': 'module.exports = {}', + 'package.json': JSON.stringify({ + jest: { + collectCoverage: true, + coverageReporters: ['text'], + testEnvironment: 'node', + }, + }), + }); + + run(`${GIT} init`, DIR); + run(`${GIT} add .`, DIR); + run(`${GIT} commit --no-gpg-sign -m "first"`, DIR); + + writeFiles(DIR, { + '__tests__/a.test.js': ` + require('../a'); + test('a1', () => expect(1).toBe(1)); + test('a2', () => expect(2).toBe(2)); + `, + }); + + const {stdout} = runJest(DIR, ['--only-changed']); + + expect(stdout).toMatch('a.js'); +}); + test('do not pickup non-tested files when reporting coverage on only changed files', () => { writeFiles(DIR, { 'a.js': 'module.exports = {}', diff --git a/packages/jest-core/src/SearchSource.ts b/packages/jest-core/src/SearchSource.ts index ba70f4ce021d..48c630f2adb4 100644 --- a/packages/jest-core/src/SearchSource.ts +++ b/packages/jest-core/src/SearchSource.ts @@ -51,13 +51,22 @@ const toTests = (context: Context, tests: Array) => path, })); +const hasSCM = (changedFilesInfo: ChangedFiles) => { + const {repos} = changedFilesInfo; + // no SCM (git/hg/...) is found in any of the roots. + const noSCM = Object.values(repos).every(scm => scm.size === 0); + return !noSCM; +}; + export default class SearchSource { private _context: Context; + private _dependencyResolver: DependencyResolver | null; private _testPathCases: TestPathCases = []; constructor(context: Context) { const {config} = context; this._context = context; + this._dependencyResolver = null; const rootPattern = new RegExp( config.roots.map(dir => escapePathForRegex(dir + path.sep)).join('|'), @@ -92,6 +101,17 @@ export default class SearchSource { } } + private _getOrBuildDependencyResolver(): DependencyResolver { + if (!this._dependencyResolver) { + this._dependencyResolver = new DependencyResolver( + this._context.resolver, + this._context.hasteFS, + buildSnapshotResolver(this._context.config), + ); + } + return this._dependencyResolver; + } + private _filterTestPathsWithStats( allPaths: Array, testPathPattern?: string, @@ -155,11 +175,7 @@ export default class SearchSource { allPaths: Set, collectCoverage: boolean, ): SearchResult { - const dependencyResolver = new DependencyResolver( - this._context.resolver, - this._context.hasteFS, - buildSnapshotResolver(this._context.config), - ); + const dependencyResolver = this._getOrBuildDependencyResolver(); if (!collectCoverage) { return { @@ -240,14 +256,11 @@ export default class SearchSource { changedFilesInfo: ChangedFiles, collectCoverage: boolean, ): SearchResult { - const {repos, changedFiles} = changedFilesInfo; - // no SCM (git/hg/...) is found in any of the roots. - const noSCM = (Object.keys(repos) as Array< - keyof ChangedFiles['repos'] - >).every(scm => repos[scm].size === 0); - return noSCM - ? {noSCM: true, tests: []} - : this.findRelatedTests(changedFiles, collectCoverage); + if (!hasSCM(changedFilesInfo)) { + return {noSCM: true, tests: []}; + } + const {changedFiles} = changedFilesInfo; + return this.findRelatedTests(changedFiles, collectCoverage); } private _getTestPaths( @@ -328,4 +341,24 @@ export default class SearchSource { return searchResult; } + + findRelatedSourcesFromTestsInChangedFiles( + changedFilesInfo: ChangedFiles, + ): Array { + if (!hasSCM(changedFilesInfo)) { + return []; + } + const {changedFiles} = changedFilesInfo; + const dependencyResolver = this._getOrBuildDependencyResolver(); + const relatedSourcesSet = new Set(); + changedFiles.forEach(filePath => { + if (this.isTestFilePath(filePath)) { + const sourcePaths = dependencyResolver.resolve(filePath, { + skipNodeResolution: this._context.config.skipNodeResolution, + }); + sourcePaths.forEach(sourcePath => relatedSourcesSet.add(sourcePath)); + } + }); + return Array.from(relatedSourcesSet); + } } diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts index 41b40e18955f..bf455a2e05c1 100644 --- a/packages/jest-core/src/TestScheduler.ts +++ b/packages/jest-core/src/TestScheduler.ts @@ -44,6 +44,7 @@ export type TestSchedulerContext = { firstRun: boolean; previousSuccess: boolean; changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export default class TestScheduler { private _dispatcher: ReporterDispatcher; @@ -180,7 +181,9 @@ export default class TestScheduler { if (!testRunners[config.runner]) { const Runner: typeof TestRunner = require(config.runner); testRunners[config.runner] = new Runner(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }); } }); @@ -272,7 +275,9 @@ export default class TestScheduler { if (!isDefault && collectCoverage) { this.addReporter( new CoverageReporter(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }), ); } @@ -302,7 +307,9 @@ export default class TestScheduler { if (collectCoverage) { this.addReporter( new CoverageReporter(this._globalConfig, { - changedFiles: this._context && this._context.changedFiles, + changedFiles: this._context?.changedFiles, + sourcesRelatedToTestsInChangedFiles: this._context + ?.sourcesRelatedToTestsInChangedFiles, }), ); } diff --git a/packages/jest-core/src/__tests__/SearchSource.test.ts b/packages/jest-core/src/__tests__/SearchSource.test.ts index 292e5e4b986a..0a6815062c85 100644 --- a/packages/jest-core/src/__tests__/SearchSource.test.ts +++ b/packages/jest-core/src/__tests__/SearchSource.test.ts @@ -531,4 +531,64 @@ describe('SearchSource', () => { } }); }); + + describe('findRelatedSourcesFromTestsInChangedFiles', () => { + const rootDir = path.resolve( + __dirname, + '../../../jest-runtime/src/__tests__/test_root', + ); + + beforeEach(async () => { + const {options: config} = normalize( + { + haste: { + hasteImplModulePath: path.resolve( + __dirname, + '../../../jest-haste-map/src/__tests__/haste_impl.js', + ), + providesModuleNodeModules: [], + }, + name: 'SearchSource-findRelatedSourcesFromTestsInChangedFiles-tests', + rootDir, + }, + {} as Config.Argv, + ); + const context = await Runtime.createContext(config, { + maxWorkers, + watchman: false, + }); + searchSource = new SearchSource(context); + }); + + it('return empty set if no SCM', () => { + const requireRegularModule = path.join( + rootDir, + 'RequireRegularModule.js', + ); + const sources = searchSource.findRelatedSourcesFromTestsInChangedFiles({ + changedFiles: new Set([requireRegularModule]), + repos: { + git: new Set(), + hg: new Set(), + }, + }); + expect(sources).toEqual([]); + }); + + it('return sources required by tests', () => { + const regularModule = path.join(rootDir, 'RegularModule.js'); + const requireRegularModule = path.join( + rootDir, + 'RequireRegularModule.js', + ); + const sources = searchSource.findRelatedSourcesFromTestsInChangedFiles({ + changedFiles: new Set([requireRegularModule]), + repos: { + git: new Set('/path/to/git'), + hg: new Set(), + }, + }); + expect(sources).toEqual([regularModule]); + }); + }); }); diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts index 38bcb8dc95be..bea930899c0d 100644 --- a/packages/jest-core/src/runJest.ts +++ b/packages/jest-core/src/runJest.ts @@ -34,13 +34,12 @@ import type {Filter, TestRunData} from './types'; const getTestPaths = async ( globalConfig: Config.GlobalConfig, - context: Context, + source: SearchSource, outputStream: NodeJS.WriteStream, changedFiles: ChangedFiles | undefined, jestHooks: JestHookEmitter, filter?: Filter, ) => { - const source = new SearchSource(context); const data = await source.getTestPaths(globalConfig, changedFiles, filter); if (!data.tests.length && globalConfig.onlyChanged && data.noSCM) { @@ -167,11 +166,14 @@ export default async function runJest({ } } + const searchSources = contexts.map(context => new SearchSource(context)); + const testRunData: TestRunData = await Promise.all( - contexts.map(async context => { + contexts.map(async (context, index) => { + const searchSource = searchSources[index]; const matches = await getTestPaths( globalConfig, - context, + searchSource, outputStream, changedFilesPromise && (await changedFilesPromise), jestHooks, @@ -242,9 +244,22 @@ export default async function runJest({ } if (changedFilesPromise) { - testSchedulerContext.changedFiles = ( - await changedFilesPromise - ).changedFiles; + const changedFilesInfo = await changedFilesPromise; + if (changedFilesInfo.changedFiles) { + testSchedulerContext.changedFiles = changedFilesInfo.changedFiles; + const sourcesRelatedToTestsInChangedFilesArray = contexts + .map((_, index) => { + const searchSource = searchSources[index]; + const relatedSourceFromTestsInChangedFiles = searchSource.findRelatedSourcesFromTestsInChangedFiles( + changedFilesInfo, + ); + return relatedSourceFromTestsInChangedFiles; + }) + .reduce((total, paths) => total.concat(paths), []); + testSchedulerContext.sourcesRelatedToTestsInChangedFiles = new Set( + sourcesRelatedToTestsInChangedFilesArray, + ); + } } const results = await new TestScheduler( diff --git a/packages/jest-reporters/src/__tests__/coverage_worker.test.js b/packages/jest-reporters/src/__tests__/coverage_worker.test.js index b3351ba29006..86cfeecb1ab3 100644 --- a/packages/jest-reporters/src/__tests__/coverage_worker.test.js +++ b/packages/jest-reporters/src/__tests__/coverage_worker.test.js @@ -41,6 +41,7 @@ test('resolves to the result of generateEmptyCoverage upon success', async () => globalConfig, config, undefined, + undefined, ); expect(result).toEqual(42); diff --git a/packages/jest-reporters/src/coverage_reporter.ts b/packages/jest-reporters/src/coverage_reporter.ts index 4ec8d75961ac..1e87c21bdbd8 100644 --- a/packages/jest-reporters/src/coverage_reporter.ts +++ b/packages/jest-reporters/src/coverage_reporter.ts @@ -182,6 +182,9 @@ export default class CoverageReporter extends BaseReporter { changedFiles: this._options.changedFiles && Array.from(this._options.changedFiles), + sourcesRelatedToTestsInChangedFiles: + this._options.sourcesRelatedToTestsInChangedFiles && + Array.from(this._options.sourcesRelatedToTestsInChangedFiles), }, path: filename, }); diff --git a/packages/jest-reporters/src/coverage_worker.ts b/packages/jest-reporters/src/coverage_worker.ts index 23109ffa16ee..d1894b97574c 100644 --- a/packages/jest-reporters/src/coverage_worker.ts +++ b/packages/jest-reporters/src/coverage_worker.ts @@ -40,6 +40,8 @@ export function worker({ path, globalConfig, config, - options && options.changedFiles && new Set(options.changedFiles), + options?.changedFiles && new Set(options.changedFiles), + options?.sourcesRelatedToTestsInChangedFiles && + new Set(options.sourcesRelatedToTestsInChangedFiles), ); } diff --git a/packages/jest-reporters/src/generateEmptyCoverage.ts b/packages/jest-reporters/src/generateEmptyCoverage.ts index b6c270060fdd..38f184d61558 100644 --- a/packages/jest-reporters/src/generateEmptyCoverage.ts +++ b/packages/jest-reporters/src/generateEmptyCoverage.ts @@ -30,6 +30,7 @@ export default function ( globalConfig: Config.GlobalConfig, config: Config.ProjectConfig, changedFiles?: Set, + sourcesRelatedToTestsInChangedFiles?: Set, ): CoverageWorkerResult | null { const coverageOptions = { changedFiles, @@ -37,6 +38,7 @@ export default function ( collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, coverageProvider: globalConfig.coverageProvider, + sourcesRelatedToTestsInChangedFiles, }; let coverageWorkerResult: CoverageWorkerResult | null = null; if (shouldInstrument(filename, coverageOptions, config)) { diff --git a/packages/jest-reporters/src/types.ts b/packages/jest-reporters/src/types.ts index ddfde5782362..d2725ead5917 100644 --- a/packages/jest-reporters/src/types.ts +++ b/packages/jest-reporters/src/types.ts @@ -37,10 +37,12 @@ export type CoverageWorker = {worker: typeof worker}; export type CoverageReporterOptions = { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type CoverageReporterSerializedOptions = { changedFiles?: Array; + sourcesRelatedToTestsInChangedFiles?: Array; }; export type OnTestStart = (test: Test) => Promise; diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index fb3e93ea0eda..dd8735be8b57 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -147,11 +147,13 @@ async function runTestInternal( setGlobal(environment.global, 'console', testConsole); const runtime = new Runtime(config, environment, resolver, cacheFS, { - changedFiles: context && context.changedFiles, + changedFiles: context?.changedFiles, collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, coverageProvider: globalConfig.coverageProvider, + sourcesRelatedToTestsInChangedFiles: + context?.sourcesRelatedToTestsInChangedFiles, }); const start = Date.now(); diff --git a/packages/jest-runner/src/types.ts b/packages/jest-runner/src/types.ts index c45b44d32677..4862c886ce86 100644 --- a/packages/jest-runner/src/types.ts +++ b/packages/jest-runner/src/types.ts @@ -51,6 +51,7 @@ export type TestRunnerOptions = { export type TestRunnerContext = { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type TestRunnerSerializedContext = { diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 363c18ba846f..ecb2d25f3ef8 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -171,6 +171,7 @@ class Runtime { collectCoverageFrom: [], collectCoverageOnlyFrom: undefined, coverageProvider: 'babel', + sourcesRelatedToTestsInChangedFiles: undefined, }; this._currentlyExecutingModulePath = ''; this._environment = environment; diff --git a/packages/jest-transform/src/shouldInstrument.ts b/packages/jest-transform/src/shouldInstrument.ts index e9d75afdbc63..d9fcdcd268c3 100644 --- a/packages/jest-transform/src/shouldInstrument.ts +++ b/packages/jest-transform/src/shouldInstrument.ts @@ -94,7 +94,12 @@ export default function shouldInstrument( } if (options.changedFiles && !options.changedFiles.has(filename)) { - return false; + if (!options.sourcesRelatedToTestsInChangedFiles) { + return false; + } + if (!options.sourcesRelatedToTestsInChangedFiles.has(filename)) { + return false; + } } return true; diff --git a/packages/jest-transform/src/types.ts b/packages/jest-transform/src/types.ts index 138bab7f5406..b984980e1112 100644 --- a/packages/jest-transform/src/types.ts +++ b/packages/jest-transform/src/types.ts @@ -16,6 +16,7 @@ export type ShouldInstrumentOptions = Pick< | 'coverageProvider' > & { changedFiles?: Set; + sourcesRelatedToTestsInChangedFiles?: Set; }; export type Options = ShouldInstrumentOptions & From d81464622dc8857ba995ed04e121af2b3e8e33bc Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Sun, 26 Apr 2020 19:13:16 +0200 Subject: [PATCH 39/39] Prints the Symbol name into the error message with a custom asymmetric matcher (#9888) --- CHANGELOG.md | 1 + .../__tests__/__snapshots__/extend.test.js.snap | 12 ++++++++++++ packages/expect/src/__tests__/extend.test.js | 17 +++++++++++++++++ packages/expect/src/jestMatchersObject.ts | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dcacb217199..07c630555d7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Fixes +- `[expect]` Prints the Symbol name into the error message with a custom asymmetric matcher ([#9888](https://github.com/facebook/jest/pull/9888)) - `[@jest/environment]` Make sure not to reference Jest types ([#9875](https://github.com/facebook/jest/pull/9875)) - `[jest-message-util]` Code frame printing should respect `--noStackTrace` flag ([#9866](https://github.com/facebook/jest/pull/9866)) - `[jest-runtime]` Support importing CJS from ESM using `import` statements ([#9850](https://github.com/facebook/jest/pull/9850)) diff --git a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap index b1b67afefea8..68129f9c16d7 100644 --- a/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap +++ b/packages/expect/src/__tests__/__snapshots__/extend.test.js.snap @@ -53,3 +53,15 @@ exports[`is available globally when matcher is unary 1`] = `expected 15 to be di exports[`is available globally when matcher is variadic 1`] = `expected 15 to be within range 1 - 3`; exports[`is ok if there is no message specified 1`] = `No message was specified for this matcher.`; + +exports[`prints the Symbol into the error message 1`] = ` +expect(received).toEqual(expected) // deep equality + +- Expected - 1 ++ Received + 1 + + Object { +- "a": toBeSymbol, ++ "a": Symbol(foo), + } +`; diff --git a/packages/expect/src/__tests__/extend.test.js b/packages/expect/src/__tests__/extend.test.js index 7861eafe5852..11b915332fee 100644 --- a/packages/expect/src/__tests__/extend.test.js +++ b/packages/expect/src/__tests__/extend.test.js @@ -23,6 +23,12 @@ jestExpect.extend({ return {message, pass}; }, + toBeSymbol(actual, expected) { + const pass = actual === expected; + const message = () => `expected ${actual} to be Symbol ${expected}`; + + return {message, pass}; + }, toBeWithinRange(actual, floor, ceiling) { const pass = actual >= floor && actual <= ceiling; const message = pass @@ -137,3 +143,14 @@ it('defines asymmetric variadic matchers that can be prefixed by not', () => { }), ).not.toThrow(); }); + +it('prints the Symbol into the error message', () => { + const foo = Symbol('foo'); + const bar = Symbol('bar'); + + expect(() => + jestExpect({a: foo}).toEqual({ + a: jestExpect.toBeSymbol(bar), + }), + ).toThrowErrorMatchingSnapshot(); +}); diff --git a/packages/expect/src/jestMatchersObject.ts b/packages/expect/src/jestMatchersObject.ts index bf08dca6db08..24b2c087071c 100644 --- a/packages/expect/src/jestMatchersObject.ts +++ b/packages/expect/src/jestMatchersObject.ts @@ -78,7 +78,7 @@ export const setMatchers = ( } toAsymmetricMatcher() { - return `${this.toString()}<${this.sample.join(', ')}>`; + return `${this.toString()}<${this.sample.map(String).join(', ')}>`; } }