diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ce5d755682a..dae229790967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ - `[jest-snapshot]` Downgrade semver to v6 to support node 8 ([#9451](https://github.com/facebook/jest/pull/9451)) - `[jest-snapshot]` Properly indent new snapshots in the presences of existing ones ([#9523](https://github.com/facebook/jest/pull/9523)) - `[jest-transform]` Correct sourcemap behavior for transformed and instrumented code ([#9460](https://github.com/facebook/jest/pull/9460)) +- `[jest-transform]` Allow instrumentation of transformed files with weird file extensions ([#9589](https://github.com/facebook/jest/pull/9589)) - `[pretty-format]` Export `OldPlugin` type ([#9491](https://github.com/facebook/jest/pull/9491)) ### Chore & Maintenance diff --git a/e2e/__tests__/__snapshots__/coverageHandlebars.test.ts.snap b/e2e/__tests__/__snapshots__/coverageHandlebars.test.ts.snap new file mode 100644 index 000000000000..3510fb666914 --- /dev/null +++ b/e2e/__tests__/__snapshots__/coverageHandlebars.test.ts.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`code coverage for Handlebars 1`] = ` +"-----------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +-----------|---------|----------|---------|---------|------------------- +All files | 75 | 66.67 | 66.67 | 66.67 | + greet.hbs | 75 | 66.67 | 66.67 | 66.67 | 10 +-----------|---------|----------|---------|---------|-------------------" +`; diff --git a/e2e/__tests__/coverageHandlebars.test.ts b/e2e/__tests__/coverageHandlebars.test.ts new file mode 100644 index 000000000000..6a10e642ad5e --- /dev/null +++ b/e2e/__tests__/coverageHandlebars.test.ts @@ -0,0 +1,33 @@ +/** + * 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 {readFileSync} from 'fs'; +import * as path from 'path'; +import {cleanup, run} from '../Utils'; +import runJest from '../runJest'; + +const dir = path.resolve(__dirname, '../coverage-handlebars'); +const coverageDir = path.join(dir, 'coverage'); + +beforeAll(() => { + cleanup(coverageDir); +}); + +it('code coverage for Handlebars', () => { + run('yarn', dir); + const result = runJest(dir, ['--coverage', '--no-cache']); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toMatchSnapshot(); + + const coverageMapFile = path.join(coverageDir, 'coverage-final.json'); + const coverageMap = JSON.parse(readFileSync(coverageMapFile, 'utf-8')); + + expect( + Object.keys(coverageMap).map(filename => path.basename(filename)), + ).toEqual(['greet.hbs']); +}); diff --git a/e2e/coverage-handlebars/__tests__/greet.js b/e2e/coverage-handlebars/__tests__/greet.js new file mode 100644 index 000000000000..f5775645112e --- /dev/null +++ b/e2e/coverage-handlebars/__tests__/greet.js @@ -0,0 +1,13 @@ +/* + * 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. + */ +const greet = require('../greet.hbs'); + +test('am', () => { + expect(greet({am: true, name: 'Joe'})).toEqual( + '

Good\n morning\nJoe!

\n' + ); +}); diff --git a/e2e/coverage-handlebars/greet.hbs b/e2e/coverage-handlebars/greet.hbs new file mode 100644 index 000000000000..9dd3847305ae --- /dev/null +++ b/e2e/coverage-handlebars/greet.hbs @@ -0,0 +1,13 @@ +{{! + * 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. +}} +

Good +{{#if am}} + morning +{{else}} + evening +{{/if}} +{{name}}!

diff --git a/e2e/coverage-handlebars/package.json b/e2e/coverage-handlebars/package.json new file mode 100644 index 000000000000..3eb23f01b754 --- /dev/null +++ b/e2e/coverage-handlebars/package.json @@ -0,0 +1,12 @@ +{ + "jest": { + "transform": { + "\\.hbs$": "/transform-handlebars.js" + }, + "testEnvironment": "node" + }, + "dependencies": { + "handlebars": "^4.7.3", + "source-map": "^0.6.1" + } +} diff --git a/e2e/coverage-handlebars/transform-handlebars.js b/e2e/coverage-handlebars/transform-handlebars.js new file mode 100644 index 000000000000..a20adf41393d --- /dev/null +++ b/e2e/coverage-handlebars/transform-handlebars.js @@ -0,0 +1,20 @@ +/* + * 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. + */ + +const Handlebars = require('handlebars/dist/cjs/handlebars.js'); +const {SourceMapConsumer, SourceNode} = require('source-map'); + +exports.process = (code, filename) => { + const pc = Handlebars.precompile(code, {srcName: filename}); + const out = new SourceNode(null, null, null, [ + 'const Handlebars = require("handlebars/dist/cjs/handlebars.runtime.js");\n', + 'module.exports = Handlebars.template(', + SourceNode.fromStringWithSourceMap(pc.code, new SourceMapConsumer(pc.map)), + ');\n', + ]).toStringWithSourceMap(); + return {code: out.code, map: out.map.toString()}; +}; diff --git a/e2e/coverage-handlebars/yarn.lock b/e2e/coverage-handlebars/yarn.lock new file mode 100644 index 000000000000..71a0f6e78e8b --- /dev/null +++ b/e2e/coverage-handlebars/yarn.lock @@ -0,0 +1,55 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +handlebars@^4.7.3: + version "4.7.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.3.tgz#8ece2797826886cf8082d1726ff21d2a022550ee" + integrity sha512-SRGwSYuNfx8DwHD/6InAPzD6RgeruWLT+B8e8a7gGs8FWgHzlExpTFMEq2IA6QpAfOClpKHy6+8IqTjeBCu6Kg== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +neo-async@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +uglify-js@^3.1.4: + version "3.8.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.8.0.tgz#f3541ae97b2f048d7e7e3aa4f39fd8a1f5d7a805" + integrity sha512-ugNSTT8ierCsDHso2jkBHXYrU8Y5/fY2ZUprfrJUiD7YpuFvV4jODLFmb3h4btQjqr5Nh4TX4XtgDfCU1WdioQ== + dependencies: + commander "~2.20.3" + source-map "~0.6.1" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index 8d6a06637be7..18b3b46a07f0 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -213,6 +213,7 @@ export default class ScriptTransformer { // files outside `cwd` will not be instrumented cwd: this._config.rootDir, exclude: [], + extension: false, // Needed for correct coverage as soon as we start storing a source map of the instrumented code inputSourceMap: input.map, useInlineSourceMaps: false,