[Bug]: No way to use inline snapshots without Babel
Version
29.6.1
Steps to reproduce
At Meta, we upgraded from Jest v24 to v29, and it broke inline snapshots. All of our JavaScript stuff uses the Hermes parser rather than Babel. as we're using some syntax that Babel does not support.
For parsing JS files to insert inline snapshots, Jest v24 used the parser from the Prettier config, whereas v29 is hard-coded to use Babel.
Is there a way to use a custom parser instead of Babel?
Expected behavior
Inline snapshots should be able to use a non-Babel parser.
Actual behavior
Inline snapshots can only use Babel parser.
Additional context
No response
Environment
N/A
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
This is the patch I ended up with. Just need to figure out the best API to make it properly pluggable:
diff --git a/node_modules/jest-snapshot/build/InlineSnapshots.js b/node_modules/jest-snapshot/build/InlineSnapshots.js
index 597ec93..ab61909 100644
--- a/node_modules/jest-snapshot/build/InlineSnapshots.js
+++ b/node_modules/jest-snapshot/build/InlineSnapshots.js
@@ -8,6 +8,7 @@ var path = _interopRequireWildcard(require('path'));
var fs = _interopRequireWildcard(require('graceful-fs'));
var _semver = _interopRequireDefault(require('semver'));
var _utils = require('./utils');
+var HermesParser = require('hermes-parser');
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
@@ -115,54 +116,15 @@ function saveInlineSnapshots(snapshots, rootDir, prettierPath) {
const saveSnapshotsForFile = (snapshots, sourceFilePath, rootDir, prettier) => {
const sourceFile = jestReadFile(sourceFilePath, 'utf8');
- // TypeScript projects may not have a babel config; make sure they can be parsed anyway.
- const presets = [require.resolve('babel-preset-current-node-syntax')];
- const plugins = [];
- if (/\.([cm]?ts|tsx)$/.test(sourceFilePath)) {
- plugins.push([
- require.resolve('@babel/plugin-syntax-typescript'),
- {
- isTSX: sourceFilePath.endsWith('x')
- },
- // unique name to make sure Babel does not complain about a possible duplicate plugin.
- 'TypeScript syntax plugin added by Jest snapshot'
- ]);
- }
-
// Record the matcher names seen during traversal and pass them down one
// by one to formatting parser.
const snapshotMatcherNames = [];
- let ast = null;
- try {
- ast = parseSync(sourceFile, {
- filename: sourceFilePath,
- plugins,
- presets,
- root: rootDir
- });
- } catch (error) {
- // attempt to recover from missing jsx plugin
- if (error.message.includes('@babel/plugin-syntax-jsx')) {
- try {
- const jsxSyntaxPlugin = [
- 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;
- }
- }
+ const ast = HermesParser.parse(sourceFile, {
+ babel: true,
+ enableExperimentalComponentSyntax: true,
+ sourceFilename: sourceFilePath,
+ sourceType: 'unambiguous',
+ });
if (!ast) {
throw new Error(`jest-snapshot: Failed to parse ${sourceFilePath}`);
}
const groupSnapshotsByFile = groupSnapshotsBy(({frame: {file}}) => file);
@@ -310,20 +272,7 @@ const runPrettier = (
})
: null;
- // Prioritize parser found in the project config.
- // If not found detect the parser for the test file.
- // For older versions of Prettier, fallback to a simple parser detection.
- // @ts-expect-error - `inferredParser` is `string`
- const inferredParser =
- (config && typeof config.parser === 'string' && config.parser) ||
- (prettier.getFileInfo
- ? prettier.getFileInfo.sync(sourceFilePath).inferredParser
- : simpleDetectParser(sourceFilePath));
- if (!inferredParser) {
- throw new Error(
- `Could not infer Prettier parser for file ${sourceFilePath}`
- );
- }
+ const inferredParser = 'hermes';
// Snapshots have now been inserted. Run prettier to make sure that the code is
// formatted, except snapshot indentation. Snapshots cannot be formatted until
@@ -333,12 +282,14 @@ const runPrettier = (
return prettier.format(
prettier.format(sourceFileWithSnapshots, {
...config,
- filepath: sourceFilePath
+ filepath: sourceFilePath,
+ plugins: ['prettier-plugin-hermes-parser'],
}),
{
...config,
filepath: sourceFilePath,
- parser: createFormattingParser(snapshotMatcherNames, inferredParser)
+ parser: createFormattingParser(snapshotMatcherNames, inferredParser),
+ plugins: ['prettier-plugin-hermes-parser'],
}
);
};
@@ -348,7 +299,12 @@ const createFormattingParser =
(snapshotMatcherNames, inferredParser) => (text, parsers, options) => {
// Workaround for https://github.com/prettier/prettier/issues/3150
options.parser = inferredParser;
- const ast = parsers[inferredParser](text, options);
+ const ast = HermesParser.parse(text, {
+ babel: true,
+ enableExperimentalComponentSyntax: true,
+ sourceType: 'unambiguous',
+ });
+
traverse(ast, (node, ancestors) => {
if (node.type !== 'CallExpression') return;
const {arguments: args, callee} = node;
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.
This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.