Skip to content

Commit

Permalink
Allow JSON transforms (#8278)
Browse files Browse the repository at this point in the history
* Allow JSON transforms for #2578

* Additional comments

* A better fix, with test

* Fix linting error from CI runs

* Address comment from @scotthovestadt

* Re-implement per @scotthovestadt's guidance

* Update Changelog

* Provide full options to transformJson

* Fix lint error
  • Loading branch information
MLoughry authored and scotthovestadt committed Apr 11, 2019
1 parent 820c2b1 commit 034ab25
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
### Fixes

- `[jest-snapshot]` Inline snapshots: do not indent empty lines ([#8277](https://github.com/facebook/jest/pull/8277))
- `[@jest/runtime, @jest/transform]` Allow custom transforms for JSON dependencies ([#2578](https://github.com/facebook/jest/pull/2578))
- `[jest-core]` Make `detectOpenHandles` imply `runInBand` ([#8283](https://github.com/facebook/jest/pull/8283))
- `[jest-haste-map]` Fix the `mapper` option which was incorrectly ignored ([#8299](https://github.com/facebook/jest/pull/8299))

Expand Down
Expand Up @@ -44,5 +44,29 @@ describe('Runtime', () => {
const exports = runtime.requireInternalModule(modulePath);
expect(exports()).toBe('internal-module-data');
}));

it('loads JSON modules and applies transforms', () =>
createRuntime(__filename, {
transform: {'^.+\\.json$': './test_json_preprocessor'},
}).then(runtime => {
const modulePath = path.resolve(
path.dirname(runtime.__mockRootPath),
'internal-root.json',
);
const exports = runtime.requireModule(modulePath);
expect(exports).toEqual({foo: 'foo'});
}));

it('loads internal JSON modules without applying transforms', () =>
createRuntime(__filename, {
transform: {'^.+\\.json$': './test_json_preprocessor'},
}).then(runtime => {
const modulePath = path.resolve(
path.dirname(runtime.__mockRootPath),
'internal-root.json',
);
const exports = runtime.requireInternalModule(modulePath);
expect(exports).toEqual({foo: 'bar'});
}));
});
});
@@ -0,0 +1,3 @@
{
"foo": "bar"
}
@@ -0,0 +1,14 @@
/**
* 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.
*/

'use strict';

module.exports.process = source => {
const json = JSON.parse(source);
Object.keys(json).forEach(k => (json[k] = k));
return JSON.stringify(json);
};
34 changes: 24 additions & 10 deletions packages/jest-runtime/src/index.ts
Expand Up @@ -25,6 +25,7 @@ import {
ScriptTransformer,
ShouldInstrumentOptions,
shouldInstrument,
TransformationOptions,
} from '@jest/transform';
import fs from 'graceful-fs';
import stripBOM from 'strip-bom';
Expand Down Expand Up @@ -465,8 +466,16 @@ class Runtime {
moduleRegistry: ModuleRegistry,
) {
if (path.extname(modulePath) === '.json') {
const text = stripBOM(fs.readFileSync(modulePath, 'utf8'));

const transformedFile = this._scriptTransformer.transformJson(
modulePath,
this._getFullTransformationOptions(options),
text,
);

localModule.exports = this._environment.global.JSON.parse(
stripBOM(fs.readFileSync(modulePath, 'utf8')),
transformedFile,
);
} else if (path.extname(modulePath) === '.node') {
localModule.exports = require(modulePath);
Expand All @@ -478,6 +487,19 @@ class Runtime {
localModule.loaded = true;
}

private _getFullTransformationOptions(
options: InternalModuleOptions | undefined,
): TransformationOptions {
return {
...options,
changedFiles: this._coverageOptions.changedFiles,
collectCoverage: this._coverageOptions.collectCoverage,
collectCoverageFrom: this._coverageOptions.collectCoverageFrom,
collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom,
extraGlobals: this._config.extraGlobals || [],
};
}

requireModuleOrMock(from: Config.Path, moduleName: string) {
try {
if (this._shouldMock(from, moduleName)) {
Expand Down Expand Up @@ -676,7 +698,6 @@ class Runtime {
return;
}

const isInternalModule = !!(options && options.isInternalModule);
const filename = localModule.filename;
const lastExecutingModulePath = this._currentlyExecutingModulePath;
this._currentlyExecutingModulePath = filename;
Expand All @@ -701,14 +722,7 @@ class Runtime {
const extraGlobals = this._config.extraGlobals || [];
const transformedFile = this._scriptTransformer.transform(
filename,
{
changedFiles: this._coverageOptions.changedFiles,
collectCoverage: this._coverageOptions.collectCoverage,
collectCoverageFrom: this._coverageOptions.collectCoverageFrom,
collectCoverageOnlyFrom: this._coverageOptions.collectCoverageOnlyFrom,
extraGlobals,
isInternalModule,
},
this._getFullTransformationOptions(options),
this._cacheFS[filename],
);

Expand Down
22 changes: 22 additions & 0 deletions packages/jest-transform/src/ScriptTransformer.ts
Expand Up @@ -405,6 +405,28 @@ export default class ScriptTransformer {
return result;
}

transformJson(
filename: Config.Path,
options: Options,
fileSource: string,
): string {
const isInternalModule = options.isInternalModule;
const isCoreModule = options.isCoreModule;
const willTransform =
!isInternalModule && !isCoreModule && this.shouldTransform(filename);

if (willTransform) {
const {code: transformedJsonSource} = this.transformSource(
filename,
fileSource,
false,
);
return transformedJsonSource;
}

return fileSource;
}

/**
* @deprecated use `this.shouldTransform` instead
*/
Expand Down
6 changes: 5 additions & 1 deletion packages/jest-transform/src/index.ts
Expand Up @@ -7,4 +7,8 @@

export {default as ScriptTransformer} from './ScriptTransformer';
export {default as shouldInstrument} from './shouldInstrument';
export {Transformer, ShouldInstrumentOptions} from './types';
export {
Transformer,
ShouldInstrumentOptions,
Options as TransformationOptions,
} from './types';

0 comments on commit 034ab25

Please sign in to comment.