Skip to content

Commit

Permalink
use babel plugin to inject bound fs
Browse files Browse the repository at this point in the history
  • Loading branch information
SimenB committed Dec 24, 2018
1 parent 7ff8646 commit 1265cd0
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 43 deletions.
44 changes: 22 additions & 22 deletions packages/jest-snapshot/src/__tests__/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/

jest.mock('../bound_fs', () => ({
boundExistsSync: jest.fn(() => true),
boundReadFile: jest.fn(),
boundWriteFile: jest.fn(),
}));
jest.mock('fs');

const fs = require('fs');
const path = require('path');
const chalk = require('chalk');
const boundFs = require('../bound_fs');

const {
getSnapshotData,
Expand All @@ -27,8 +23,18 @@ const {
SNAPSHOT_VERSION_WARNING,
} = require('../utils');

const writeFileSync = fs.writeFileSync;
const readFileSync = fs.readFileSync;
const existsSync = fs.existsSync;
beforeEach(() => {
jest.clearAllMocks();
fs.writeFileSync = jest.fn();
fs.readFileSync = jest.fn();
fs.existsSync = jest.fn(() => true);
});
afterEach(() => {
fs.writeFileSync = writeFileSync;
fs.readFileSync = readFileSync;
fs.existsSync = existsSync;
});

test('keyToTestName()', () => {
Expand All @@ -51,7 +57,7 @@ test('saveSnapshotFile() works with \r\n', () => {
};

saveSnapshotFile(data, filename);
expect(boundFs.boundWriteFile).toBeCalledWith(
expect(fs.writeFileSync).toBeCalledWith(
filename,
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`myKey`] = `<div>\n</div>`;\n',
Expand All @@ -65,7 +71,7 @@ test('saveSnapshotFile() works with \r', () => {
};

saveSnapshotFile(data, filename);
expect(boundFs.boundWriteFile).toBeCalledWith(
expect(fs.writeFileSync).toBeCalledWith(
filename,
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`myKey`] = `<div>\n</div>`;\n',
Expand All @@ -74,9 +80,7 @@ test('saveSnapshotFile() works with \r', () => {

test('getSnapshotData() throws when no snapshot version', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
() => 'exports[`myKey`] = `<div>\n</div>`;\n',
);
fs.readFileSync = jest.fn(() => 'exports[`myKey`] = `<div>\n</div>`;\n');
const update = 'none';

expect(() => getSnapshotData(filename, update)).toThrowError(
Expand All @@ -91,7 +95,7 @@ test('getSnapshotData() throws when no snapshot version', () => {

test('getSnapshotData() throws for older snapshot version', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
fs.readFileSync = jest.fn(
() =>
`// Jest Snapshot v0.99, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`myKey`] = `<div>\n</div>`;\n',
Expand All @@ -114,7 +118,7 @@ test('getSnapshotData() throws for older snapshot version', () => {

test('getSnapshotData() throws for newer snapshot version', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
fs.readFileSync = jest.fn(
() =>
`// Jest Snapshot v2, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`myKey`] = `<div>\n</div>`;\n',
Expand All @@ -137,27 +141,23 @@ test('getSnapshotData() throws for newer snapshot version', () => {

test('getSnapshotData() does not throw for when updating', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
() => 'exports[`myKey`] = `<div>\n</div>`;\n',
);
fs.readFileSync = jest.fn(() => 'exports[`myKey`] = `<div>\n</div>`;\n');
const update = 'all';

expect(() => getSnapshotData(filename, update)).not.toThrow();
});

test('getSnapshotData() marks invalid snapshot dirty when updating', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
() => 'exports[`myKey`] = `<div>\n</div>`;\n',
);
fs.readFileSync = jest.fn(() => 'exports[`myKey`] = `<div>\n</div>`;\n');
const update = 'all';

expect(getSnapshotData(filename, update)).toMatchObject({dirty: true});
});

test('getSnapshotData() marks valid snapshot not dirty when updating', () => {
const filename = path.join(__dirname, 'old-snapshot.snap');
boundFs.boundReadFile.mockImplementation(
fs.readFileSync = jest.fn(
() =>
`// Jest Snapshot v${SNAPSHOT_VERSION}, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`myKey`] = `<div>\n</div>`;\n',
Expand All @@ -171,7 +171,7 @@ test('escaping', () => {
const filename = path.join(__dirname, 'escaping.snap');
const data = '"\'\\';
saveSnapshotFile({key: data}, filename);
const writtenData = boundFs.boundWriteFile.mock.calls[0][1];
const writtenData = fs.writeFileSync.mock.calls[0][1];
expect(writtenData).toBe(
`// Jest Snapshot v1, ${SNAPSHOT_GUIDE_LINK}\n\n` +
'exports[`key`] = `"\'\\\\`;\n',
Expand Down
16 changes: 0 additions & 16 deletions packages/jest-snapshot/src/bound_fs.js

This file was deleted.

9 changes: 4 additions & 5 deletions packages/jest-snapshot/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import type {Path, SnapshotUpdateState} from 'types/Config';

import {getSerializers} from './plugins';
import chalk from 'chalk';
import fs from 'fs';
import mkdirp from 'mkdirp';
import naturalCompare from 'natural-compare';
import path from 'path';
import prettyFormat from 'pretty-format';

import {boundReadFile, boundWriteFile, boundExistsSync} from './bound_fs';

export const SNAPSHOT_VERSION = '1';
const SNAPSHOT_VERSION_REGEXP = /^\/\/ Jest Snapshot v(.+),/;
export const SNAPSHOT_GUIDE_LINK = 'https://goo.gl/fbAQLP';
Expand Down Expand Up @@ -100,9 +99,9 @@ export const getSnapshotData = (
let snapshotContents = '';
let dirty = false;

if (boundExistsSync(snapshotPath)) {
if (fs.existsSync(snapshotPath)) {
try {
snapshotContents = boundReadFile(snapshotPath, 'utf8');
snapshotContents = fs.readFileSync(snapshotPath, 'utf8');
// eslint-disable-next-line no-new-func
const populate = new Function('exports', snapshotContents);
// $FlowFixMe
Expand Down Expand Up @@ -173,7 +172,7 @@ export const saveSnapshotFile = (
);

ensureDirectoryExists(snapshotPath);
boundWriteFile(
fs.writeFileSync(
snapshotPath,
writeSnapshotVersion() + '\n\n' + snapshots.join('\n\n') + '\n',
);
Expand Down
16 changes: 16 additions & 0 deletions packages/jest-util/src/installCommonGlobals.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import type {ConfigGlobals} from 'types/Config';
import type {Global} from 'types/Global';

import fs from 'fs';
import createProcessObject from './createProcessObject';
import deepCyclicCopy from './deepCyclicCopy';

Expand All @@ -31,6 +32,21 @@ export default function(globalObject: Global, globals: ConfigGlobals) {
value: globalObject.Date.now.bind(globalObject.Date),
writable: false,
},
[symbol.for('jest-native-read-file')]: {
enumerable: false,
value: fs.readFileSync.bind(fs),
writable: false,
},
[symbol.for('jest-native-write-file')]: {
enumerable: false,
value: fs.writeFileSync.bind(fs),
writable: false,
},
[symbol.for('jest-native-exists-file')]: {
enumerable: false,
value: fs.existsSync.bind(fs),
writable: false,
},
'jest-symbol-do-not-touch': {
enumerable: false,
value: symbol,
Expand Down
50 changes: 50 additions & 0 deletions scripts/babel-plugin-jest-native-globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ module.exports = ({template}) => {
const nowDeclaration = template(`
var jestNow = global[Symbol.for('jest-native-now')] || global.Date.now;
`);
const fsReadFileDeclaration = template(`
var jestReadFile = global[Symbol.for('jest-native-read-file')] || fs.readFileSync;
`);
const fsWriteFileDeclaration = template(`
var jestWriteFile = global[Symbol.for('jest-native-write-file')] || fs.writeFileSync;
`);
const fsExistsFileDeclaration = template(`
var jestExistsFile = global[Symbol.for('jest-native-exists-file')] || fs.existsSync;
`);

return {
name: 'jest-native-globals',
Expand Down Expand Up @@ -57,6 +66,47 @@ module.exports = ({template}) => {

path.parentPath.replaceWithSourceString('jestNow');
}
if (
path.node.name === 'fs' &&
path.parent.property &&
['readFileSync', 'writeFileSync', 'existsSync'].includes(
path.parent.property.name
)
) {
if (!state.jestInjectedRead && path.parent.property.name === 'readFileSync') {
state.jestInjectedRead = true;
path
.findParent(p => p.isProgram())
.unshiftContainer('body', fsReadFileDeclaration());
path
.findParent(p => p.isProgram())
.unshiftContainer('body', symbolDeclaration());

path.parentPath.replaceWithSourceString('jestReadFile');
}
if (!state.jestInjectedWrite && path.parent.property.name === 'writeFileSync') {
state.jestInjectedWrite = true;
path
.findParent(p => p.isProgram())
.unshiftContainer('body', fsWriteFileDeclaration());
path
.findParent(p => p.isProgram())
.unshiftContainer('body', symbolDeclaration());

path.parentPath.replaceWithSourceString('jestWriteFile');
}
if (!state.jestInjectedExists && path.parent.property.name === 'existsSync') {
state.jestInjectedExists = true;
path
.findParent(p => p.isProgram())
.unshiftContainer('body', fsExistsFileDeclaration());
path
.findParent(p => p.isProgram())
.unshiftContainer('body', symbolDeclaration());

path.parentPath.replaceWithSourceString('jestExistsFile');
}
}
},
},
};
Expand Down

0 comments on commit 1265cd0

Please sign in to comment.