'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports.runAndTransformResultsToJestFormat = exports.initialize = void 0; var _testResult = require('@jest/test-result'); var _expect = require('expect'); var _jestMessageUtil = require('jest-message-util'); var _jestSnapshot = require('jest-snapshot'); var _throat = _interopRequireDefault(require('throat')); var _state = require('../state'); var _utils = require('../utils'); var _run = _interopRequireDefault(require('../run')); var _ = _interopRequireDefault(require('..')); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : {default: obj}; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty( target, key, Object.getOwnPropertyDescriptor(source, key) ); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } // TODO: hard to type // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types const initialize = ({ config, environment, getPrettier, getBabelTraverse, globalConfig, localRequire, parentProcess, testPath }) => { if (globalConfig.testTimeout) { (0, _state.getState)().testTimeout = globalConfig.testTimeout; } const mutex = (0, _throat.default)(globalConfig.maxConcurrency); const nodeGlobal = global; Object.assign(nodeGlobal, _.default); nodeGlobal.xit = nodeGlobal.it.skip; nodeGlobal.xtest = nodeGlobal.it.skip; nodeGlobal.xdescribe = nodeGlobal.describe.skip; nodeGlobal.fit = nodeGlobal.it.only; nodeGlobal.fdescribe = nodeGlobal.describe.only; nodeGlobal.test.concurrent = (test => { const concurrent = (testName, testFn, timeout) => { // For concurrent tests we first run the function that returns promise, and then register a // nomral test that will be waiting on the returned promise (when we start the test, the promise // will already be in the process of execution). // Unfortunately at this stage there's no way to know if there are any `.only` tests in the suite // that will result in this test to be skipped, so we'll be executing the promise function anyway, // even if it ends up being skipped. const promise = mutex(() => testFn()); nodeGlobal.test(testName, () => promise, timeout); }; concurrent.only = (testName, testFn, timeout) => { const promise = mutex(() => testFn()); // eslint-disable-next-line jest/no-focused-tests test.only(testName, () => promise, timeout); }; concurrent.skip = test.skip; return concurrent; })(nodeGlobal.test); (0, _state.addEventHandler)(eventHandler); if (environment.handleTestEvent) { (0, _state.addEventHandler)(environment.handleTestEvent.bind(environment)); } (0, _state.dispatch)({ name: 'setup', parentProcess, testNamePattern: globalConfig.testNamePattern }); if (config.testLocationInResults) { (0, _state.dispatch)({ name: 'include_test_location_in_result' }); } // Jest tests snapshotSerializers in order preceding built-in serializers. // Therefore, add in reverse because the last added is the first tested. config.snapshotSerializers .concat() .reverse() .forEach(path => { (0, _jestSnapshot.addSerializer)(localRequire(path)); }); const {expand, updateSnapshot} = globalConfig; const snapshotResolver = (0, _jestSnapshot.buildSnapshotResolver)(config); const snapshotPath = snapshotResolver.resolveSnapshotPath(testPath); const snapshotState = new _jestSnapshot.SnapshotState(snapshotPath, { expand, getBabelTraverse, getPrettier, updateSnapshot }); (0, _expect.setState)({ snapshotState, testPath }); (0, _state.addEventHandler)(handleSnapshotStateAfterRetry(snapshotState)); // Return it back to the outer scope (test runner outside the VM). return { globals: _.default, snapshotState }; }; exports.initialize = initialize; const runAndTransformResultsToJestFormat = async ({ config, globalConfig, testPath }) => { const runResult = await (0, _run.default)(); let numFailingTests = 0; let numPassingTests = 0; let numPendingTests = 0; let numTodoTests = 0; const assertionResults = runResult.testResults.map(testResult => { let status; if (testResult.status === 'skip') { status = 'pending'; numPendingTests += 1; } else if (testResult.status === 'todo') { status = 'todo'; numTodoTests += 1; } else if (testResult.errors.length) { status = 'failed'; numFailingTests += 1; } else { status = 'passed'; numPassingTests += 1; } const ancestorTitles = testResult.testPath.filter( name => name !== _state.ROOT_DESCRIBE_BLOCK_NAME ); const title = ancestorTitles.pop(); return { ancestorTitles, duration: testResult.duration, failureMessages: testResult.errors, fullName: title ? ancestorTitles.concat(title).join(' ') : ancestorTitles.join(' '), invocations: testResult.invocations, location: testResult.location, numPassingAsserts: 0, status, title: testResult.testPath[testResult.testPath.length - 1] }; }); let failureMessage = (0, _jestMessageUtil.formatResultsErrors)( assertionResults, config, globalConfig, testPath ); let testExecError; if (runResult.unhandledErrors.length) { testExecError = { message: '', stack: runResult.unhandledErrors.join('\n') }; failureMessage = (failureMessage || '') + '\n\n' + runResult.unhandledErrors .map(err => (0, _jestMessageUtil.formatExecError)(err, config, globalConfig) ) .join('\n'); } (0, _state.dispatch)({ name: 'teardown' }); return _objectSpread({}, (0, _testResult.createEmptyTestResult)(), { console: undefined, displayName: config.displayName, failureMessage, numFailingTests, numPassingTests, numPendingTests, numTodoTests, sourceMaps: {}, testExecError, testFilePath: testPath, testResults: assertionResults }); }; exports.runAndTransformResultsToJestFormat = runAndTransformResultsToJestFormat; const handleSnapshotStateAfterRetry = snapshotState => event => { switch (event.name) { case 'test_retry': { // Clear any snapshot data that occurred in previous test run snapshotState.clear(); } } }; const eventHandler = event => { switch (event.name) { case 'test_start': { (0, _expect.setState)({ currentTestName: (0, _utils.getTestID)(event.test) }); break; } case 'test_done': { _addSuppressedErrors(event.test); _addExpectedAssertionErrors(event.test); break; } } }; const _addExpectedAssertionErrors = test => { const failures = (0, _expect.extractExpectedAssertionsErrors)(); const errors = failures.map(failure => failure.error); test.errors = test.errors.concat(errors); }; // Get suppressed errors from ``jest-matchers`` that weren't throw during // test execution and add them to the test result, potentially failing // a passing test. const _addSuppressedErrors = test => { const {suppressedErrors} = (0, _expect.getState)(); (0, _expect.setState)({ suppressedErrors: [] }); if (suppressedErrors.length) { test.errors = test.errors.concat(suppressedErrors); } };