diff --git a/CHANGELOG.md b/CHANGELOG.md index cabe3e1e4403..830993a75ed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - `[@jest/expect-utils]` Fix deep equality of ImmutableJS Record ([#13055](https://github.com/facebook/jest/pull/13055)) - `[jest-haste-map]` Increase the maximum possible file size that jest-haste-map can handle ([#13094](https://github.com/facebook/jest/pull/13094)) - `[jest-snapshot]` Make `prettierPath` optional in `SnapshotState` ([#13149](https://github.com/facebook/jest/pull/13149)) +- `[jest-snapshot]` Fix parsing error from inline snapshot files with `JSX` ([#12760](https://github.com/facebook/jest/pull/12760)) - `[jest-worker]` When a process runs out of memory worker exits correctly and doesn't spin indefinitely ([#13054](https://github.com/facebook/jest/pull/13054)) ### Chore & Maintenance diff --git a/e2e/__tests__/toMatchInlineSnapshotWithJSX.test.ts b/e2e/__tests__/toMatchInlineSnapshotWithJSX.test.ts index ef1b98b5c35c..1f5b63fa0a0e 100644 --- a/e2e/__tests__/toMatchInlineSnapshotWithJSX.test.ts +++ b/e2e/__tests__/toMatchInlineSnapshotWithJSX.test.ts @@ -109,3 +109,52 @@ it('successfully runs the tests with external babel config', () => { expect(updateSnapshotRun.exitCode).toBe(0); expect(updateSnapshotRun.stderr).toContain('1 snapshot updated.'); }); + +it('successfully runs the tests with inline babel config', () => { + writeFiles(DIR, { + 'package.json': JSON.stringify({ + ...pkg, + jest: { + testEnvironment: 'jsdom', + transform: { + '^.+\\.(js|jsx)$': ['babel-jest', babelConfig], + }, + }, + }), + }); + + const normalRun = runWithJson(DIR, []); + expect(normalRun.exitCode).toBe(1); + expect(normalRun.stderr).toContain('1 snapshot failed from 1 test suite.'); + expect(normalRun.json.testResults[0].message).toMatchInlineSnapshot(` + " ●
x
+ + expect(received).toMatchInlineSnapshot(snapshot) + + Snapshot name: \`
x
1\` + + - Snapshot - 1 + + Received + 1 + +
+ - y + + x +
+ + 3 | + 4 | test('
x
', () => { + > 5 | expect(renderer.create(
x
).toJSON()).toMatchInlineSnapshot(\` + | ^ + 6 |
+ 7 | y + 8 |
+ + at Object.toMatchInlineSnapshot (__tests__/MismatchingSnapshot.test.js:5:50) + " + `); + + const updateSnapshotRun = runJest(DIR, ['--updateSnapshot']); + + expect(updateSnapshotRun.exitCode).toBe(0); + expect(updateSnapshotRun.stderr).toContain('1 snapshot updated.'); +}); diff --git a/packages/jest-snapshot/package.json b/packages/jest-snapshot/package.json index 725514e6bbdf..18feba9e57cb 100644 --- a/packages/jest-snapshot/package.json +++ b/packages/jest-snapshot/package.json @@ -19,6 +19,7 @@ "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", diff --git a/packages/jest-snapshot/src/InlineSnapshots.ts b/packages/jest-snapshot/src/InlineSnapshots.ts index 2e5013784b4a..53d644e63c48 100644 --- a/packages/jest-snapshot/src/InlineSnapshots.ts +++ b/packages/jest-snapshot/src/InlineSnapshots.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import type {PluginItem} from '@babel/core'; +import type {ParseResult, PluginItem} from '@babel/core'; import {Expression, File, Program, isAwaitExpression} from '@babel/types'; import * as fs from 'graceful-fs'; import type { @@ -95,12 +95,39 @@ const saveSnapshotsForFile = ( // by one to formatting parser. const snapshotMatcherNames: Array = []; - const ast = parseSync(sourceFile, { - filename: sourceFilePath, - plugins, - presets, - root: rootDir, - }); + let ast: ParseResult | null = null; + + try { + ast = parseSync(sourceFile, { + filename: sourceFilePath, + plugins, + presets, + root: rootDir, + }); + } catch (error: any) { + // attempt to recover from missing jsx plugin + if (error.message.includes('@babel/plugin-syntax-jsx')) { + try { + const jsxSyntaxPlugin: PluginItem = [ + require.resolve('@babel/plugin-syntax-jsx'), + {}, + // unique name to make sure Babel does not complain about a possible duplicate plugin. + 'JSX syntax plugin added by Jest snapshot', + ]; + ast = parseSync(sourceFile, { + filename: sourceFilePath, + plugins: [...plugins, jsxSyntaxPlugin], + presets, + root: rootDir, + }); + } catch { + throw error; + } + } else { + throw error; + } + } + if (!ast) { throw new Error(`jest-snapshot: Failed to parse ${sourceFilePath}`); } diff --git a/yarn.lock b/yarn.lock index baa8f88f55b2..815500a8368d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1030,7 +1030,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.18.6": +"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.18.6 resolution: "@babel/plugin-syntax-jsx@npm:7.18.6" dependencies: @@ -12847,6 +12847,7 @@ __metadata: dependencies: "@babel/core": ^7.11.6 "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-jsx": ^7.7.2 "@babel/plugin-syntax-typescript": ^7.7.2 "@babel/preset-flow": ^7.7.2 "@babel/preset-react": ^7.12.1