|
| 1 | +/** |
| 2 | + * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | + * |
| 4 | + * This source code is licensed under the MIT license found in the |
| 5 | + * LICENSE file in the root directory of this source tree. |
| 6 | + */ |
| 7 | + |
| 8 | +jest.mock('graceful-fs', () => ({ |
| 9 | + ...jest.createMockFromModule<typeof import('fs')>('fs'), |
| 10 | + existsSync: jest.fn().mockReturnValue(true), |
| 11 | +})); |
| 12 | + |
| 13 | +import * as path from 'path'; |
| 14 | +import chalk = require('chalk'); |
| 15 | +import * as fs from 'graceful-fs'; |
| 16 | +import { |
| 17 | + SNAPSHOT_GUIDE_LINK, |
| 18 | + SNAPSHOT_VERSION, |
| 19 | + SNAPSHOT_VERSION_WARNING, |
| 20 | + getSnapshotData, |
| 21 | + keyToTestName, |
| 22 | + saveSnapshotFile, |
| 23 | + testNameToKey, |
| 24 | +} from '../utils'; |
| 25 | + |
| 26 | +test('keyToTestName()', () => { |
| 27 | + expect(keyToTestName('abc cde 12')).toBe('abc cde'); |
| 28 | + expect(keyToTestName('abc cde 12')).toBe('abc cde '); |
| 29 | + expect(() => keyToTestName('abc cde')).toThrow( |
| 30 | + 'Snapshot keys must end with a number.', |
| 31 | + ); |
| 32 | +}); |
| 33 | + |
| 34 | +test('testNameToKey', () => { |
| 35 | + expect(testNameToKey('abc cde', 1)).toBe('abc cde 1'); |
| 36 | + expect(testNameToKey('abc cde ', 12)).toBe('abc cde 12'); |
| 37 | +}); |
| 38 | + |
| 39 | +test('saveSnapshotFile() works with \r\n', () => { |
| 40 | + const filename = path.join(__dirname, 'remove-newlines.snap'); |
| 41 | + const data = { |
| 42 | + myKey: '<div>\r\n</div>', |
| 43 | + }; |
| 44 | + |
| 45 | + saveSnapshotFile(data, filename); |
| 46 | + expect(fs.writeFileSync).toHaveBeenCalledWith( |
| 47 | + filename, |
| 48 | + `// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 49 | + 'exports[`myKey`] = `<div>\n</div>`;\n', |
| 50 | + ); |
| 51 | +}); |
| 52 | + |
| 53 | +test('saveSnapshotFile() works with \r', () => { |
| 54 | + const filename = path.join(__dirname, 'remove-newlines.snap'); |
| 55 | + const data = { |
| 56 | + myKey: '<div>\r</div>', |
| 57 | + }; |
| 58 | + |
| 59 | + saveSnapshotFile(data, filename); |
| 60 | + expect(fs.writeFileSync).toHaveBeenCalledWith( |
| 61 | + filename, |
| 62 | + `// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 63 | + 'exports[`myKey`] = `<div>\n</div>`;\n', |
| 64 | + ); |
| 65 | +}); |
| 66 | + |
| 67 | +test('getSnapshotData() throws when no snapshot version', () => { |
| 68 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 69 | + jest |
| 70 | + .mocked(fs.readFileSync) |
| 71 | + .mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n'); |
| 72 | + const update = 'none'; |
| 73 | + |
| 74 | + expect(() => getSnapshotData(filename, update)).toThrow( |
| 75 | + chalk.red( |
| 76 | + `${chalk.bold('Outdated snapshot')}: No snapshot header found. ` + |
| 77 | + 'Jest 19 introduced versioned snapshots to ensure all developers on ' + |
| 78 | + 'a project are using the same version of Jest. ' + |
| 79 | + 'Please update all snapshots during this upgrade of Jest.\n\n', |
| 80 | + ) + SNAPSHOT_VERSION_WARNING, |
| 81 | + ); |
| 82 | +}); |
| 83 | + |
| 84 | +test('getSnapshotData() throws for older snapshot version', () => { |
| 85 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 86 | + jest |
| 87 | + .mocked(fs.readFileSync) |
| 88 | + .mockReturnValue( |
| 89 | + `// Jest Snapshot v0.99, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 90 | + 'exports[`myKey`] = `<div>\n</div>`;\n', |
| 91 | + ); |
| 92 | + const update = 'none'; |
| 93 | + |
| 94 | + expect(() => getSnapshotData(filename, update)).toThrow( |
| 95 | + `${chalk.red( |
| 96 | + `${chalk.red.bold('Outdated snapshot')}: The version of the snapshot ` + |
| 97 | + 'file associated with this test is outdated. The snapshot file ' + |
| 98 | + 'version ensures that all developers on a project are using ' + |
| 99 | + 'the same version of Jest. ' + |
| 100 | + 'Please update all snapshots during this upgrade of Jest.', |
| 101 | + )}\n\nExpected: v${SNAPSHOT_VERSION}\n` + |
| 102 | + `Received: v0.99\n\n${SNAPSHOT_VERSION_WARNING}`, |
| 103 | + ); |
| 104 | +}); |
| 105 | + |
| 106 | +test('getSnapshotData() throws for newer snapshot version', () => { |
| 107 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 108 | + jest |
| 109 | + .mocked(fs.readFileSync) |
| 110 | + .mockReturnValue( |
| 111 | + `// Jest Snapshot v2, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 112 | + 'exports[`myKey`] = `<div>\n</div>`;\n', |
| 113 | + ); |
| 114 | + const update = 'none'; |
| 115 | + |
| 116 | + expect(() => getSnapshotData(filename, update)).toThrow( |
| 117 | + `${chalk.red( |
| 118 | + `${chalk.red.bold('Outdated Jest version')}: The version of this ` + |
| 119 | + 'snapshot file indicates that this project is meant to be used ' + |
| 120 | + 'with a newer version of Jest. ' + |
| 121 | + 'The snapshot file version ensures that all developers on a project ' + |
| 122 | + 'are using the same version of Jest. ' + |
| 123 | + 'Please update your version of Jest and re-run the tests.', |
| 124 | + )}\n\nExpected: v${SNAPSHOT_VERSION}\nReceived: v2`, |
| 125 | + ); |
| 126 | +}); |
| 127 | + |
| 128 | +test('getSnapshotData() does not throw for when updating', () => { |
| 129 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 130 | + jest |
| 131 | + .mocked(fs.readFileSync) |
| 132 | + .mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n'); |
| 133 | + const update = 'all'; |
| 134 | + |
| 135 | + expect(() => getSnapshotData(filename, update)).not.toThrow(); |
| 136 | +}); |
| 137 | + |
| 138 | +test('getSnapshotData() marks invalid snapshot dirty when updating', () => { |
| 139 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 140 | + jest |
| 141 | + .mocked(fs.readFileSync) |
| 142 | + .mockReturnValue('exports[`myKey`] = `<div>\n</div>`;\n'); |
| 143 | + const update = 'all'; |
| 144 | + |
| 145 | + expect(getSnapshotData(filename, update)).toMatchObject({dirty: true}); |
| 146 | +}); |
| 147 | + |
| 148 | +test('getSnapshotData() marks valid snapshot not dirty when updating', () => { |
| 149 | + const filename = path.join(__dirname, 'old-snapshot.snap'); |
| 150 | + jest |
| 151 | + .mocked(fs.readFileSync) |
| 152 | + .mockReturnValue( |
| 153 | + `// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 154 | + 'exports[`myKey`] = `<div>\n</div>`;\n', |
| 155 | + ); |
| 156 | + const update = 'all'; |
| 157 | + |
| 158 | + expect(getSnapshotData(filename, update)).toMatchObject({dirty: false}); |
| 159 | +}); |
| 160 | + |
| 161 | +test('escaping', () => { |
| 162 | + const filename = path.join(__dirname, 'escaping.snap'); |
| 163 | + const data = '"\'\\'; |
| 164 | + const writeFileSync = jest.mocked(fs.writeFileSync); |
| 165 | + |
| 166 | + writeFileSync.mockReset(); |
| 167 | + saveSnapshotFile({key: data}, filename); |
| 168 | + const writtenData = writeFileSync.mock.calls[0][1]; |
| 169 | + expect(writtenData).toBe( |
| 170 | + `// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` + |
| 171 | + 'exports[`key`] = `"\'\\\\`;\n', |
| 172 | + ); |
| 173 | + |
| 174 | + // eslint-disable-next-line no-eval |
| 175 | + const readData = eval(`var exports = {}; ${writtenData} exports`); |
| 176 | + expect(readData).toEqual({key: data}); |
| 177 | + const snapshotData = readData.key; |
| 178 | + expect(data).toEqual(snapshotData); |
| 179 | +}); |
0 commit comments