node-jest/e2e/__tests__/snapshot.test.ts

332 lines
11 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* 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 {extractSummary} from '../Utils';
import runJest, {json as runWithJson} from '../runJest';
const emptyTest = 'describe("", () => {it("", () => {})})';
const snapshotDir = path.resolve(
__dirname,
'../snapshot/__tests__/__snapshots__',
);
const snapshotFile = path.resolve(snapshotDir, 'snapshot.test.js.snap');
const secondSnapshotFile = path.resolve(
snapshotDir,
'secondSnapshot.test.js.snap',
);
const snapshotOfCopy = path.resolve(snapshotDir, 'snapshot.test_copy.js.snap');
const originalTestPath = path.resolve(
__dirname,
'../snapshot/__tests__/snapshot.test.js',
);
const originalTestContent = fs.readFileSync(originalTestPath, 'utf8');
const copyOfTestPath = originalTestPath.replace(/\.js$/, '_copy.js');
const snapshotEscapeDir = path.resolve(
__dirname,
'../snapshot-escape/__tests__/',
);
const snapshotEscapeTestFile = path.resolve(
snapshotEscapeDir,
'snapshot.test.js',
);
const snapshotEscapeSnapshotDir = path.resolve(
snapshotEscapeDir,
'__snapshots__',
);
const snapshotEscapeFile = path.resolve(
snapshotEscapeSnapshotDir,
'snapshot.test.js.snap',
);
const snapshotEscapeRegexFile = path.resolve(
snapshotEscapeSnapshotDir,
'snapshotEscapeRegex.js.snap',
);
const snapshotEscapeSubstitutionFile = path.resolve(
snapshotEscapeSnapshotDir,
'snapshotEscapeSubstitution.test.js.snap',
);
const initialTestData = fs.readFileSync(snapshotEscapeTestFile, 'utf8');
const fileExists = (filePath: string) => {
try {
return fs.statSync(filePath).isFile();
} catch {}
return false;
};
const getSnapshotOfCopy = () => {
const exports = Object.create(null);
// eslint-disable-next-line no-eval
eval(fs.readFileSync(snapshotOfCopy, 'utf8'));
return exports;
};
describe('Snapshot', () => {
const cleanup = () => {
[
snapshotFile,
secondSnapshotFile,
snapshotOfCopy,
copyOfTestPath,
snapshotEscapeFile,
snapshotEscapeRegexFile,
snapshotEscapeSubstitutionFile,
].forEach(file => {
if (fileExists(file)) {
fs.unlinkSync(file);
}
});
if (fileExists(snapshotDir)) {
fs.rmdirSync(snapshotDir);
}
if (fileExists(snapshotEscapeSnapshotDir)) {
fs.rmdirSync(snapshotEscapeSnapshotDir);
}
fs.writeFileSync(snapshotEscapeTestFile, initialTestData, 'utf8');
};
beforeEach(cleanup);
afterAll(cleanup);
it('stores new snapshots on the first run', () => {
const {exitCode, json, stderr} = runWithJson('snapshot', [
'-w=1',
'--ci=false',
]);
expect(json.numTotalTests).toBe(5);
expect(json.numPassedTests).toBe(5);
expect(json.numFailedTests).toBe(0);
expect(json.numPendingTests).toBe(0);
expect(exitCode).toBe(0);
const content = require(snapshotFile);
expect(
content['snapshot is not influenced by previous counter 1'],
).not.toBeUndefined();
expect(stderr).toMatch('5 snapshots written from 2 test suites');
expect(extractSummary(stderr).summary).toMatchSnapshot();
});
it('works with escaped characters', () => {
// Write the first snapshot
let result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshot.test.js',
]);
let stderr = result.stderr;
expect(stderr).toMatch('1 snapshot written');
expect(result.exitCode).toBe(0);
expect(extractSummary(stderr).summary).toMatchSnapshot();
// Write the second snapshot
const testData =
"test('escape strings two', () => expect('two: \\'\"')." +
'toMatchSnapshot());';
const newTestData = initialTestData + testData;
fs.writeFileSync(snapshotEscapeTestFile, newTestData, 'utf8');
result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'--updateSnapshot',
'snapshot.test.js',
]);
stderr = result.stderr;
expect(stderr).toMatch('1 snapshot written');
expect(extractSummary(stderr).summary).toMatchSnapshot();
expect(result.exitCode).toBe(0);
// Now let's check again if everything still passes.
// If this test doesn't pass, some snapshot data was not properly escaped.
result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshot.test.js',
]);
stderr = result.stderr;
expect(stderr).not.toMatch('Snapshot Summary');
expect(extractSummary(stderr).summary).toMatchSnapshot();
expect(result.exitCode).toBe(0);
});
it('works with escaped regex', () => {
// Write the first snapshot
let result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshotEscapeRegex.js',
]);
let stderr = result.stderr;
expect(stderr).toMatch('2 snapshots written from 1 test suite.');
expect(result.exitCode).toBe(0);
expect(extractSummary(stderr).summary).toMatchSnapshot();
result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshotEscapeRegex.js',
]);
stderr = result.stderr;
// Make sure we aren't writing a snapshot this time which would
// indicate that the snapshot couldn't be loaded properly.
expect(stderr).not.toMatch('Snapshot Summary');
expect(extractSummary(stderr).summary).toMatchSnapshot();
expect(result.exitCode).toBe(0);
});
it('works with template literal substitutions', () => {
// Write the first snapshot
let result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshotEscapeSubstitution.test.js',
]);
let stderr = result.stderr;
expect(stderr).toMatch('1 snapshot written');
expect(result.exitCode).toBe(0);
expect(extractSummary(stderr).summary).toMatchSnapshot();
result = runJest('snapshot-escape', [
'-w=1',
'--ci=false',
'snapshotEscapeSubstitution.test.js',
]);
stderr = result.stderr;
// Make sure we aren't writing a snapshot this time which would
// indicate that the snapshot couldn't be loaded properly.
expect(stderr).not.toMatch('1 snapshot written');
expect(extractSummary(stderr).summary).toMatchSnapshot();
expect(result.exitCode).toBe(0);
});
describe('Validation', () => {
beforeEach(() => {
fs.writeFileSync(copyOfTestPath, originalTestContent);
});
it('does not save snapshots in CI mode by default', () => {
const result = runWithJson('snapshot', ['-w=1', '--ci=true']);
expect(result.json.success).toBe(false);
expect(result.json.numTotalTests).toBe(9);
expect(result.json.snapshot.added).toBe(0);
expect(result.json.snapshot.total).toBe(9);
const {rest, summary} = extractSummary(result.stderr);
expect(rest).toMatch('New snapshot was not written');
expect(summary).toMatchSnapshot();
});
it('works on subsequent runs without `-u`', () => {
const firstRun = runWithJson('snapshot', ['-w=1', '--ci=false']);
const content = require(snapshotOfCopy);
expect(content).not.toBe(undefined);
const secondRun = runWithJson('snapshot', []);
expect(firstRun.json.numTotalTests).toBe(9);
expect(secondRun.json.numTotalTests).toBe(9);
expect(secondRun.json.success).toBe(true);
expect(firstRun.stderr).toMatch('9 snapshots written from 3 test suites');
expect(secondRun.stderr).toMatch('9 passed, 9 total');
expect(extractSummary(firstRun.stderr).summary).toMatchSnapshot();
expect(extractSummary(secondRun.stderr).summary).toMatchSnapshot();
});
it('deletes the snapshot if the test suite has been removed', () => {
const firstRun = runWithJson('snapshot', ['-w=1', '--ci=false']);
fs.unlinkSync(copyOfTestPath);
const content = require(snapshotOfCopy);
expect(content).not.toBe(undefined);
const secondRun = runWithJson('snapshot', ['-w=1', '--ci=false', '-u']);
expect(firstRun.json.numTotalTests).toBe(9);
expect(secondRun.json.numTotalTests).toBe(5);
expect(fileExists(snapshotOfCopy)).toBe(false);
expect(firstRun.stderr).toMatch('9 snapshots written from 3 test suites');
expect(secondRun.stderr).toMatch(
'1 snapshot file removed from 1 test suite',
);
expect(extractSummary(firstRun.stderr).summary).toMatchSnapshot();
expect(extractSummary(secondRun.stderr).summary).toMatchSnapshot();
});
it('deletes a snapshot when a test does removes all the snapshots', () => {
const firstRun = runWithJson('snapshot', ['-w=1', '--ci=false']);
fs.writeFileSync(copyOfTestPath, emptyTest);
const secondRun = runWithJson('snapshot', ['-w=1', '--ci=false', '-u']);
fs.unlinkSync(copyOfTestPath);
expect(firstRun.json.numTotalTests).toBe(9);
expect(secondRun.json.numTotalTests).toBe(6);
expect(fileExists(snapshotOfCopy)).toBe(false);
expect(firstRun.stderr).toMatch('9 snapshots written from 3 test suites');
expect(secondRun.stderr).toMatch(
'1 snapshot file removed from 1 test suite',
);
expect(extractSummary(firstRun.stderr).summary).toMatchSnapshot();
expect(extractSummary(secondRun.stderr).summary).toMatchSnapshot();
});
it('updates the snapshot when a test removes some snapshots', () => {
const firstRun = runWithJson('snapshot', ['-w=1', '--ci=false']);
fs.unlinkSync(copyOfTestPath);
const beforeRemovingSnapshot = getSnapshotOfCopy();
fs.writeFileSync(
copyOfTestPath,
originalTestContent.replace(
'.toMatchSnapshot()',
'.not.toBe(undefined)',
),
);
const secondRun = runWithJson('snapshot', ['-w=1', '--ci=false', '-u']);
fs.unlinkSync(copyOfTestPath);
expect(firstRun.json.numTotalTests).toBe(9);
expect(secondRun.json.numTotalTests).toBe(9);
expect(fileExists(snapshotOfCopy)).toBe(true);
const afterRemovingSnapshot = getSnapshotOfCopy();
expect(Object.keys(beforeRemovingSnapshot).length - 1).toBe(
Object.keys(afterRemovingSnapshot).length,
);
const keyToCheck =
'snapshot works with plain objects and the ' +
'title has `escape` characters 2';
expect(beforeRemovingSnapshot[keyToCheck]).not.toBe(undefined);
expect(afterRemovingSnapshot[keyToCheck]).toBe(undefined);
expect(extractSummary(firstRun.stderr).summary).toMatchSnapshot();
expect(firstRun.stderr).toMatch('9 snapshots written from 3 test suites');
expect(extractSummary(secondRun.stderr).summary).toMatchSnapshot();
expect(secondRun.stderr).toMatch('1 snapshot updated from 1 test suite');
expect(secondRun.stderr).toMatch('1 snapshot removed from 1 test suite');
});
});
});