From 79cbda4e1fc4b1fa293a03794611ec072baf69fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Tue, 13 Jun 2017 17:22:05 +0200 Subject: [PATCH] Provide better error checking for transformed content (#3807) --- .../jest-mock/src/__tests__/jest-mock-test.js | 2 +- .../jest-runtime/src/ScriptTransformer.js | 7 ++- .../src/__tests__/ScriptTransformer-test.js | 51 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/jest-mock/src/__tests__/jest-mock-test.js b/packages/jest-mock/src/__tests__/jest-mock-test.js index ec95776159ef..3c793f2d03a8 100644 --- a/packages/jest-mock/src/__tests__/jest-mock-test.js +++ b/packages/jest-mock/src/__tests__/jest-mock-test.js @@ -187,7 +187,7 @@ describe('moduleMocker', () => { expect(typeof multipleBoundFuncMock).toBe('function'); }); - it('mocks methods that are bound after mocking', () => { + it('mocks methods that are bound after mocking', () => { const fooMock = moduleMocker.generateFromMetadata( moduleMocker.getMetadata(() => {}), ); diff --git a/packages/jest-runtime/src/ScriptTransformer.js b/packages/jest-runtime/src/ScriptTransformer.js index e6da9330959d..51778164e7e9 100644 --- a/packages/jest-runtime/src/ScriptTransformer.js +++ b/packages/jest-runtime/src/ScriptTransformer.js @@ -208,8 +208,13 @@ class ScriptTransformer { if (typeof processed === 'string') { transformed.code = processed; - } else { + } else if (processed != null && typeof processed.code === 'string') { transformed = processed; + } else { + throw new TypeError( + "Jest: a transform's `process` function must return a string, " + + 'or an object with `code` key containing this string.', + ); } } diff --git a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js index 0530e2b18cb7..661f6ea79b11 100644 --- a/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js +++ b/packages/jest-runtime/src/__tests__/ScriptTransformer-test.js @@ -75,6 +75,16 @@ jest.mock( {virtual: true}, ); +jest.mock( + 'passthrough-preprocessor', + () => { + return { + process: jest.fn(), + }; + }, + {virtual: true}, +); + const getCachePath = (fs, config) => { for (const path in mockFs) { if (path.startsWith(config.cacheDirectory)) { @@ -101,6 +111,9 @@ describe('ScriptTransformer', () => { mockFs = object({ '/fruits/banana.js': ['module.exports = "banana";'].join('\n'), + '/fruits/grapefruit.js': [ + 'module.exports = function () { return "grapefruit"; }', + ].join('\n'), '/fruits/kiwi.js': ['module.exports = () => "kiwi";'].join('\n'), '/node_modules/react.js': ['module.exports = "react";'].join('\n'), '/styles/App.css': ['root {', ' font-family: Helvetica;', '}'].join( @@ -180,6 +193,44 @@ describe('ScriptTransformer', () => { expect(vm.Script.mock.calls[1][0]).toEqual(snapshot); }); + it( + "throws an error if `process` doesn't return a string or an object" + + 'containing `code` key with processed string', + () => { + config = Object.assign(config, { + transform: [['^.+\\.js$', 'passthrough-preprocessor']], + }); + const scriptTransformer = new ScriptTransformer(config); + + const incorrectReturnValues = [ + [undefined, '/fruits/banana.js'], + [{a: 'a'}, '/fruits/kiwi.js'], + [[], '/fruits/grapefruit.js'], + ]; + + incorrectReturnValues.forEach(([returnValue, filePath]) => { + require('passthrough-preprocessor').process.mockReturnValue( + returnValue, + ); + expect(() => scriptTransformer.transform(filePath, {})).toThrow( + 'must return a string', + ); + }); + + const correctReturnValues = [ + ['code', '/fruits/banana.js'], + [{code: 'code'}, '/fruits/kiwi.js'], + ]; + + correctReturnValues.forEach(([returnValue, filePath]) => { + require('passthrough-preprocessor').process.mockReturnValue( + returnValue, + ); + expect(() => scriptTransformer.transform(filePath, {})).not.toThrow(); + }); + }, + ); + it('uses the supplied preprocessor', () => { config = Object.assign(config, { transform: [['^.+\\.js$', 'test-preprocessor']],