diff --git a/CHANGELOG.md b/CHANGELOG.md index c7b55999a023..58c7b98f72ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -114,6 +114,8 @@ ([#5888](https://github.com/facebook/jest/pull/5888)) * `[jest-mock]` [**BREAKING**] Replace timestamps with `invocationCallOrder` ([#5867](https://github.com/facebook/jest/pull/5867)) +* `[jest-jasmine2]` Install `sourcemap-support` into normal runtime to catch + runtime errors ([#5945](https://github.com/facebook/jest/pull/5945)) * `[jest-jasmine2]` Added assertion error handling inside `afterAll hook` ([#5884](https://github.com/facebook/jest/pull/5884)) * `[jest-cli]` Remove the notifier actions in case of failure when not in watch @@ -167,6 +169,8 @@ ### Chore & Maintenance +* `[jest-runner]` Move sourcemap installation from `jest-jasmine2` to + `jest-runner` ([#6176](https://github.com/facebook/jest/pull/6176)) * `[jest-cli]` Use yargs's built-in `version` instead of rolling our own ([#6215](https://github.com/facebook/jest/pull/6215)) * `[docs]` Add explanation on how to mock methods not implemented in JSDOM diff --git a/integration-tests/__tests__/__snapshots__/detect_open_handles.js.snap b/integration-tests/__tests__/__snapshots__/detect_open_handles.js.snap index 046161397d47..82c3c6dfe58c 100644 --- a/integration-tests/__tests__/__snapshots__/detect_open_handles.js.snap +++ b/integration-tests/__tests__/__snapshots__/detect_open_handles.js.snap @@ -24,5 +24,5 @@ exports[`prints out info about open handlers 1`] = ` 8 | at Object. (server.js:7:5) - at Object. (__tests__/test.js:3:1)" + at Object. (__tests__/test.js:1:1)" `; diff --git a/integration-tests/__tests__/__snapshots__/globals.test.js.snap b/integration-tests/__tests__/__snapshots__/globals.test.js.snap index 0a79b88e36c2..30496da2c554 100644 --- a/integration-tests/__tests__/__snapshots__/globals.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/globals.test.js.snap @@ -28,7 +28,7 @@ exports[`cannot test with no implementation 1`] = ` 1 | 2 | it('it', () => {}); > 3 | it('it, no implementation'); - | ^ + | ^ 4 | test('test, no implementation'); 5 | @@ -56,7 +56,7 @@ exports[`cannot test with no implementation with expand arg 1`] = ` 1 | 2 | it('it', () => {}); > 3 | it('it, no implementation'); - | ^ + | ^ 4 | test('test, no implementation'); 5 | diff --git a/integration-tests/__tests__/globals.test.js b/integration-tests/__tests__/globals.test.js index ba3d5580e954..22a8e60f6041 100644 --- a/integration-tests/__tests__/globals.test.js +++ b/integration-tests/__tests__/globals.test.js @@ -28,12 +28,6 @@ beforeEach(() => { afterAll(() => cleanup(DIR)); -// This function is needed due to differences between Node 6 and 8-9-10 when -// returning the result of the error. -function clean(text) { - return text.replace(/([\r\n])\s+(?=[\r\n])/g, '$1').replace(/\s+\^/g, ' ^'); -} - test('basic test constructs', () => { const filename = 'basic.test-constructs.test.js'; const content = ` @@ -129,8 +123,8 @@ test('cannot test with no implementation', () => { expect(status).toBe(1); const {summary, rest} = extractSummary(stderr, {stripLocation: true}); - expect(clean(rest)).toMatchSnapshot(); - expect(clean(summary)).toMatchSnapshot(); + expect(rest).toMatchSnapshot(); + expect(summary).toMatchSnapshot(); }); test('skips with expand arg', () => { @@ -207,8 +201,8 @@ test('cannot test with no implementation with expand arg', () => { expect(status).toBe(1); const {summary, rest} = extractSummary(stderr, {stripLocation: true}); - expect(clean(rest)).toMatchSnapshot(); - expect(clean(summary)).toMatchSnapshot(); + expect(rest).toMatchSnapshot(); + expect(summary).toMatchSnapshot(); }); test('function as descriptor', () => { diff --git a/integration-tests/__tests__/stack_trace.test.js b/integration-tests/__tests__/stack_trace.test.js index dc20cea89f96..d37b5409eca9 100644 --- a/integration-tests/__tests__/stack_trace.test.js +++ b/integration-tests/__tests__/stack_trace.test.js @@ -21,6 +21,7 @@ describe('Stack Trace', () => { expect(stderr).toMatch( /ReferenceError: thisIsARuntimeError is not defined/, ); + expect(stderr).toMatch(/> 10 \| thisIsARuntimeError\(\);/); expect(stderr).toMatch( /\s+at\s(?:.+?)\s\(__tests__\/runtime_error.test\.js/, ); diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index ca7cfe6a401b..3c720008ccd3 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -11,15 +11,13 @@ "chalk": "^2.0.1", "co": "^4.6.0", "expect": "^22.4.0", - "graceful-fs": "^4.1.11", "is-generator-fn": "^1.0.0", "jest-diff": "^22.4.0", "jest-matcher-utils": "^22.4.0", "jest-message-util": "^22.4.0", "jest-snapshot": "^22.4.0", "jest-util": "^22.4.1", - "pretty-format": "^22.4.0", - "source-map-support": "^0.5.0" + "pretty-format": "^22.4.0" }, "devDependencies": { "jest-runtime": "^22.4.2" diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 785fa5cf0548..a20fe97d6763 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -15,7 +15,6 @@ import type {TestResult} from 'types/TestResult'; import type Runtime from 'jest-runtime'; import path from 'path'; -import fs from 'graceful-fs'; import installEach from './each'; import {getCallsite} from 'jest-util'; import JasmineReporter from './reporter'; @@ -119,30 +118,6 @@ async function jasmine2( runtime.requireModule(config.setupTestFrameworkScriptFile); } - runtime - .requireInternalModule( - require.resolve('source-map-support'), - 'source-map-support', - ) - .install({ - environment: 'node', - handleUncaughtExceptions: false, - retrieveSourceMap: source => { - const sourceMaps = runtime.getSourceMaps(); - const sourceMapSource = sourceMaps && sourceMaps[source]; - - if (sourceMapSource) { - try { - return { - map: JSON.parse(fs.readFileSync(sourceMapSource)), - url: source, - }; - } catch (e) {} - } - return null; - }, - }); - if (globalConfig.enabledTestsMap) { env.specFilter = spec => { const suiteMap = @@ -157,9 +132,10 @@ async function jasmine2( runtime.requireModule(testPath); await env.execute(); - return reporter - .getResults() - .then(results => addSnapshotData(results, snapshotState)); + + const results = await reporter.getResults(); + + return addSnapshotData(results, snapshotState); } const addSnapshotData = (results, snapshotState) => { diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json index a086ba78223f..547d136507ec 100644 --- a/packages/jest-runner/package.json +++ b/packages/jest-runner/package.json @@ -9,6 +9,7 @@ "main": "build/index.js", "dependencies": { "exit": "^0.1.2", + "graceful-fs": "^4.1.11", "jest-config": "^22.4.2", "jest-docblock": "^22.4.0", "jest-haste-map": "^22.4.2", @@ -18,6 +19,7 @@ "jest-runtime": "^22.4.2", "jest-util": "^22.4.1", "jest-worker": "^22.2.2", + "source-map-support": "^0.5.6", "throat": "^4.0.0" } } diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index a209ffca7c51..8a351610c856 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -14,7 +14,7 @@ import type {TestFramework} from 'types/TestRunner'; import type {TestResult} from 'types/TestResult'; import type RuntimeClass from 'jest-runtime'; -import fs from 'fs'; +import fs from 'graceful-fs'; import { BufferedConsole, Console, @@ -26,6 +26,7 @@ import jasmine2 from 'jest-jasmine2'; import LeakDetector from 'jest-leak-detector'; import {getTestEnvironment} from 'jest-config'; import * as docblock from 'jest-docblock'; +import sourcemapSupport from 'source-map-support'; type RunTestInternalResult = { leakDetector: ?LeakDetector, @@ -116,15 +117,57 @@ async function runTestInternal( }); const start = Date.now(); - await environment.setup(); + + const sourcemapOptions = { + environment: 'node', + handleUncaughtExceptions: false, + retrieveSourceMap: source => { + const sourceMaps = runtime && runtime.getSourceMaps(); + const sourceMapSource = sourceMaps && sourceMaps[source]; + + if (sourceMapSource) { + try { + return { + map: JSON.parse(fs.readFileSync(sourceMapSource)), + url: source, + }; + } catch (e) {} + } + return null; + }, + }; + + // For tests + runtime + .requireInternalModule( + require.resolve('source-map-support'), + 'source-map-support', + ) + .install(sourcemapOptions); + + // For runtime errors + sourcemapSupport.install(sourcemapOptions); + try { - const result: TestResult = await testFramework( - globalConfig, - config, - environment, - runtime, - path, - ); + await environment.setup(); + + let result: TestResult; + + try { + result = await testFramework( + globalConfig, + config, + environment, + runtime, + path, + ); + } catch (err) { + // Access stack before uninstalling sourcemaps + err.stack; + + throw err; + } + const testCount = result.numPassingTests + result.numFailingTests + result.numPendingTests; @@ -151,6 +194,8 @@ async function runTestInternal( }); } finally { await environment.teardown(); + + sourcemapSupport.resetRetrieveHandlers(); } } diff --git a/yarn.lock b/yarn.lock index 84db775f89e7..5b95e52b7de8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8711,9 +8711,9 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.0: - version "0.5.5" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.5.tgz#0d4af9e00493e855402e8ec36ebed2d266fceb90" +source-map-support@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" dependencies: buffer-from "^1.0.0" source-map "^0.6.0"