Files
jest/e2e/__tests__/toMatchInlineSnapshot.test.ts

418 lines
14 KiB
TypeScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as path from 'path';
import * as fs from 'graceful-fs';
import {cleanup, extractSummary, makeTemplate, writeFiles} from '../Utils';
import runJest from '../runJest';
const DIR = path.resolve(__dirname, '../to-match-inline-snapshot');
const TESTS_DIR = path.resolve(DIR, '__tests__');
const readFile = (filename: string) =>
fs.readFileSync(path.join(TESTS_DIR, filename), 'utf8');
beforeEach(() => cleanup(TESTS_DIR));
afterAll(() => cleanup(TESTS_DIR));
test('basic support', () => {
const filename = 'basic-support.test.js';
const template = makeTemplate(
"test('inline snapshots', () => expect($1).toMatchInlineSnapshot());\n",
);
{
writeFiles(TESTS_DIR, {
[filename]: template(['{apple: "original value"}']),
});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('initial write');
}
{
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshots: 1 passed, 1 total');
expect(stderr).not.toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('snapshot passed');
}
{
writeFiles(TESTS_DIR, {
[filename]: readFile(filename).replace('original value', 'updated value'),
});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshot name: `inline snapshots 1`');
expect(exitCode).toBe(1);
expect(fileAfter).toMatchSnapshot('snapshot mismatch');
}
{
const {stderr, exitCode} = runJest(DIR, [
'-w=1',
'--ci=false',
filename,
'-u',
]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot updated from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('snapshot updated');
}
});
test('do not indent empty lines', () => {
const filename = 'empty-line-indent.test.js';
const template = makeTemplate(
"test('inline snapshots', () => expect($1).toMatchInlineSnapshot());\n",
);
{
writeFiles(TESTS_DIR, {
[filename]: template(['`hello\n\nworld`']),
});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('initial write');
}
{
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshots: 1 passed, 1 total');
expect(stderr).not.toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('snapshot passed');
}
});
test('handles property matchers', () => {
const filename = 'handle-property-matchers.test.js';
const template = makeTemplate(`test('handles property matchers', () => {
expect({createdAt: $1}).toMatchInlineSnapshot({createdAt: expect.any(Date)});
});
`);
{
writeFiles(TESTS_DIR, {[filename]: template(['new Date()'])});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('initial write');
}
{
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshots: 1 passed, 1 total');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('snapshot passed');
}
{
writeFiles(TESTS_DIR, {
[filename]: readFile(filename).replace('new Date()', '"string"'),
});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshot name: `handles property matchers 1`');
expect(stderr).toMatch('Snapshots: 1 failed, 1 total');
expect(exitCode).toBe(1);
expect(fileAfter).toMatchSnapshot('snapshot failed');
}
{
writeFiles(TESTS_DIR, {
[filename]: readFile(filename).replace('any(Date)', 'any(String)'),
});
const {stderr, exitCode} = runJest(DIR, [
'-w=1',
'--ci=false',
filename,
'-u',
]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot updated from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('snapshot updated');
}
});
test('removes obsolete external snapshots', () => {
const filename = 'removes-obsolete-external-snapshots.test.js';
const snapshotPath = path.join(
TESTS_DIR,
'__snapshots__',
`${filename}.snap`,
);
const template = makeTemplate(`
test('removes obsolete external snapshots', () => {
expect('1').$1();
});
`);
{
writeFiles(TESTS_DIR, {[filename]: template(['toMatchSnapshot'])});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('initial write');
expect(fs.existsSync(snapshotPath)).toBe(true);
}
{
writeFiles(TESTS_DIR, {[filename]: template(['toMatchInlineSnapshot'])});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshots: 1 obsolete, 1 written, 1 total');
expect(exitCode).toBe(1);
expect(fileAfter).toMatchSnapshot('inline snapshot written');
expect(fs.existsSync(snapshotPath)).toBe(true);
}
{
const {stderr, exitCode} = runJest(DIR, [
'-w=1',
'--ci=false',
filename,
'-u',
]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('Snapshots: 1 file removed, 1 passed, 1 total');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('external snapshot cleaned');
expect(fs.existsSync(snapshotPath)).toBe(false);
}
});
test('supports async matchers', () => {
const filename = 'async-matchers.test.js';
const test = `
test('inline snapshots', async () => {
expect(Promise.resolve('success')).resolves.toMatchInlineSnapshot();
expect(Promise.reject('fail')).rejects.toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('2 snapshots written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot();
});
test('supports async tests', () => {
const filename = 'async.test.js';
const test = `
test('inline snapshots', async () => {
await 'next tick';
expect(42).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot();
});
test('writes snapshots with non-literals in expect(...)', () => {
const filename = 'async.test.js';
const test = `
it('works with inline snapshots', () => {
expect({a: 1}).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot();
});
// issue: https://github.com/jestjs/jest/issues/6702
test('handles mocking native modules prettier relies on', () => {
const filename = 'mockFail.test.js';
const test = `
jest.mock('path', () => ({}));
jest.mock('fs', () => ({}));
jest.mock('graceful-fs', () => ({}));
test('inline snapshots', () => {
expect({}).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
});
test('supports custom matchers', () => {
const filename = 'custom-matchers.test.js';
const test = `
const { toMatchInlineSnapshot } = require('jest-snapshot');
expect.extend({
toMatchCustomInlineSnapshot(received, ...args) {
return toMatchInlineSnapshot.call(this, received, ...args);
}
});
test('inline snapshots', () => {
expect({apple: "original value"}).toMatchCustomInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('custom matchers');
});
test('supports custom matchers with property matcher', () => {
const filename = 'custom-matchers-with-property-matcher.test.js';
const test = `
const { toMatchInlineSnapshot } = require('jest-snapshot');
expect.extend({
toMatchCustomInlineSnapshot(received, ...args) {
return toMatchInlineSnapshot.call(this, received, ...args);
},
toMatchUserInlineSnapshot(received, ...args) {
return toMatchInlineSnapshot.call(
this,
received,
{
createdAt: expect.any(Date),
id: expect.any(Number),
},
...args
);
},
});
test('inline snapshots', () => {
const user = {
createdAt: new Date(),
id: Math.floor(Math.random() * 20),
name: 'LeBron James',
};
expect(user).toMatchCustomInlineSnapshot({
createdAt: expect.any(Date),
id: expect.any(Number),
});
expect(user).toMatchUserInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('2 snapshots written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('custom matchers with property matcher');
});
test('multiple custom matchers and native matchers', () => {
const filename = 'multiple-matchers.test.js';
const test = `
const { toMatchInlineSnapshot } = require('jest-snapshot');
expect.extend({
toMatchCustomInlineSnapshot(received, ...args) {
return toMatchInlineSnapshot.call(this, received, ...args);
},
toMatchCustomInlineSnapshot2(received, ...args) {
return toMatchInlineSnapshot.call(this, received, ...args);
},
});
test('inline snapshots', () => {
expect({apple: "value 1"}).toMatchCustomInlineSnapshot();
expect({apple: "value 2"}).toMatchInlineSnapshot();
expect({apple: "value 3"}).toMatchCustomInlineSnapshot2();
expect({apple: "value 4"}).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('4 snapshots written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('multiple matchers');
});
test('indentation is correct in the presences of existing snapshots', () => {
const filename = 'existing-snapshot.test.js';
const test = `
test('existing snapshot', () => {
expect({ hello: 'world' }).toMatchInlineSnapshot(\`
{
"hello": "world",
}
\`);
expect({ hello: 'world' }).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('existing snapshot');
});
test('indentation is correct in the presences of existing snapshots, when the file is correctly formatted by prettier', () => {
const filename = 'existing-snapshot.test.js';
// A prettier-formatted file has no leading blank line and ends with a single
// trailing newline; skipTrim keeps the newline that dedent would otherwise eat.
const test = ` it('is true', () => {
expect(true).toMatchInlineSnapshot(\`true\`);
expect([1, 2, 3]).toMatchInlineSnapshot();
});
`;
writeFiles(TESTS_DIR, {[filename]: test}, {skipTrim: true});
const {stderr, exitCode} = runJest(DIR, ['-w=1', '--ci=false', filename]);
const fileAfter = readFile(filename);
expect(stderr).toMatch('1 snapshot written from 1 test suite.');
expect(exitCode).toBe(0);
expect(fileAfter).toMatchSnapshot('existing snapshot');
});
test('diff with prototype is correct', () => {
const filename = 'with-prototype-diff.test.js';
const test = `
test('diff with prototype is correct', () => {
expect({ hello: 'world' }).toMatchInlineSnapshot(\`
Object {
"hello": "world",
}
\`);
});
`;
writeFiles(TESTS_DIR, {[filename]: test});
const {stderr, exitCode} = runJest(DIR, ['--run-in-band', filename]);
expect(extractSummary(stderr).rest).toMatchSnapshot();
expect(exitCode).toBe(1);
});