diff --git a/README.md b/README.md index a266a1da..01d45794 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ Here is a list of common options. Run `c8 --help` for the full list and document | `--per-file` | check thresholds per file | `boolean` | `false` | | `--temp-directory` | directory V8 coverage data is written to and read from | `string` | `process.env.NODE_V8_COVERAGE` | | `--clean` | should temp files be deleted before script execution | `boolean` | `true` | +| `--experimental-monocart` | see [section below](#using-monocart-coverage-reports-experimental) for more info | `boolean` | `false` | ## Checking for "full" source coverage using `--all` @@ -119,6 +120,23 @@ The `--100` flag can be set for the `check-coverage` as well: c8 check-coverage --100 ``` +## Using Monocart coverage reports (experimental) +Monocart is an alternate library for outputting [v8 code coverage](https://v8.dev/blog/javascript-code-coverage) data as Istanbul reports. + +Monocart also provides reporters based directly on v8's byte-offset-based output. Such as, `console-details` and `v8`. This removes a complex transformation step and may be less bug prone for some environments. + +**Example usage:** + +```sh +c8 --experimental-monocart --reporter=v8 --reporter=console-details node foo.js +``` + +NOTE: Monocart requires additional `monocart-coverage-reports` to be installed: + +```sh +npm i monocart-coverage-reports --save-dev +``` + ## Ignoring Uncovered Lines, Functions, and Blocks Sometimes you might find yourself wanting to ignore uncovered portions of your diff --git a/lib/commands/report.js b/lib/commands/report.js index 7bdc48c3..ec6e7fcc 100644 --- a/lib/commands/report.js +++ b/lib/commands/report.js @@ -36,7 +36,8 @@ exports.outputReport = async function (argv) { src: argv.src, skipFull: argv.skipFull, excludeNodeModules: argv.excludeNodeModules, - mergeAsync: argv.mergeAsync + mergeAsync: argv.mergeAsync, + monocartArgv: (argv.experimentalMonocart || process.env.EXPERIMENTAL_MONOCART) ? argv : null }) await report.run() if (argv.checkCoverage) await checkCoverages(argv, report) diff --git a/lib/parse-args.js b/lib/parse-args.js index 21a9cd7a..84ff8e3e 100644 --- a/lib/parse-args.js +++ b/lib/parse-args.js @@ -158,6 +158,11 @@ function buildYargs (withCommands = false) { describe: 'supplying --merge-async will merge all v8 coverage reports asynchronously and incrementally. ' + 'This is to avoid OOM issues with Node.js runtime.' }) + .option('experimental-monocart', { + default: false, + type: 'boolean', + describe: 'Use Monocart coverage reports' + }) .pkgConf('c8') .demandCommand(1) .check((argv) => { diff --git a/lib/report.js b/lib/report.js index a69a5595..d7220e03 100644 --- a/lib/report.js +++ b/lib/report.js @@ -36,7 +36,8 @@ class Report { allowExternal = false, skipFull, excludeNodeModules, - mergeAsync + mergeAsync, + monocartArgv }) { this.reporter = reporter this.reporterOptions = reporterOptions || {} @@ -60,6 +61,7 @@ class Report { this.src = this._getSrc(src) this.skipFull = skipFull this.mergeAsync = mergeAsync + this.monocartArgv = monocartArgv } _getSrc (src) { @@ -73,6 +75,9 @@ class Report { } async run () { + if (this.monocartArgv) { + return this.runMonocart() + } const context = libReport.createContext({ dir: this.reportsDirectory, watermarks: this.watermarks, @@ -89,6 +94,141 @@ class Report { } } + async importMonocart () { + return import('monocart-coverage-reports') + } + + async getMonocart () { + let MCR + try { + MCR = await this.importMonocart() + } catch (e) { + console.error('--experimental-monocart requires the plugin monocart-coverage-reports. Run: "npm i monocart-coverage-reports --save-dev"') + process.exit(1) + } + return MCR + } + + async runMonocart () { + const MCR = await this.getMonocart() + if (!MCR) { + return + } + + const argv = this.monocartArgv + const exclude = this.exclude + + function getEntryFilter () { + return argv.entryFilter || argv.filter || function (entry) { + return exclude.shouldInstrument(fileURLToPath(entry.url)) + } + } + + function getSourceFilter () { + return argv.sourceFilter || argv.filter || function (sourcePath) { + if (argv.excludeAfterRemap) { + // console.log(sourcePath) + return exclude.shouldInstrument(sourcePath) + } + return true + } + } + + function getReports () { + const reports = Array.isArray(argv.reporter) ? argv.reporter : [argv.reporter] + const reporterOptions = argv.reporterOptions || {} + + return reports.map((reportName) => { + const reportOptions = { + ...reporterOptions[reportName] + } + if (reportName === 'text') { + reportOptions.skipEmpty = false + reportOptions.skipFull = argv.skipFull + reportOptions.maxCols = process.stdout.columns || 100 + } + return [reportName, reportOptions] + }) + } + + // --all: add empty coverage for all files + function getAllOptions () { + if (!argv.all) { + return + } + + const src = argv.src + const workingDirs = Array.isArray(src) ? src : (typeof src === 'string' ? [src] : [process.cwd()]) + return { + dir: workingDirs, + filter: (filePath) => { + return exclude.shouldInstrument(filePath) + } + } + } + + function initPct (summary) { + Object.keys(summary).forEach(k => { + if (summary[k].pct === '') { + summary[k].pct = 100 + } + }) + return summary + } + + // adapt coverage options + const coverageOptions = { + logging: argv.logging, + name: argv.name, + + reports: getReports(), + + outputDir: argv.reportsDir, + baseDir: argv.baseDir, + + entryFilter: getEntryFilter(), + sourceFilter: getSourceFilter(), + + inline: argv.inline, + lcov: argv.lcov, + + all: getAllOptions(), + + clean: argv.clean, + + // use default value for istanbul + defaultSummarizer: 'pkg', + + onEnd: (coverageResults) => { + // for check coverage + this._allCoverageFiles = { + files: () => { + return coverageResults.files.map(it => it.sourcePath) + }, + fileCoverageFor: (file) => { + const fileCoverage = coverageResults.files.find(it => it.sourcePath === file) + return { + toSummary: () => { + return initPct(fileCoverage.summary) + } + } + }, + getCoverageSummary: () => { + return initPct(coverageResults.summary) + } + } + } + } + const coverageReport = new MCR.CoverageReport(coverageOptions) + coverageReport.cleanCache() + + // read v8 coverage data from tempDirectory + await coverageReport.addFromDir(argv.tempDirectory) + + // generate report + await coverageReport.generate() + } + async getCoverageMapFromAllCoverageFiles () { // the merge process can be very expensive, and it's often the case that // check-coverage is called immediately after a report. We memoize the diff --git a/package-lock.json b/package-lock.json index 066c91c0..3a780a41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,9 @@ }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "monocart-coverage-reports": "^2.8.3" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -770,6 +773,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/console-grid": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/console-grid/-/console-grid-2.2.2.tgz", + "integrity": "sha512-ohlgXexdDTKLNsZz7DSJuCAwmRc8omSS61txOk39W3NOthgKGr1a1jJpZ5BCQe4PlrwMw01OvPQ1Bl3G7Y/uFg==", + "peer": true + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -922,6 +931,12 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/eight-colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eight-colors/-/eight-colors-1.3.0.tgz", + "integrity": "sha512-hVoK898cR71ADj7L1LZWaECLaSkzzPtqGXIaKv4K6Pzb72QgjLVsQaNI+ELDQQshzFvgp5xTPkaYkPGqw3YR+g==", + "peer": true + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2509,9 +2524,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -2815,6 +2830,12 @@ "node": ">=10" } }, + "node_modules/lz-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lz-utils/-/lz-utils-2.0.2.tgz", + "integrity": "sha512-i1PJN4hNEevkrvLMqNWCCac1BcB5SRaghywG7HVzWOyVkFOasLCG19ND1sY1F/ZEsM6SnGtoXyBWnmfqOM5r6g==", + "peer": true + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -2993,6 +3014,52 @@ "node": ">=10" } }, + "node_modules/monocart-code-viewer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/monocart-code-viewer/-/monocart-code-viewer-1.1.3.tgz", + "integrity": "sha512-v1dbT8fDr9vjyjEYE035JSC4JXBA/Z034mogVJWRO3khX0/guVwGb69iSIYSzTbR9+KpRKV/C/AscRAkUwP32w==", + "peer": true + }, + "node_modules/monocart-coverage-reports": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/monocart-coverage-reports/-/monocart-coverage-reports-2.8.3.tgz", + "integrity": "sha512-F6SK6VqKofrnjGtM0Cu9BLgp1ZZPMJhHq8rd8l0vudj3amrVRb+H9UH5X9Xxp4JuGVSODg0XfTDpFOxVjIGjUw==", + "peer": true, + "workspaces": [ + "packages/*", + "test" + ], + "dependencies": { + "console-grid": "^2.2.2", + "eight-colors": "^1.3.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.7", + "lz-utils": "^2.0.2", + "monocart-code-viewer": "^1.1.3", + "monocart-formatter": "^3.0.0", + "monocart-locator": "^1.0.0", + "turbogrid": "^3.0.13" + }, + "bin": { + "mcr": "lib/cli.js" + } + }, + "node_modules/monocart-formatter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/monocart-formatter/-/monocart-formatter-3.0.0.tgz", + "integrity": "sha512-91OQpUb/9iDqvrblUv6ki11Jxi1d3Fp5u2jfVAPl3UdNp9TM+iBleLzXntUS51W0o+zoya3CJjZZ01z2XWn25g==", + "peer": true, + "workspaces": [ + "packages/*" + ] + }, + "node_modules/monocart-locator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/monocart-locator/-/monocart-locator-1.0.0.tgz", + "integrity": "sha512-qIHJ7f99miF2HbVUWAFKR93SfgGYpFPUCQPmW9q1VXU9onxMUFJxhQDdG3HkEteogUbsKB7Gr5MRgjzcIxwTaQ==", + "peer": true + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4435,6 +4502,12 @@ "strip-bom": "^3.0.0" } }, + "node_modules/turbogrid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/turbogrid/-/turbogrid-3.1.0.tgz", + "integrity": "sha512-IpNYGO26pJkd8c0qSOWVHfg8lYuVhbweaWboy7Xvg/KTI3WjhgYzPS6szPMoxXLEGAhykXagaQCRYl9pGapN6g==", + "peer": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5411,6 +5484,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "console-grid": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/console-grid/-/console-grid-2.2.2.tgz", + "integrity": "sha512-ohlgXexdDTKLNsZz7DSJuCAwmRc8omSS61txOk39W3NOthgKGr1a1jJpZ5BCQe4PlrwMw01OvPQ1Bl3G7Y/uFg==", + "peer": true + }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -5521,6 +5600,12 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "eight-colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eight-colors/-/eight-colors-1.3.0.tgz", + "integrity": "sha512-hVoK898cR71ADj7L1LZWaECLaSkzzPtqGXIaKv4K6Pzb72QgjLVsQaNI+ELDQQshzFvgp5xTPkaYkPGqw3YR+g==", + "peer": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -6669,9 +6754,9 @@ } }, "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -6918,6 +7003,12 @@ "yallist": "^4.0.0" } }, + "lz-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lz-utils/-/lz-utils-2.0.2.tgz", + "integrity": "sha512-i1PJN4hNEevkrvLMqNWCCac1BcB5SRaghywG7HVzWOyVkFOasLCG19ND1sY1F/ZEsM6SnGtoXyBWnmfqOM5r6g==", + "peer": true + }, "make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -7048,6 +7139,42 @@ } } }, + "monocart-code-viewer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/monocart-code-viewer/-/monocart-code-viewer-1.1.3.tgz", + "integrity": "sha512-v1dbT8fDr9vjyjEYE035JSC4JXBA/Z034mogVJWRO3khX0/guVwGb69iSIYSzTbR9+KpRKV/C/AscRAkUwP32w==", + "peer": true + }, + "monocart-coverage-reports": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/monocart-coverage-reports/-/monocart-coverage-reports-2.8.3.tgz", + "integrity": "sha512-F6SK6VqKofrnjGtM0Cu9BLgp1ZZPMJhHq8rd8l0vudj3amrVRb+H9UH5X9Xxp4JuGVSODg0XfTDpFOxVjIGjUw==", + "peer": true, + "requires": { + "console-grid": "^2.2.2", + "eight-colors": "^1.3.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.7", + "lz-utils": "^2.0.2", + "monocart-code-viewer": "^1.1.3", + "monocart-formatter": "^3.0.0", + "monocart-locator": "^1.0.0", + "turbogrid": "^3.0.13" + } + }, + "monocart-formatter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/monocart-formatter/-/monocart-formatter-3.0.0.tgz", + "integrity": "sha512-91OQpUb/9iDqvrblUv6ki11Jxi1d3Fp5u2jfVAPl3UdNp9TM+iBleLzXntUS51W0o+zoya3CJjZZ01z2XWn25g==", + "peer": true + }, + "monocart-locator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/monocart-locator/-/monocart-locator-1.0.0.tgz", + "integrity": "sha512-qIHJ7f99miF2HbVUWAFKR93SfgGYpFPUCQPmW9q1VXU9onxMUFJxhQDdG3HkEteogUbsKB7Gr5MRgjzcIxwTaQ==", + "peer": true + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8079,6 +8206,12 @@ "strip-bom": "^3.0.0" } }, + "turbogrid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/turbogrid/-/turbogrid-3.1.0.tgz", + "integrity": "sha512-IpNYGO26pJkd8c0qSOWVHfg8lYuVhbweaWboy7Xvg/KTI3WjhgYzPS6szPMoxXLEGAhykXagaQCRYl9pGapN6g==", + "peer": true + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 730a9365..96b077b0 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,9 @@ "ts-node": "^10.7.0", "typescript": "^5.0.0" }, + "peerDependencies": { + "monocart-coverage-reports": "^2.8.3" + }, "engines": { "node": ">=18" }, diff --git a/test/fixtures/import-mcr.js b/test/fixtures/import-mcr.js new file mode 100644 index 00000000..18969e60 --- /dev/null +++ b/test/fixtures/import-mcr.js @@ -0,0 +1,12 @@ +const importMCR = async () => { + const Report = require('../../lib/report') + const report = Report({ + monocartArgv: {} + }) + report.importMonocart = () => { + throw new Error('not found module') + } + await report.run() +} + +importMCR(); \ No newline at end of file diff --git a/test/integration.js b/test/integration.js index d4aaeb13..8e00be0b 100644 --- a/test/integration.js +++ b/test/integration.js @@ -685,6 +685,7 @@ beforeEach(function () { c8Path, '--all', '--exclude="test/*.js"', + '--exclude="tmp/monocart-*/**/*.js"', '--extension=.js', '--extension=.special', '--temp-directory=tmp/extension', @@ -696,5 +697,134 @@ beforeEach(function () { output.toString('utf8').should.matchSnapshot() }) }) + + describe('monocart report', () => { + it('check import monocart', async () => { + const { output, status } = spawnSync(nodePath, ['./test/fixtures/import-mcr.js']) + status.should.equal(1) + output.toString('utf8').should.matchSnapshot() + }) + + it('monocart check normal', () => { + const { output } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--exclude="test/*.js"', + '--temp-directory=tmp/monocart-normal', + '--reports-dir=tmp/monocart-normal-reports', + '--reporter=v8', + '--reporter=console-details', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/normal') + ]) + output.toString('utf8').should.matchSnapshot() + }) + + it('monocart check all', () => { + const { output } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--temp-directory=tmp/monocart-vanilla-all', + '--reports-dir=tmp/monocart-vanilla-all-reports', + '--reporter=v8', + '--reporter=console-details', + '--all', + '--include=test/fixtures/all/vanilla/**/*.js', + '--exclude=**/*.ts', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/all/vanilla/main') + ]) + output.toString('utf8').should.matchSnapshot() + }) + + it('monocart check coverage', () => { + const { output, status } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--exclude="test/*.js"', + '--temp-directory=tmp/monocart-check-coverage', + '--reports-dir=tmp/monocart-check-coverage-reports', + '--reporter=v8', + '--reporter=console-details', + '--check-coverage', + '--statements=80', + '--branches=80', + '--lines=80', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/normal') + ]) + status.should.equal(1) + output.toString('utf8').should.matchSnapshot() + }) + + it('monocart check coverage pre file', () => { + const { output, status } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--exclude="test/*.js"', + '--temp-directory=tmp/monocart-check-per-file', + '--reports-dir=tmp/monocart-check-per-file-reports', + '--reporter=v8', + '--reporter=console-details', + '--check-coverage', + '--statements=80', + '--branches=80', + '--lines=80', + '--per-file', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/normal') + ]) + status.should.equal(1) + output.toString('utf8').should.matchSnapshot() + }) + + it('monocart check all and 100', () => { + const { output, status } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--temp-directory=tmp/monocart-all-100', + '--reports-dir=tmp/monocart-all-100-reports', + '--reporter=v8', + '--reporter=console-details', + '--all', + '--100', + '--per-file', + '--include=test/fixtures/all/vanilla/**/*.js', + '--exclude=**/*.ts', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/all/vanilla/main') + ]) + status.should.equal(1) + output.toString('utf8').should.matchSnapshot() + }) + + it('check sourcemap', () => { + const { output } = spawnSync(nodePath, [ + c8Path, + '--experimental-monocart', + '--exclude="test/*.js"', + '--temp-directory=tmp/monocart-source-map', + '--reports-dir=tmp/monocart-source-map-reports', + '--reporter=v8', + '--reporter=text', + '--exclude-after-remap', + '--clean=false', + `--merge-async=${mergeAsync}`, + nodePath, + require.resolve('./fixtures/source-maps/branches/branches.typescript.js') + ]) + output.toString('utf8').should.matchSnapshot() + }) + }) }) }) diff --git a/test/integration.js.snap b/test/integration.js.snap index a9279c7e..0c2c37ea 100644 --- a/test/integration.js.snap +++ b/test/integration.js.snap @@ -156,7 +156,7 @@ hey ---------------------------------------|---------|----------|---------|---------|------------------------ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ---------------------------------------|---------|----------|---------|---------|------------------------ -All files | 3.52 | 12.5 | 6.52 | 3.52 | +All files | 3.21 | 12.24 | 6.38 | 3.21 | c8 | 0 | 0 | 0 | 0 | index.js | 0 | 0 | 0 | 0 | 1 c8/bin | 0 | 0 | 0 | 0 | @@ -166,19 +166,20 @@ All files | 3.52 | 12.5 | 6.52 | 3.52 prettify.js | 0 | 0 | 0 | 0 | 1-2 sorter.js | 0 | 0 | 0 | 0 | 1-196 c8/lib | 0 | 0 | 0 | 0 | - parse-args.js | 0 | 0 | 0 | 0 | 1-224 - report.js | 0 | 0 | 0 | 0 | 1-402 + parse-args.js | 0 | 0 | 0 | 0 | 1-229 + report.js | 0 | 0 | 0 | 0 | 1-542 source-map-from-file.js | 0 | 0 | 0 | 0 | 1-100 c8/lib/commands | 0 | 0 | 0 | 0 | check-coverage.js | 0 | 0 | 0 | 0 | 1-70 - report.js | 0 | 0 | 0 | 0 | 1-43 - c8/test/fixtures | 30.97 | 37.5 | 21.42 | 30.97 | + report.js | 0 | 0 | 0 | 0 | 1-44 + c8/test/fixtures | 29.08 | 35.29 | 20 | 29.08 | async.js | 100 | 100 | 100 | 100 | c8-ignore-next.js | 54.54 | 0 | 0 | 54.54 | 1,3-4,9,12,17-19,21-22 c8-ignore-start-stop.js | 61.9 | 0 | 0 | 61.9 | 1-4,10,16-18 computed-method.js | 0 | 0 | 0 | 0 | 1-15 custom-ext.special | 75 | 66.66 | 33.33 | 75 | 14-16,18-20 custom-ext2.special | 0 | 0 | 0 | 0 | 1-24 + import-mcr.js | 0 | 0 | 0 | 0 | 1-12 issue-254.js | 28.57 | 0 | 0 | 28.57 | 1-2,5-7 multiple-spawn.js | 0 | 0 | 0 | 0 | 1-12 normal.js | 0 | 0 | 0 | 0 | 1-24 @@ -521,7 +522,7 @@ hey ---------------------------------------|---------|----------|---------|---------|------------------------ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ---------------------------------------|---------|----------|---------|---------|------------------------ -All files | 3.52 | 12.5 | 6.52 | 3.52 | +All files | 3.21 | 12.24 | 6.38 | 3.21 | c8 | 0 | 0 | 0 | 0 | index.js | 0 | 0 | 0 | 0 | 1 c8/bin | 0 | 0 | 0 | 0 | @@ -531,19 +532,20 @@ All files | 3.52 | 12.5 | 6.52 | 3.52 prettify.js | 0 | 0 | 0 | 0 | 1-2 sorter.js | 0 | 0 | 0 | 0 | 1-196 c8/lib | 0 | 0 | 0 | 0 | - parse-args.js | 0 | 0 | 0 | 0 | 1-224 - report.js | 0 | 0 | 0 | 0 | 1-402 + parse-args.js | 0 | 0 | 0 | 0 | 1-229 + report.js | 0 | 0 | 0 | 0 | 1-542 source-map-from-file.js | 0 | 0 | 0 | 0 | 1-100 c8/lib/commands | 0 | 0 | 0 | 0 | check-coverage.js | 0 | 0 | 0 | 0 | 1-70 - report.js | 0 | 0 | 0 | 0 | 1-43 - c8/test/fixtures | 30.97 | 37.5 | 21.42 | 30.97 | + report.js | 0 | 0 | 0 | 0 | 1-44 + c8/test/fixtures | 29.08 | 35.29 | 20 | 29.08 | async.js | 100 | 100 | 100 | 100 | c8-ignore-next.js | 54.54 | 0 | 0 | 54.54 | 1,3-4,9,12,17-19,21-22 c8-ignore-start-stop.js | 61.9 | 0 | 0 | 61.9 | 1-4,10,16-18 computed-method.js | 0 | 0 | 0 | 0 | 1-15 custom-ext.special | 75 | 66.66 | 33.33 | 75 | 14-16,18-20 custom-ext2.special | 0 | 0 | 0 | 0 | 1-24 + import-mcr.js | 0 | 0 | 0 | 0 | 1-12 issue-254.js | 28.57 | 0 | 0 | 28.57 | 1-2,5-7 multiple-spawn.js | 0 | 0 | 0 | 0 | 1-12 normal.js | 0 | 0 | 0 | 0 | 1-24 @@ -745,6 +747,132 @@ All files | 100 | 100 | 100 | 100 | ," `; +exports[`c8 mergeAsync monocart report check import monocart 1`] = ` +",,--experimental-monocart requires the plugin monocart-coverage-reports. Run: \\"npm i monocart-coverage-reports --save-dev\\" +" +`; + +exports[`c8 mergeAsync monocart report check sourcemap 1`] = ` +",reachable +a = true +a = false +------------------------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +------------------------|---------|----------|---------|---------|------------------- +All files | 82.35 | 70 | 100 | 81.25 | + branches.typescript.ts | 82.35 | 70 | 100 | 81.25 | 7,11,18 +------------------------|---------|----------|---------|---------|------------------- +," +`; + +exports[`c8 mergeAsync monocart report monocart check all 1`] = ` +",zero +positive +negative +┌───────────────────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures/all/vanilla │ │ │ │ │ │ │ +│ ├ dir │ │ │ │ │ │ │ +│ │ └ unloaded.js │ 0.00 % │ 0.00 % │ │ 0.00 % │ 0.00 % │ 1-5 │ +│ ├ main.js │ 100.00 % │ 100.00 % │ │ │ 100.00 % │ │ +│ └ loaded.js │ 80.41 % │ 80.00 % │ 75.00 % │ 100.00 % │ 68.42 % │ 3-5,16-18 │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 65.64 % │ 70.59 % │ 75.00 % │ 50.00 % │ 62.96 % │ │ +└───────────────────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +," +`; + +exports[`c8 mergeAsync monocart report monocart check all and 100 1`] = ` +",zero +positive +negative +┌───────────────────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures/all/vanilla │ │ │ │ │ │ │ +│ ├ dir │ │ │ │ │ │ │ +│ │ └ unloaded.js │ 0.00 % │ 0.00 % │ │ 0.00 % │ 0.00 % │ 1-5 │ +│ ├ main.js │ 100.00 % │ 100.00 % │ │ │ 100.00 % │ │ +│ └ loaded.js │ 80.41 % │ 80.00 % │ 75.00 % │ 100.00 % │ 68.42 % │ 3-5,16-18 │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 65.64 % │ 70.59 % │ 75.00 % │ 50.00 % │ 62.96 % │ │ +└───────────────────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for lines (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for functions (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for statements (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for lines (68.42%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +ERROR: Coverage for branches (75%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +ERROR: Coverage for statements (80%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +" +`; + +exports[`c8 mergeAsync monocart report monocart check coverage 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for branches (62.5%) does not meet global threshold (80%) +" +`; + +exports[`c8 mergeAsync monocart report monocart check coverage pre file 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for lines (70.59%) does not meet threshold (80%) for test/fixtures/normal.js +ERROR: Coverage for branches (62.5%) does not meet threshold (80%) for test/fixtures/normal.js +" +`; + +exports[`c8 mergeAsync monocart report monocart check normal 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +," +`; + exports[`c8 mergeAsync report generates report from existing temporary files 1`] = ` ",-----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s @@ -1017,6 +1145,132 @@ All files | 100 | 100 | 100 | 100 | ," `; +exports[`c8 monocart report check import monocart 1`] = ` +",,--experimental-monocart requires the plugin monocart-coverage-reports. Run: \\"npm i monocart-coverage-reports --save-dev\\" +" +`; + +exports[`c8 monocart report check sourcemap 1`] = ` +",reachable +a = true +a = false +------------------------|---------|----------|---------|---------|------------------- +File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s +------------------------|---------|----------|---------|---------|------------------- +All files | 82.35 | 70 | 100 | 81.25 | + branches.typescript.ts | 82.35 | 70 | 100 | 81.25 | 7,11,18 +------------------------|---------|----------|---------|---------|------------------- +," +`; + +exports[`c8 monocart report monocart check all 1`] = ` +",zero +positive +negative +┌───────────────────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures/all/vanilla │ │ │ │ │ │ │ +│ ├ dir │ │ │ │ │ │ │ +│ │ └ unloaded.js │ 0.00 % │ 0.00 % │ │ 0.00 % │ 0.00 % │ 1-5 │ +│ ├ main.js │ 100.00 % │ 100.00 % │ │ │ 100.00 % │ │ +│ └ loaded.js │ 80.41 % │ 80.00 % │ 75.00 % │ 100.00 % │ 68.42 % │ 3-5,16-18 │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 65.64 % │ 70.59 % │ 75.00 % │ 50.00 % │ 62.96 % │ │ +└───────────────────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +," +`; + +exports[`c8 monocart report monocart check all and 100 1`] = ` +",zero +positive +negative +┌───────────────────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures/all/vanilla │ │ │ │ │ │ │ +│ ├ dir │ │ │ │ │ │ │ +│ │ └ unloaded.js │ 0.00 % │ 0.00 % │ │ 0.00 % │ 0.00 % │ 1-5 │ +│ ├ main.js │ 100.00 % │ 100.00 % │ │ │ 100.00 % │ │ +│ └ loaded.js │ 80.41 % │ 80.00 % │ 75.00 % │ 100.00 % │ 68.42 % │ 3-5,16-18 │ +├───────────────────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 65.64 % │ 70.59 % │ 75.00 % │ 50.00 % │ 62.96 % │ │ +└───────────────────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for lines (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for functions (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for statements (0%) does not meet threshold (100%) for test/fixtures/all/vanilla/dir/unloaded.js +ERROR: Coverage for lines (68.42%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +ERROR: Coverage for branches (75%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +ERROR: Coverage for statements (80%) does not meet threshold (100%) for test/fixtures/all/vanilla/loaded.js +" +`; + +exports[`c8 monocart report monocart check coverage 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for branches (62.5%) does not meet global threshold (80%) +" +`; + +exports[`c8 monocart report monocart check coverage pre file 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +,ERROR: Coverage for lines (70.59%) does not meet threshold (80%) for test/fixtures/normal.js +ERROR: Coverage for branches (62.5%) does not meet threshold (80%) for test/fixtures/normal.js +" +`; + +exports[`c8 monocart report monocart check normal 1`] = ` +",hey +i am a line of code +what +hey +what +hey +what +hey +┌───────────────┬──────────┬────────────┬──────────┬───────────┬──────────┬─────────────────┐ +│ Name │ Bytes │ Statements │ Branches │ Functions │ Lines │ Uncovered Lines │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ test/fixtures │ │ │ │ │ │ │ +│ ├ normal.js │ 77.99 % │ 83.33 % │ 62.50 % │ 33.33 % │ 70.59 % │ 9,14-20 │ +│ └ async.js │ 100.00 % │ 100.00 % │ │ 100.00 % │ 100.00 % │ │ +├───────────────┼──────────┼────────────┼──────────┼───────────┼──────────┼─────────────────┤ +│ Summary │ 84.60 % │ 88.89 % │ 62.50 % │ 66.67 % │ 80.77 % │ │ +└───────────────┴──────────┴────────────┴──────────┴───────────┴──────────┴─────────────────┘ +," +`; + exports[`c8 report generates report from existing temporary files 1`] = ` ",-----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s