123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', {
- value: true
- });
- exports.default = runTest;
- function _chalk() {
- const data = _interopRequireDefault(require('chalk'));
- _chalk = function () {
- return data;
- };
- return data;
- }
- function fs() {
- const data = _interopRequireWildcard(require('graceful-fs'));
- fs = function () {
- return data;
- };
- return data;
- }
- function _sourceMapSupport() {
- const data = _interopRequireDefault(require('source-map-support'));
- _sourceMapSupport = function () {
- return data;
- };
- return data;
- }
- function _console() {
- const data = require('@jest/console');
- _console = function () {
- return data;
- };
- return data;
- }
- function _transform() {
- const data = require('@jest/transform');
- _transform = function () {
- return data;
- };
- return data;
- }
- function docblock() {
- const data = _interopRequireWildcard(require('jest-docblock'));
- docblock = function () {
- return data;
- };
- return data;
- }
- function _jestLeakDetector() {
- const data = _interopRequireDefault(require('jest-leak-detector'));
- _jestLeakDetector = function () {
- return data;
- };
- return data;
- }
- function _jestMessageUtil() {
- const data = require('jest-message-util');
- _jestMessageUtil = function () {
- return data;
- };
- return data;
- }
- function _jestResolve() {
- const data = require('jest-resolve');
- _jestResolve = function () {
- return data;
- };
- return data;
- }
- function _jestUtil() {
- const data = require('jest-util');
- _jestUtil = function () {
- return data;
- };
- return data;
- }
- function _getRequireWildcardCache(nodeInterop) {
- if (typeof WeakMap !== 'function') return null;
- var cacheBabelInterop = new WeakMap();
- var cacheNodeInterop = new WeakMap();
- return (_getRequireWildcardCache = function (nodeInterop) {
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
- })(nodeInterop);
- }
- function _interopRequireWildcard(obj, nodeInterop) {
- if (!nodeInterop && obj && obj.__esModule) {
- return obj;
- }
- if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
- return {default: obj};
- }
- var cache = _getRequireWildcardCache(nodeInterop);
- if (cache && cache.has(obj)) {
- return cache.get(obj);
- }
- var newObj = {};
- var hasPropertyDescriptor =
- Object.defineProperty && Object.getOwnPropertyDescriptor;
- for (var key in obj) {
- if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
- var desc = hasPropertyDescriptor
- ? Object.getOwnPropertyDescriptor(obj, key)
- : null;
- if (desc && (desc.get || desc.set)) {
- Object.defineProperty(newObj, key, desc);
- } else {
- newObj[key] = obj[key];
- }
- }
- }
- newObj.default = obj;
- if (cache) {
- cache.set(obj, newObj);
- }
- return newObj;
- }
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {default: obj};
- }
- /**
- * 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.
- *
- */
- function freezeConsole(testConsole, config) {
- // @ts-expect-error: `_log` is `private` - we should figure out some proper API here
- testConsole._log = function fakeConsolePush(_type, message) {
- const error = new (_jestUtil().ErrorWithStack)(
- `${_chalk().default.red(
- `${_chalk().default.bold(
- 'Cannot log after tests are done.'
- )} Did you forget to wait for something async in your test?`
- )}\nAttempted to log "${message}".`,
- fakeConsolePush
- );
- const formattedError = (0, _jestMessageUtil().formatExecError)(
- error,
- config,
- {
- noStackTrace: false
- },
- undefined,
- true
- );
- process.stderr.write('\n' + formattedError + '\n');
- process.exitCode = 1;
- };
- } // Keeping the core of "runTest" as a separate function (as "runTestInternal")
- // is key to be able to detect memory leaks. Since all variables are local to
- // the function, when "runTestInternal" finishes its execution, they can all be
- // freed, UNLESS something else is leaking them (and that's why we can detect
- // the leak!).
- //
- // If we had all the code in a single function, we should manually nullify all
- // references to verify if there is a leak, which is not maintainable and error
- // prone. That's why "runTestInternal" CANNOT be inlined inside "runTest".
- async function runTestInternal(
- path,
- globalConfig,
- config,
- resolver,
- context,
- sendMessageToJest
- ) {
- const testSource = fs().readFileSync(path, 'utf8');
- const docblockPragmas = docblock().parse(docblock().extract(testSource));
- const customEnvironment = docblockPragmas['jest-environment'];
- let testEnvironment = config.testEnvironment;
- if (customEnvironment) {
- if (Array.isArray(customEnvironment)) {
- throw new Error(
- `You can only define a single test environment through docblocks, got "${customEnvironment.join(
- ', '
- )}"`
- );
- }
- testEnvironment = (0, _jestResolve().resolveTestEnvironment)({
- ...config,
- requireResolveFunction: require.resolve,
- testEnvironment: customEnvironment
- });
- }
- const cacheFS = new Map([[path, testSource]]);
- const transformer = await (0, _transform().createScriptTransformer)(
- config,
- cacheFS
- );
- const TestEnvironment = await transformer.requireAndTranspileModule(
- testEnvironment
- );
- const testFramework = await transformer.requireAndTranspileModule(
- process.env.JEST_JASMINE === '1'
- ? require.resolve('jest-jasmine2')
- : config.testRunner
- );
- const Runtime = (0, _jestUtil().interopRequireDefault)(
- config.moduleLoader ? require(config.moduleLoader) : require('jest-runtime')
- ).default;
- const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout;
- const consoleFormatter = (type, message) =>
- (0, _console().getConsoleOutput)(
- // 4 = the console call is buried 4 stack frames deep
- _console().BufferedConsole.write([], type, message, 4),
- config,
- globalConfig
- );
- let testConsole;
- if (globalConfig.silent) {
- testConsole = new (_console().NullConsole)(
- consoleOut,
- consoleOut,
- consoleFormatter
- );
- } else if (globalConfig.verbose) {
- testConsole = new (_console().CustomConsole)(
- consoleOut,
- consoleOut,
- consoleFormatter
- );
- } else {
- testConsole = new (_console().BufferedConsole)();
- }
- const environment = new TestEnvironment(config, {
- console: testConsole,
- docblockPragmas,
- testPath: path
- });
- if (typeof environment.getVmContext !== 'function') {
- console.error(
- `Test environment found at "${testEnvironment}" does not export a "getVmContext" method, which is mandatory from Jest 27. This method is a replacement for "runScript".`
- );
- process.exit(1);
- }
- const leakDetector = config.detectLeaks
- ? new (_jestLeakDetector().default)(environment)
- : null;
- (0, _jestUtil().setGlobal)(environment.global, 'console', testConsole);
- const runtime = new Runtime(
- config,
- environment,
- resolver,
- transformer,
- cacheFS,
- {
- changedFiles:
- context === null || context === void 0 ? void 0 : context.changedFiles,
- collectCoverage: globalConfig.collectCoverage,
- collectCoverageFrom: globalConfig.collectCoverageFrom,
- collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom,
- coverageProvider: globalConfig.coverageProvider,
- sourcesRelatedToTestsInChangedFiles:
- context === null || context === void 0
- ? void 0
- : context.sourcesRelatedToTestsInChangedFiles
- },
- path
- );
- const start = Date.now();
- 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 = {
- environment: 'node',
- handleUncaughtExceptions: false,
- retrieveSourceMap: source => {
- var _runtime$getSourceMap;
- const sourceMapSource =
- (_runtime$getSourceMap = runtime.getSourceMaps()) === null ||
- _runtime$getSourceMap === void 0
- ? void 0
- : _runtime$getSourceMap.get(source);
- if (sourceMapSource) {
- try {
- return {
- map: JSON.parse(fs().readFileSync(sourceMapSource, 'utf8')),
- url: source
- };
- } catch {}
- }
- return null;
- }
- }; // For tests
- runtime
- .requireInternalModule(
- require.resolve('source-map-support'),
- 'source-map-support'
- )
- .install(sourcemapOptions); // For runtime errors
- _sourceMapSupport().default.install(sourcemapOptions);
- if (
- environment.global &&
- environment.global.process &&
- environment.global.process.exit
- ) {
- const realExit = environment.global.process.exit;
- environment.global.process.exit = function exit(...args) {
- const error = new (_jestUtil().ErrorWithStack)(
- `process.exit called with "${args.join(', ')}"`,
- exit
- );
- const formattedError = (0, _jestMessageUtil().formatExecError)(
- error,
- config,
- {
- noStackTrace: false
- },
- undefined,
- true
- );
- process.stderr.write(formattedError);
- return realExit(...args);
- };
- } // if we don't have `getVmContext` on the env skip coverage
- const collectV8Coverage =
- globalConfig.coverageProvider === 'v8' &&
- typeof environment.getVmContext === 'function';
- try {
- await environment.setup();
- let result;
- try {
- if (collectV8Coverage) {
- await runtime.collectV8Coverage();
- }
- result = await testFramework(
- globalConfig,
- config,
- environment,
- runtime,
- path,
- sendMessageToJest
- );
- } catch (err) {
- // Access stack before uninstalling sourcemaps
- err.stack;
- throw err;
- } finally {
- if (collectV8Coverage) {
- await runtime.stopCollectingV8Coverage();
- }
- }
- freezeConsole(testConsole, config);
- const testCount =
- result.numPassingTests +
- result.numFailingTests +
- result.numPendingTests +
- result.numTodoTests;
- const end = Date.now();
- const testRuntime = end - start;
- result.perfStats = {
- end,
- runtime: testRuntime,
- slow: testRuntime / 1000 > config.slowTestThreshold,
- start
- };
- result.testFilePath = path;
- result.console = testConsole.getBuffer();
- result.skipped = testCount === result.numPendingTests;
- result.displayName = config.displayName;
- const coverage = runtime.getAllCoverageInfoCopy();
- if (coverage) {
- const coverageKeys = Object.keys(coverage);
- if (coverageKeys.length) {
- result.coverage = coverage;
- }
- }
- if (collectV8Coverage) {
- const v8Coverage = runtime.getAllV8CoverageInfoCopy();
- if (v8Coverage && v8Coverage.length > 0) {
- result.v8Coverage = v8Coverage;
- }
- }
- if (globalConfig.logHeapUsage) {
- if (global.gc) {
- global.gc();
- }
- result.memoryUsage = process.memoryUsage().heapUsed;
- } // Delay the resolution to allow log messages to be output.
- return new Promise(resolve => {
- setImmediate(() =>
- resolve({
- leakDetector,
- result
- })
- );
- });
- } finally {
- runtime.teardown();
- await environment.teardown();
- _sourceMapSupport().default.resetRetrieveHandlers();
- }
- }
- async function runTest(
- path,
- globalConfig,
- config,
- resolver,
- context,
- sendMessageToJest
- ) {
- const {leakDetector, result} = await runTestInternal(
- path,
- globalConfig,
- config,
- resolver,
- context,
- sendMessageToJest
- );
- if (leakDetector) {
- // We wanna allow a tiny but time to pass to allow last-minute cleanup
- await new Promise(resolve => setTimeout(resolve, 100)); // Resolve leak detector, outside the "runTestInternal" closure.
- result.leaks = await leakDetector.isLeaking();
- } else {
- result.leaks = false;
- }
- return result;
- }
|