From 71c9abe8d8320e0ccbff5a1d982588d8e320f105 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Tue, 28 Feb 2023 10:42:19 +0800 Subject: [PATCH 1/7] fix: collect coverage from vm script --- .../coverageProviderV8.test.ts.snap | 9 ++++ e2e/__tests__/coverageProviderV8.test.ts | 12 ++++++ .../__tests__/extract-coverage.test.js | 42 +++++++++++++++++++ e2e/vmscript-coverage/package.json | 6 +++ e2e/vmscript-coverage/package/vmscript.js | 27 ++++++++++++ packages/jest-runtime/src/index.ts | 1 - 6 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 e2e/vmscript-coverage/__tests__/extract-coverage.test.js create mode 100644 e2e/vmscript-coverage/package.json create mode 100644 e2e/vmscript-coverage/package/vmscript.js diff --git a/e2e/__tests__/__snapshots__/coverageProviderV8.test.ts.snap b/e2e/__tests__/__snapshots__/coverageProviderV8.test.ts.snap index f24e97dce582..102d755384bb 100644 --- a/e2e/__tests__/__snapshots__/coverageProviderV8.test.ts.snap +++ b/e2e/__tests__/__snapshots__/coverageProviderV8.test.ts.snap @@ -105,3 +105,12 @@ All files | 59.37 | 33.33 | 33.33 | 59.37 | uncovered.js | 0 | 0 | 0 | 0 | 1-8 --------------|---------|----------|---------|---------|-------------------" `; + +exports[`vm script coverage generator 1`] = ` +"-------------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +-------------|---------|----------|---------|---------|------------------- +All files | 88.88 | 100 | 66.66 | 88.88 | + vmscript.js | 88.88 | 100 | 66.66 | 88.88 | 20-22 +-------------|---------|----------|---------|---------|-------------------" +`; diff --git a/e2e/__tests__/coverageProviderV8.test.ts b/e2e/__tests__/coverageProviderV8.test.ts index b282b5182f9e..2928bf91c6a4 100644 --- a/e2e/__tests__/coverageProviderV8.test.ts +++ b/e2e/__tests__/coverageProviderV8.test.ts @@ -106,3 +106,15 @@ test('prints correct coverage report, if a TS module is transpiled by custom tra expect(exitCode).toBe(0); expect(stdout).toMatchSnapshot(); }); + +test('vm script coverage generator', () => { + const dir = path.resolve(__dirname, '../vmscript-coverage'); + const {stdout, exitCode} = runJest( + dir, + ['--coverage', '--coverage-provider', 'v8'], + {stripAnsi: true}, + ); + + expect(exitCode).toBe(0); + expect(stdout).toMatchSnapshot(); +}); diff --git a/e2e/vmscript-coverage/__tests__/extract-coverage.test.js b/e2e/vmscript-coverage/__tests__/extract-coverage.test.js new file mode 100644 index 000000000000..741562b2b16c --- /dev/null +++ b/e2e/vmscript-coverage/__tests__/extract-coverage.test.js @@ -0,0 +1,42 @@ +/** + * 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 fs = require('fs'); +const path = require('path'); +const vm = require('vm'); +const filePath = path.resolve(__dirname, '../package/vmscript.js'); + +test('extract coverage', () => { + const content = fs.readFileSync(filePath, {encoding: 'utf8'}); + + const case1 = vm.runInNewContext( + content, + { + inputObject: { + number: 0, + }, + }, + { + filename: filePath, + }, + ); + + const case2 = vm.runInNewContext( + content, + { + inputObject: { + number: 7, + }, + }, + { + filename: filePath, + }, + ); + + expect(case1).toBe(false); + expect(case2).toBe(true); +}); diff --git a/e2e/vmscript-coverage/package.json b/e2e/vmscript-coverage/package.json new file mode 100644 index 000000000000..149899d8ce60 --- /dev/null +++ b/e2e/vmscript-coverage/package.json @@ -0,0 +1,6 @@ +{ + "jest": { + "rootDir": "./", + "testEnvironment": "node" + } +} \ No newline at end of file diff --git a/e2e/vmscript-coverage/package/vmscript.js b/e2e/vmscript-coverage/package/vmscript.js new file mode 100644 index 000000000000..d5bb0a02a65e --- /dev/null +++ b/e2e/vmscript-coverage/package/vmscript.js @@ -0,0 +1,27 @@ +/** + * 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. + */ + +function addOne(inputNumber) { + return ++inputNumber; +} + +function isEven(inputNumber) { + if (inputNumber % 2 === 0) { + return true; + } else { + return false; + } +} + +function notCovered() { + return 'not covered'; +} + +/* global inputObject */ +if (inputObject.number / 1 === inputObject.number) { + isEven(addOne(inputObject.number)); +} diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index b638e2927577..55c6933e996a 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -1267,7 +1267,6 @@ export default class Runtime { res => // TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways res.url.startsWith(this._config.rootDir) && - this._v8CoverageSources!.has(res.url) && shouldInstrument(res.url, this._coverageOptions, this._config), ) .map(result => { From e5c0cfa66573c6bfcae3ffbd1fda401472d03009 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Tue, 28 Feb 2023 17:52:32 +0800 Subject: [PATCH 2/7] style: format vmscript-coverage/package.json with prettier --- e2e/vmscript-coverage/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/vmscript-coverage/package.json b/e2e/vmscript-coverage/package.json index 149899d8ce60..c3ca3ea1d928 100644 --- a/e2e/vmscript-coverage/package.json +++ b/e2e/vmscript-coverage/package.json @@ -3,4 +3,4 @@ "rootDir": "./", "testEnvironment": "node" } -} \ No newline at end of file +} From 9ac74c5be2e4ea922611cd34ee16326d5fc09607 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Wed, 1 Mar 2023 10:11:10 +0800 Subject: [PATCH 3/7] chore: update comment Facebook -> Meta --- e2e/vmscript-coverage/__tests__/extract-coverage.test.js | 2 +- e2e/vmscript-coverage/package/vmscript.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/vmscript-coverage/__tests__/extract-coverage.test.js b/e2e/vmscript-coverage/__tests__/extract-coverage.test.js index 741562b2b16c..29fad304fa07 100644 --- a/e2e/vmscript-coverage/__tests__/extract-coverage.test.js +++ b/e2e/vmscript-coverage/__tests__/extract-coverage.test.js @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/e2e/vmscript-coverage/package/vmscript.js b/e2e/vmscript-coverage/package/vmscript.js index d5bb0a02a65e..57b3370ff98d 100644 --- a/e2e/vmscript-coverage/package/vmscript.js +++ b/e2e/vmscript-coverage/package/vmscript.js @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. From 92025488385a01e3eecc0671c3d1e7e3ec40d6e7 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Wed, 1 Mar 2023 12:03:08 +0800 Subject: [PATCH 4/7] fix: fix coverage --- e2e/vmscript-coverage/package.json | 5 ++++- packages/jest-runtime/src/index.ts | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/e2e/vmscript-coverage/package.json b/e2e/vmscript-coverage/package.json index c3ca3ea1d928..4a3ea998ce9d 100644 --- a/e2e/vmscript-coverage/package.json +++ b/e2e/vmscript-coverage/package.json @@ -1,6 +1,9 @@ { "jest": { "rootDir": "./", - "testEnvironment": "node" + "testEnvironment": "node", + "collectCoverageFrom": [ + "package/**/*.js" + ] } } diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 55c6933e996a..115bafea20b0 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -53,7 +53,12 @@ import type {MockMetadata, ModuleMocker} from 'jest-mock'; import {escapePathForRegex} from 'jest-regex-util'; import Resolver, {ResolveModuleConfig} from 'jest-resolve'; import {EXTENSION as SnapshotExtension} from 'jest-snapshot'; -import {createDirectory, deepCyclicCopy} from 'jest-util'; +import { + createDirectory, + deepCyclicCopy, + globsToMatcher, + replacePathSepForGlob, +} from 'jest-util'; import { createOutsideJestVmPath, decodePossibleOutsideJestVmPath, @@ -1260,6 +1265,18 @@ export default class Runtime { throw new Error('You need to call `stopCollectingV8Coverage` first.'); } + const coverageMatcher = this._coverageOptions.collectCoverageFrom.length + ? globsToMatcher(this._coverageOptions.collectCoverageFrom) + : undefined; + const matchesCoveragePattern = (file: string) => { + if (coverageMatcher) { + return coverageMatcher( + replacePathSepForGlob(path.relative(this._config.rootDir, file)), + ); + } + return this._v8CoverageSources!.has(file); + }; + return this._v8CoverageResult .filter(res => res.url.startsWith('file://')) .map(res => ({...res, url: fileURLToPath(res.url)})) @@ -1267,6 +1284,7 @@ export default class Runtime { res => // TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways res.url.startsWith(this._config.rootDir) && + matchesCoveragePattern(res.url) && shouldInstrument(res.url, this._coverageOptions, this._config), ) .map(result => { From cb0f4d18f32d303e8ad39b38005d419fa4cdb846 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Wed, 1 Mar 2023 14:13:30 +0800 Subject: [PATCH 5/7] chore: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f5bbe26c2b..27f1d15bde7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - `[jest-circus]` Update message printed on test timeout ([#13830](https://github.com/facebook/jest/pull/13830)) - `[jest-circus]` Avoid creating the word "testfalse" when `takesDoneCallback` is `false` in the message printed on test timeout AND updated timeouts test ([#13954](https://github.com/facebook/jest/pull/13954)) - `[@jest/test-result]` Allow `TestResultsProcessor` type to return a Promise ([#13950](https://github.com/facebook/jest/pull/13950)) +- `[jest-runtime]` Support coverage with v8 for scripts loaded with `vm.runInContext`. Note: `collectCoverageFrom` must be set for it to work ([#](https://github.com/facebook/jest/pull/13962)) ### Chore & Maintenance From a338b201ce042d7e04998026da704e0a96899b71 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Wed, 1 Mar 2023 21:39:00 +0800 Subject: [PATCH 6/7] refactor: only rely on shouldInstrument --- .../no-sourcemap/package.json | 5 ++++- packages/jest-runtime/src/index.ts | 20 +------------------ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/e2e/coverage-provider-v8/no-sourcemap/package.json b/e2e/coverage-provider-v8/no-sourcemap/package.json index e63e40a94614..f247a2268da8 100644 --- a/e2e/coverage-provider-v8/no-sourcemap/package.json +++ b/e2e/coverage-provider-v8/no-sourcemap/package.json @@ -6,6 +6,9 @@ "transform": { "\\.[jt]sx?$": "babel-jest", "\\.css$": "/cssTransform.js" - } + }, + "coveragePathIgnorePatterns": [ + "cssTransform\\.js" + ] } } diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index 115bafea20b0..55c6933e996a 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -53,12 +53,7 @@ import type {MockMetadata, ModuleMocker} from 'jest-mock'; import {escapePathForRegex} from 'jest-regex-util'; import Resolver, {ResolveModuleConfig} from 'jest-resolve'; import {EXTENSION as SnapshotExtension} from 'jest-snapshot'; -import { - createDirectory, - deepCyclicCopy, - globsToMatcher, - replacePathSepForGlob, -} from 'jest-util'; +import {createDirectory, deepCyclicCopy} from 'jest-util'; import { createOutsideJestVmPath, decodePossibleOutsideJestVmPath, @@ -1265,18 +1260,6 @@ export default class Runtime { throw new Error('You need to call `stopCollectingV8Coverage` first.'); } - const coverageMatcher = this._coverageOptions.collectCoverageFrom.length - ? globsToMatcher(this._coverageOptions.collectCoverageFrom) - : undefined; - const matchesCoveragePattern = (file: string) => { - if (coverageMatcher) { - return coverageMatcher( - replacePathSepForGlob(path.relative(this._config.rootDir, file)), - ); - } - return this._v8CoverageSources!.has(file); - }; - return this._v8CoverageResult .filter(res => res.url.startsWith('file://')) .map(res => ({...res, url: fileURLToPath(res.url)})) @@ -1284,7 +1267,6 @@ export default class Runtime { res => // TODO: will this work on windows? It might be better if `shouldInstrument` deals with it anyways res.url.startsWith(this._config.rootDir) && - matchesCoveragePattern(res.url) && shouldInstrument(res.url, this._coverageOptions, this._config), ) .map(result => { From 9fcfe2f0bbea41079e4151f1298845869083d0e4 Mon Sep 17 00:00:00 2001 From: GP4cK Date: Wed, 1 Mar 2023 21:44:33 +0800 Subject: [PATCH 7/7] chore: update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27f1d15bde7d..f6337283a5b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ - `[jest-circus]` Update message printed on test timeout ([#13830](https://github.com/facebook/jest/pull/13830)) - `[jest-circus]` Avoid creating the word "testfalse" when `takesDoneCallback` is `false` in the message printed on test timeout AND updated timeouts test ([#13954](https://github.com/facebook/jest/pull/13954)) - `[@jest/test-result]` Allow `TestResultsProcessor` type to return a Promise ([#13950](https://github.com/facebook/jest/pull/13950)) -- `[jest-runtime]` Support coverage with v8 for scripts loaded with `vm.runInContext`. Note: `collectCoverageFrom` must be set for it to work ([#](https://github.com/facebook/jest/pull/13962)) +- `[jest-runtime]` Support coverage with v8 for scripts loaded with `vm.runInContext` ([#13962](https://github.com/facebook/jest/pull/13962)) ### Chore & Maintenance