Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(jest-snapshot): type prettier usage properly #10505

Merged
merged 2 commits into from
Sep 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/jest-snapshot/src/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ export default class SnapshotState {
private _snapshotPath: Config.Path;
private _inlineSnapshots: Array<InlineSnapshot>;
private _uncheckedKeys: Set<string>;
private _getBabelTraverse: () => BabelTraverse;
private _getPrettier: () => null | typeof import('prettier');
private _getBabelTraverse: SnapshotStateOptions['getBabelTraverse'];
private _getPrettier: SnapshotStateOptions['getPrettier'];

added: number;
expand: boolean;
Expand Down
55 changes: 24 additions & 31 deletions packages/jest-snapshot/src/inline_snapshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
import * as path from 'path';
import * as fs from 'graceful-fs';
import semver = require('semver');
import {
CallExpression,
file,
templateElement,
templateLiteral,
} from '@babel/types';
import {file, templateElement, templateLiteral} from '@babel/types';
import type {Frame} from 'jest-message-util';
import type {
CustomParser as PrettierCustomParser,
BuiltInParser as PrettierParser,
BuiltInParserName as PrettierParserName,
} from 'prettier';
import type {Config} from '@jest/types';
import type {BabelTraverse, Prettier} from './types';
import {escapeBacktickString} from './utils';

type PrettierParserMap = Record<PrettierParserName, PrettierParser>;

export type InlineSnapshot = {
snapshot: string;
frame: Frame;
Expand Down Expand Up @@ -59,22 +61,21 @@ export function saveInlineSnapshots(
const saveSnapshotsForFile = (
snapshots: Array<InlineSnapshot>,
sourceFilePath: Config.Path,
prettier: any,
prettier: Prettier,
babelTraverse: BabelTraverse,
) => {
const sourceFile = fs.readFileSync(sourceFilePath, 'utf8');

// Resolve project configuration.
// For older versions of Prettier, do not load configuration.
const config = prettier.resolveConfig
? prettier.resolveConfig.sync(sourceFilePath, {
editorconfig: true,
})
? prettier.resolveConfig.sync(sourceFilePath, {editorconfig: true})
: null;

// Detect the parser for the test file.
// For older versions of Prettier, fallback to a simple parser detection.
const inferredParser = prettier.getFileInfo
// @ts-expect-error
const inferredParser: PrettierParserName = prettier.getFileInfo
? prettier.getFileInfo.sync(sourceFilePath).inferredParser
: (config && config.parser) || simpleDetectParser(sourceFilePath);

Expand Down Expand Up @@ -163,8 +164,8 @@ const indent = (snapshot: string, numIndents: number, indentation: string) => {
};

const getAst = (
parsers: Record<string, (text: string) => any>,
inferredParser: string,
parsers: PrettierParserMap,
inferredParser: PrettierParserName,
text: string,
) => {
// Flow uses a 'Program' parent node, babel expects a 'File'.
Expand All @@ -180,13 +181,9 @@ const getAst = (
const createInsertionParser = (
snapshots: Array<InlineSnapshot>,
snapshotMatcherNames: Array<string>,
inferredParser: string,
inferredParser: PrettierParserName,
babelTraverse: BabelTraverse,
) => (
text: string,
parsers: Record<string, (text: string) => any>,
options: any,
) => {
): PrettierCustomParser => (text, parsers, options) => {
// Workaround for https://github.com/prettier/prettier/issues/3150
options.parser = inferredParser;

Expand All @@ -195,7 +192,7 @@ const createInsertionParser = (

const ast = getAst(parsers, inferredParser, text);
babelTraverse(ast, {
CallExpression({node: {arguments: args, callee}}: {node: CallExpression}) {
CallExpression({node: {arguments: args, callee}}) {
if (
callee.type !== 'MemberExpression' ||
callee.property.type !== 'Identifier' ||
Expand Down Expand Up @@ -247,19 +244,15 @@ const createInsertionParser = (
// This parser formats snapshots to the correct indentation.
const createFormattingParser = (
snapshotMatcherNames: Array<string>,
inferredParser: string,
inferredParser: PrettierParserName,
babelTraverse: BabelTraverse,
) => (
text: string,
parsers: Record<string, (text: string) => any>,
options: any,
) => {
): PrettierCustomParser => (text, parsers, options) => {
// Workaround for https://github.com/prettier/prettier/issues/3150
options.parser = inferredParser;

const ast = getAst(parsers, inferredParser, text);
babelTraverse(ast, {
CallExpression({node: {arguments: args, callee}}: {node: CallExpression}) {
CallExpression({node: {arguments: args, callee}}) {
if (
callee.type !== 'MemberExpression' ||
callee.property.type !== 'Identifier' ||
Expand Down Expand Up @@ -288,10 +281,10 @@ const createFormattingParser = (
snapshot,
Math.ceil(
useSpaces
? callee.loc.start.column / options.tabWidth
? callee.loc.start.column / (options.tabWidth ?? 1)
: callee.loc.start.column / 2, // Each tab is 2 characters.
),
useSpaces ? ' '.repeat(options.tabWidth) : '\t',
useSpaces ? ' '.repeat(options.tabWidth ?? 1) : '\t',
);

const replacementNode = templateLiteral(
Expand All @@ -309,10 +302,10 @@ const createFormattingParser = (
return ast;
};

const simpleDetectParser = (filePath: Config.Path) => {
const simpleDetectParser = (filePath: Config.Path): PrettierParserName => {
const extname = path.extname(filePath);
if (/tsx?$/.test(extname)) {
return 'typescript';
}
return 'babylon';
return 'babel';
};