diff --git a/packages/coverage-c8/package.json b/packages/coverage-c8/package.json index 959acf235654..120f0894c256 100644 --- a/packages/coverage-c8/package.json +++ b/packages/coverage-c8/package.json @@ -45,7 +45,9 @@ "vitest": ">=0.30.0 <1" }, "dependencies": { + "@ampproject/remapping": "^2.2.0", "c8": "^7.13.0", + "magic-string": "^0.30.0", "picocolors": "^1.0.0", "std-env": "^3.3.2" }, diff --git a/packages/coverage-c8/src/provider.ts b/packages/coverage-c8/src/provider.ts index d37e44661087..bc9019f5dafd 100644 --- a/packages/coverage-c8/src/provider.ts +++ b/packages/coverage-c8/src/provider.ts @@ -1,6 +1,8 @@ import { existsSync, promises as fs } from 'node:fs' import _url from 'node:url' import type { Profiler } from 'node:inspector' +import MagicString from 'magic-string' +import remapping from '@ampproject/remapping' import { extname, resolve } from 'pathe' import c from 'picocolors' import { provider } from 'std-env' @@ -18,6 +20,9 @@ import { checkCoverages } from 'c8/lib/commands/check-coverage.js' type Options = ResolvedCoverageOptions<'c8'> +// Note that this needs to match the line ending as well +const VITE_EXPORTS_LINE_PATTERN = /Object\.defineProperty\(__vite_ssr_exports__.*\n/g + export class C8CoverageProvider extends BaseCoverageProvider implements CoverageProvider { name = 'c8' @@ -169,7 +174,7 @@ export class C8CoverageProvider extends BaseCoverageProvider implements Coverage return { sourceMap: { - sourcemap: data.map, + sourcemap: removeViteHelpersFromSourceMaps(data.source, data.map), }, source: Array(offset).fill('.').join('') + data.source, } @@ -193,3 +198,27 @@ export class C8CoverageProvider extends BaseCoverageProvider implements Coverage } } } + +/** + * Remove generated code from the source maps: + * - Vite's export helpers: e.g. `Object.defineProperty(__vite_ssr_exports__, "sum", { enumerable: true, configurable: true, get(){ return sum }});` + */ +function removeViteHelpersFromSourceMaps(source: string | undefined, map: EncodedSourceMap) { + if (!source || !source.match(VITE_EXPORTS_LINE_PATTERN)) + return map + + const sourceWithoutHelpers = new MagicString(source) + sourceWithoutHelpers.replaceAll(VITE_EXPORTS_LINE_PATTERN, '\n') + + const mapWithoutHelpers = sourceWithoutHelpers.generateMap({ + hires: true, + }) + + // A merged source map where the first one excludes helpers + const combinedMap = remapping( + [{ ...mapWithoutHelpers, version: 3 }, map], + () => null, + ) + + return combinedMap +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e0dc780f457..dccbf739883b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -873,9 +873,15 @@ importers: packages/coverage-c8: dependencies: + '@ampproject/remapping': + specifier: ^2.2.0 + version: 2.2.0 c8: specifier: ^7.13.0 version: 7.13.0 + magic-string: + specifier: ^0.30.0 + version: 0.30.0 picocolors: specifier: ^1.0.0 version: 1.0.0 @@ -1476,6 +1482,9 @@ importers: test/coverage-test: devDependencies: + '@types/istanbul-lib-coverage': + specifier: ^2.0.4 + version: 2.0.4 '@vitejs/plugin-vue': specifier: latest version: 4.1.0(vite@4.2.1)(vue@3.2.47) @@ -1488,6 +1497,9 @@ importers: happy-dom: specifier: latest version: 9.1.7 + istanbul-lib-coverage: + specifier: ^3.2.0 + version: 3.2.0 vite: specifier: ^4.2.1 version: 4.2.1(@types/node@18.15.11) diff --git a/test/coverage-test/coverage-report-tests/__snapshots__/c8.report.test.ts.snap b/test/coverage-test/coverage-report-tests/__snapshots__/c8.report.test.ts.snap index bc105adcc360..e55e5fbacbf3 100644 --- a/test/coverage-test/coverage-report-tests/__snapshots__/c8.report.test.ts.snap +++ b/test/coverage-test/coverage-report-tests/__snapshots__/c8.report.test.ts.snap @@ -695,68 +695,10 @@ exports[`c8 json report 1`] = ` }, "/src/Counter/index.ts": { "all": false, - "b": { - "0": [ - 1, - ], - }, - "branchMap": { - "0": { - "line": 4, - "loc": { - "end": { - "column": 39, - "line": 4, - }, - "start": { - "column": 27, - "line": 4, - }, - }, - "locations": [ - { - "end": { - "column": 39, - "line": 4, - }, - "start": { - "column": 27, - "line": 4, - }, - }, - ], - "type": "branch", - }, - }, - "f": { - "0": 1, - }, - "fnMap": { - "0": { - "decl": { - "end": { - "column": 39, - "line": 4, - }, - "start": { - "column": 27, - "line": 4, - }, - }, - "line": 4, - "loc": { - "end": { - "column": 39, - "line": 4, - }, - "start": { - "column": 27, - "line": 4, - }, - }, - "name": "get", - }, - }, + "b": {}, + "branchMap": {}, + "f": {}, + "fnMap": {}, "path": "/src/Counter/index.ts", "s": { "0": 1, @@ -1300,7 +1242,7 @@ exports[`c8 json report 1`] = ` }, }, }, - "/src/implicitElse.ts": { + "/src/function-count.ts": { "all": false, "b": { "0": [ @@ -1309,55 +1251,84 @@ exports[`c8 json report 1`] = ` "1": [ 1, ], + "2": [ + 1, + ], }, "branchMap": { "0": { - "line": 1, + "line": 11, "loc": { "end": { "column": 1, - "line": 8, + "line": 13, }, "start": { - "column": 49, - "line": 1, + "column": 17, + "line": 11, }, }, "locations": [ { "end": { "column": 1, - "line": 8, + "line": 13, }, "start": { - "column": 49, - "line": 1, + "column": 17, + "line": 11, }, }, ], "type": "branch", }, "1": { - "line": 8, + "line": 18, "loc": { "end": { "column": 1, - "line": 8, + "line": 21, + }, + "start": { + "column": 7, + "line": 18, + }, + }, + "locations": [ + { + "end": { + "column": 1, + "line": 21, + }, + "start": { + "column": 7, + "line": 18, + }, + }, + ], + "type": "branch", + }, + "2": { + "line": 34, + "loc": { + "end": { + "column": 1, + "line": 36, }, "start": { "column": 0, - "line": 8, + "line": 34, }, }, "locations": [ { "end": { "column": 1, - "line": 8, + "line": 36, }, "start": { "column": 0, - "line": 8, + "line": 34, }, }, ], @@ -1367,72 +1338,175 @@ exports[`c8 json report 1`] = ` "f": { "0": 1, "1": 1, + "2": 0, + "3": 0, + "4": 1, }, "fnMap": { "0": { "decl": { "end": { "column": 1, - "line": 8, + "line": 13, }, "start": { - "column": 49, - "line": 1, + "column": 17, + "line": 11, }, }, - "line": 1, + "line": 11, "loc": { "end": { "column": 1, - "line": 8, + "line": 13, }, "start": { - "column": 49, - "line": 1, + "column": 17, + "line": 11, }, }, - "name": "implicitElse", + "name": "first", }, "1": { "decl": { "end": { "column": 1, - "line": 8, + "line": 21, + }, + "start": { + "column": 7, + "line": 18, + }, + }, + "line": 18, + "loc": { + "end": { + "column": 1, + "line": 21, + }, + "start": { + "column": 7, + "line": 18, + }, + }, + "name": "second", + }, + "2": { + "decl": { + "end": { + "column": 1, + "line": 26, + }, + "start": { + "column": 7, + "line": 24, + }, + }, + "line": 24, + "loc": { + "end": { + "column": 1, + "line": 26, + }, + "start": { + "column": 7, + "line": 24, + }, + }, + "name": "third", + }, + "3": { + "decl": { + "end": { + "column": 1, + "line": 31, }, "start": { "column": 0, - "line": 8, + "line": 29, }, }, - "line": 8, + "line": 29, "loc": { "end": { "column": 1, - "line": 8, + "line": 31, }, "start": { "column": 0, - "line": 8, + "line": 29, + }, + }, + "name": "fourth", + }, + "4": { + "decl": { + "end": { + "column": 1, + "line": 36, + }, + "start": { + "column": 0, + "line": 34, + }, + }, + "line": 34, + "loc": { + "end": { + "column": 1, + "line": 36, + }, + "start": { + "column": 0, + "line": 34, }, }, - "name": "get", + "name": "fifth", }, }, - "path": "/src/implicitElse.ts", + "path": "/src/function-count.ts", "s": { "0": 1, "1": 1, + "10": 1, + "11": 1, + "12": 1, + "13": 1, + "14": 1, + "15": 1, + "16": 1, + "17": 1, + "18": 1, + "19": 1, "2": 1, + "20": 1, + "21": 1, + "22": 1, + "23": 1, + "24": 0, + "25": 0, + "26": 1, + "27": 1, + "28": 0, + "29": 0, "3": 1, + "30": 0, + "31": 1, + "32": 1, + "33": 1, + "34": 1, + "35": 1, "4": 1, "5": 1, "6": 1, "7": 1, + "8": 1, + "9": 1, }, "statementMap": { "0": { "end": { - "column": 50, + "column": 2, "line": 1, }, "start": { @@ -1442,7 +1516,7 @@ exports[`c8 json report 1`] = ` }, "1": { "end": { - "column": 11, + "column": 25, "line": 2, }, "start": { @@ -1450,77 +1524,354 @@ exports[`c8 json report 1`] = ` "line": 2, }, }, - "2": { + "10": { + "end": { + "column": 18, + "line": 11, + }, + "start": { + "column": 0, + "line": 11, + }, + }, + "11": { "end": { + "column": 10, + "line": 12, + }, + "start": { "column": 0, - "line": 3, + "line": 12, + }, + }, + "12": { + "end": { + "column": 1, + "line": 13, }, "start": { "column": 0, - "line": 3, + "line": 13, }, }, - "3": { + "13": { "end": { - "column": 16, - "line": 4, + "column": 0, + "line": 14, }, "start": { "column": 0, - "line": 4, + "line": 14, }, }, - "4": { + "14": { "end": { - "column": 9, - "line": 5, + "column": 7, + "line": 15, }, "start": { "column": 0, - "line": 5, + "line": 15, }, }, - "5": { + "15": { "end": { "column": 0, - "line": 6, + "line": 16, }, "start": { "column": 0, - "line": 6, + "line": 16, }, }, - "6": { + "16": { "end": { - "column": 10, - "line": 7, + "column": 27, + "line": 17, }, "start": { "column": 0, - "line": 7, + "line": 17, }, }, - "7": { + "17": { "end": { - "column": 1, - "line": 8, + "column": 26, + "line": 18, }, "start": { "column": 0, - "line": 8, + "line": 18, }, }, - }, - }, - "/src/importEnv.ts": { - "all": false, - "b": { + "18": { + "end": { + "column": 9, + "line": 19, + }, + "start": { + "column": 0, + "line": 19, + }, + }, + "19": { + "end": { + "column": 10, + "line": 20, + }, + "start": { + "column": 0, + "line": 20, + }, + }, + "2": { + "end": { + "column": 25, + "line": 3, + }, + "start": { + "column": 0, + "line": 3, + }, + }, + "20": { + "end": { + "column": 1, + "line": 21, + }, + "start": { + "column": 0, + "line": 21, + }, + }, + "21": { + "end": { + "column": 0, + "line": 22, + }, + "start": { + "column": 0, + "line": 22, + }, + }, + "22": { + "end": { + "column": 31, + "line": 23, + }, + "start": { + "column": 0, + "line": 23, + }, + }, + "23": { + "end": { + "column": 25, + "line": 24, + }, + "start": { + "column": 0, + "line": 24, + }, + }, + "24": { + "end": { + "column": 46, + "line": 25, + }, + "start": { + "column": 0, + "line": 25, + }, + }, + "25": { + "end": { + "column": 1, + "line": 26, + }, + "start": { + "column": 0, + "line": 26, + }, + }, + "26": { + "end": { + "column": 0, + "line": 27, + }, + "start": { + "column": 0, + "line": 27, + }, + }, + "27": { + "end": { + "column": 31, + "line": 28, + }, + "start": { + "column": 0, + "line": 28, + }, + }, + "28": { + "end": { + "column": 19, + "line": 29, + }, + "start": { + "column": 0, + "line": 29, + }, + }, + "29": { + "end": { + "column": 10, + "line": 30, + }, + "start": { + "column": 0, + "line": 30, + }, + }, + "3": { + "end": { + "column": 24, + "line": 4, + }, + "start": { + "column": 0, + "line": 4, + }, + }, + "30": { + "end": { + "column": 1, + "line": 31, + }, + "start": { + "column": 0, + "line": 31, + }, + }, + "31": { + "end": { + "column": 0, + "line": 32, + }, + "start": { + "column": 0, + "line": 32, + }, + }, + "32": { + "end": { + "column": 27, + "line": 33, + }, + "start": { + "column": 0, + "line": 33, + }, + }, + "33": { + "end": { + "column": 18, + "line": 34, + }, + "start": { + "column": 0, + "line": 34, + }, + }, + "34": { + "end": { + "column": 10, + "line": 35, + }, + "start": { + "column": 0, + "line": 35, + }, + }, + "35": { + "end": { + "column": 1, + "line": 36, + }, + "start": { + "column": 0, + "line": 36, + }, + }, + "4": { + "end": { + "column": 26, + "line": 5, + }, + "start": { + "column": 0, + "line": 5, + }, + }, + "5": { + "end": { + "column": 3, + "line": 6, + }, + "start": { + "column": 0, + "line": 6, + }, + }, + "6": { + "end": { + "column": 0, + "line": 7, + }, + "start": { + "column": 0, + "line": 7, + }, + }, + "7": { + "end": { + "column": 50, + "line": 8, + }, + "start": { + "column": 0, + "line": 8, + }, + }, + "8": { + "end": { + "column": 0, + "line": 9, + }, + "start": { + "column": 0, + "line": 9, + }, + }, + "9": { + "end": { + "column": 27, + "line": 10, + }, + "start": { + "column": 0, + "line": 10, + }, + }, + }, + }, + "/src/implicitElse.ts": { + "all": false, + "b": { "0": [ 1, ], - "1": [ - 1, - ], }, "branchMap": { "0": { @@ -1528,10 +1879,10 @@ exports[`c8 json report 1`] = ` "loc": { "end": { "column": 1, - "line": 3, + "line": 8, }, "start": { - "column": 31, + "column": 49, "line": 1, }, }, @@ -1539,26 +1890,158 @@ exports[`c8 json report 1`] = ` { "end": { "column": 1, - "line": 3, + "line": 8, }, "start": { - "column": 31, + "column": 49, "line": 1, }, }, ], "type": "branch", }, + }, + "f": { + "0": 1, + }, + "fnMap": { + "0": { + "decl": { + "end": { + "column": 1, + "line": 8, + }, + "start": { + "column": 49, + "line": 1, + }, + }, + "line": 1, + "loc": { + "end": { + "column": 1, + "line": 8, + }, + "start": { + "column": 49, + "line": 1, + }, + }, + "name": "implicitElse", + }, + }, + "path": "/src/implicitElse.ts", + "s": { + "0": 1, + "1": 1, + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 1, + }, + "statementMap": { + "0": { + "end": { + "column": 50, + "line": 1, + }, + "start": { + "column": 0, + "line": 1, + }, + }, "1": { - "line": 3, + "end": { + "column": 11, + "line": 2, + }, + "start": { + "column": 0, + "line": 2, + }, + }, + "2": { + "end": { + "column": 0, + "line": 3, + }, + "start": { + "column": 0, + "line": 3, + }, + }, + "3": { + "end": { + "column": 16, + "line": 4, + }, + "start": { + "column": 0, + "line": 4, + }, + }, + "4": { + "end": { + "column": 9, + "line": 5, + }, + "start": { + "column": 0, + "line": 5, + }, + }, + "5": { + "end": { + "column": 0, + "line": 6, + }, + "start": { + "column": 0, + "line": 6, + }, + }, + "6": { + "end": { + "column": 10, + "line": 7, + }, + "start": { + "column": 0, + "line": 7, + }, + }, + "7": { + "end": { + "column": 1, + "line": 8, + }, + "start": { + "column": 0, + "line": 8, + }, + }, + }, + }, + "/src/importEnv.ts": { + "all": false, + "b": { + "0": [ + 1, + ], + }, + "branchMap": { + "0": { + "line": 1, "loc": { "end": { "column": 1, "line": 3, }, "start": { - "column": 0, - "line": 3, + "column": 31, + "line": 1, }, }, "locations": [ @@ -1568,8 +2051,8 @@ exports[`c8 json report 1`] = ` "line": 3, }, "start": { - "column": 0, - "line": 3, + "column": 31, + "line": 1, }, }, ], @@ -1578,7 +2061,6 @@ exports[`c8 json report 1`] = ` }, "f": { "0": 1, - "1": 1, }, "fnMap": { "0": { @@ -1605,30 +2087,6 @@ exports[`c8 json report 1`] = ` }, "name": "useImportEnv", }, - "1": { - "decl": { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - "line": 3, - "loc": { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - "name": "get", - }, }, "path": "/src/importEnv.ts", "s": { @@ -1675,9 +2133,6 @@ exports[`c8 json report 1`] = ` "0": [ 1, ], - "1": [ - 1, - ], }, "branchMap": { "0": { @@ -1706,36 +2161,9 @@ exports[`c8 json report 1`] = ` ], "type": "branch", }, - "1": { - "line": 7, - "loc": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "locations": [ - { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - ], - "type": "branch", - }, }, "f": { "0": 1, - "1": 1, }, "fnMap": { "0": { @@ -1762,30 +2190,6 @@ exports[`c8 json report 1`] = ` }, "name": "pythagoras", }, - "1": { - "decl": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "line": 7, - "loc": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "name": "get", - }, }, "path": "/src/index.mts", "s": { @@ -2309,24 +2713,15 @@ exports[`c8 json report 1`] = ` "0": [ 1, ], - "1": [ - 1, - ], - "2": [ - 2, - ], - "3": [ + "1": [ 2, ], - "4": [ + "2": [ 1, ], - "5": [ + "3": [ 0, ], - "6": [ - 1, - ], }, "branchMap": { "0": { @@ -2356,32 +2751,6 @@ exports[`c8 json report 1`] = ` "type": "branch", }, "1": { - "line": 3, - "loc": { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - "locations": [ - { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - ], - "type": "branch", - }, - "2": { "line": 5, "loc": { "end": { @@ -2407,33 +2776,7 @@ exports[`c8 json report 1`] = ` ], "type": "branch", }, - "3": { - "line": 7, - "loc": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "locations": [ - { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - ], - "type": "branch", - }, - "4": { + "2": { "line": 14, "loc": { "end": { @@ -2459,7 +2802,7 @@ exports[`c8 json report 1`] = ` ], "type": "branch", }, - "5": { + "3": { "line": 16, "loc": { "end": { @@ -2485,46 +2828,14 @@ exports[`c8 json report 1`] = ` ], "type": "branch", }, - "6": { - "line": 19, - "loc": { - "end": { - "column": 1, - "line": 19, - }, - "start": { - "column": 0, - "line": 19, - }, - }, - "locations": [ - { - "end": { - "column": 1, - "line": 19, - }, - "start": { - "column": 0, - "line": 19, - }, - }, - ], - "type": "branch", - }, }, "f": { "0": 1, - "1": 1, - "10": 1, - "11": 1, - "2": 2, - "3": 2, + "1": 2, + "2": 0, + "3": 1, "4": 0, - "5": 0, - "6": 1, - "7": 1, - "8": 0, - "9": 0, + "5": 1, }, "fnMap": { "0": { @@ -2552,78 +2863,6 @@ exports[`c8 json report 1`] = ` "name": "add", }, "1": { - "decl": { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - "line": 3, - "loc": { - "end": { - "column": 1, - "line": 3, - }, - "start": { - "column": 0, - "line": 3, - }, - }, - "name": "get", - }, - "10": { - "decl": { - "end": { - "column": 1, - "line": 30, - }, - "start": { - "column": 7, - "line": 28, - }, - }, - "line": 28, - "loc": { - "end": { - "column": 1, - "line": 30, - }, - "start": { - "column": 7, - "line": 28, - }, - }, - "name": "ignoredFunction", - }, - "11": { - "decl": { - "end": { - "column": 1, - "line": 30, - }, - "start": { - "column": 0, - "line": 30, - }, - }, - "line": 30, - "loc": { - "end": { - "column": 1, - "line": 30, - }, - "start": { - "column": 0, - "line": 30, - }, - }, - "name": "get", - }, - "2": { "decl": { "end": { "column": 1, @@ -2647,31 +2886,7 @@ exports[`c8 json report 1`] = ` }, "name": "multiply", }, - "3": { - "decl": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "line": 7, - "loc": { - "end": { - "column": 1, - "line": 7, - }, - "start": { - "column": 0, - "line": 7, - }, - }, - "name": "get", - }, - "4": { + "2": { "decl": { "end": { "column": 1, @@ -2695,31 +2910,7 @@ exports[`c8 json report 1`] = ` }, "name": "divide", }, - "5": { - "decl": { - "end": { - "column": 1, - "line": 12, - }, - "start": { - "column": 0, - "line": 12, - }, - }, - "line": 12, - "loc": { - "end": { - "column": 1, - "line": 12, - }, - "start": { - "column": 0, - "line": 12, - }, - }, - "name": "get", - }, - "6": { + "3": { "decl": { "end": { "column": 1, @@ -2743,31 +2934,7 @@ exports[`c8 json report 1`] = ` }, "name": "sqrt", }, - "7": { - "decl": { - "end": { - "column": 1, - "line": 19, - }, - "start": { - "column": 0, - "line": 19, - }, - }, - "line": 19, - "loc": { - "end": { - "column": 1, - "line": 19, - }, - "start": { - "column": 0, - "line": 19, - }, - }, - "name": "get", - }, - "8": { + "4": { "decl": { "end": { "column": 1, @@ -2791,29 +2958,29 @@ exports[`c8 json report 1`] = ` }, "name": "run", }, - "9": { + "5": { "decl": { "end": { "column": 1, - "line": 24, + "line": 30, }, "start": { - "column": 0, - "line": 24, + "column": 7, + "line": 28, }, }, - "line": 24, + "line": 28, "loc": { "end": { "column": 1, - "line": 24, + "line": 30, }, "start": { - "column": 0, - "line": 24, + "column": 7, + "line": 28, }, }, - "name": "get", + "name": "ignoredFunction", }, }, "path": "/src/utils.ts", diff --git a/test/coverage-test/coverage-report-tests/__snapshots__/custom.report.test.ts.snap b/test/coverage-test/coverage-report-tests/__snapshots__/custom.report.test.ts.snap index c3ea52c099cb..228f2acdde93 100644 --- a/test/coverage-test/coverage-report-tests/__snapshots__/custom.report.test.ts.snap +++ b/test/coverage-test/coverage-report-tests/__snapshots__/custom.report.test.ts.snap @@ -16,6 +16,7 @@ exports[`custom json report 1`] = ` "/src/Defined.vue", "/src/Hello.vue", "/src/another-setup.ts", + "/src/function-count.ts", "/src/implicitElse.ts", "/src/importEnv.ts", "/src/index.mts", diff --git a/test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap b/test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap index 4bdaff5fe8e9..5863cfc4a4fc 100644 --- a/test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap +++ b/test/coverage-test/coverage-report-tests/__snapshots__/istanbul.report.test.ts.snap @@ -519,6 +519,216 @@ exports[`istanbul json report 1`] = ` }, }, }, + "/src/function-count.ts": { + "b": {}, + "branchMap": {}, + "f": { + "0": 1, + "1": 1, + "2": 0, + "3": 0, + "4": 1, + }, + "fnMap": { + "0": { + "decl": { + "end": { + "column": 17, + "line": 11, + }, + "start": { + "column": 9, + "line": 11, + }, + }, + "loc": { + "end": { + "column": null, + "line": 13, + }, + "start": { + "column": 17, + "line": 11, + }, + }, + "name": "first", + }, + "1": { + "decl": { + "end": { + "column": 25, + "line": 18, + }, + "start": { + "column": 16, + "line": 18, + }, + }, + "loc": { + "end": { + "column": null, + "line": 21, + }, + "start": { + "column": 25, + "line": 18, + }, + }, + "name": "second", + }, + "2": { + "decl": { + "end": { + "column": 24, + "line": 24, + }, + "start": { + "column": 16, + "line": 24, + }, + }, + "loc": { + "end": { + "column": null, + "line": 26, + }, + "start": { + "column": 24, + "line": 24, + }, + }, + "name": "third", + }, + "3": { + "decl": { + "end": { + "column": 18, + "line": 29, + }, + "start": { + "column": 9, + "line": 29, + }, + }, + "loc": { + "end": { + "column": null, + "line": 31, + }, + "start": { + "column": 18, + "line": 29, + }, + }, + "name": "fourth", + }, + "4": { + "decl": { + "end": { + "column": 17, + "line": 34, + }, + "start": { + "column": 9, + "line": 34, + }, + }, + "loc": { + "end": { + "column": null, + "line": 36, + }, + "start": { + "column": 17, + "line": 34, + }, + }, + "name": "fifth", + }, + }, + "path": "/src/function-count.ts", + "s": { + "0": 1, + "1": 1, + "2": 1, + "3": 1, + "4": 0, + "5": 0, + "6": 1, + }, + "statementMap": { + "0": { + "end": { + "column": null, + "line": 12, + }, + "start": { + "column": 2, + "line": 12, + }, + }, + "1": { + "end": { + "column": null, + "line": 15, + }, + "start": { + "column": 0, + "line": 15, + }, + }, + "2": { + "end": { + "column": null, + "line": 19, + }, + "start": { + "column": 2, + "line": 19, + }, + }, + "3": { + "end": { + "column": null, + "line": 20, + }, + "start": { + "column": 2, + "line": 20, + }, + }, + "4": { + "end": { + "column": null, + "line": 25, + }, + "start": { + "column": 2, + "line": 25, + }, + }, + "5": { + "end": { + "column": null, + "line": 30, + }, + "start": { + "column": 2, + "line": 30, + }, + }, + "6": { + "end": { + "column": null, + "line": 35, + }, + "start": { + "column": 2, + "line": 35, + }, + }, + }, + }, "/src/implicitElse.ts": { "b": { "0": [ diff --git a/test/coverage-test/coverage-report-tests/generic.report.test.ts b/test/coverage-test/coverage-report-tests/generic.report.test.ts index 59633522ea68..705a56b7b6c2 100644 --- a/test/coverage-test/coverage-report-tests/generic.report.test.ts +++ b/test/coverage-test/coverage-report-tests/generic.report.test.ts @@ -5,6 +5,9 @@ import fs from 'node:fs' import { resolve } from 'pathe' import { expect, test } from 'vitest' +import libCoverage from 'istanbul-lib-coverage' + +import { readCoverageJson } from './utils' test('html report', async () => { const coveragePath = resolve('./coverage/src') @@ -80,3 +83,14 @@ test('thresholdAutoUpdate updates thresholds', async () => { const updatedConfig = configContents.replace(/(branches|functions|lines|statements): ([\d|\.])+/g, '$1: 1.01') fs.writeFileSync(configFilename, updatedConfig) }) + +test('function count is correct', async () => { + const coverageJson = await readCoverageJson() + const coverageMap = libCoverage.createCoverageMap(coverageJson as any) + const fileCoverage = coverageMap.fileCoverageFor('/src/function-count.ts') + + const { functions } = fileCoverage.toSummary() + + expect(functions.total).toBe(5) + expect(functions.covered).toBe(3) +}) diff --git a/test/coverage-test/package.json b/test/coverage-test/package.json index 88d4c7cc0358..4350eb240295 100644 --- a/test/coverage-test/package.json +++ b/test/coverage-test/package.json @@ -10,10 +10,12 @@ "test:types": "vitest typecheck --run --reporter verbose" }, "devDependencies": { + "@types/istanbul-lib-coverage": "^2.0.4", "@vitejs/plugin-vue": "latest", "@vitest/browser": "workspace:*", "@vue/test-utils": "latest", "happy-dom": "latest", + "istanbul-lib-coverage": "^3.2.0", "vite": "latest", "vitest": "workspace:*", "vue": "latest", diff --git a/test/coverage-test/src/function-count.ts b/test/coverage-test/src/function-count.ts new file mode 100644 index 000000000000..52d435bb3c5a --- /dev/null +++ b/test/coverage-test/src/function-count.ts @@ -0,0 +1,36 @@ +/* + * This file should have: + * - 5 functions in total + * - 3 covered functions + * - 2 uncovered functions + */ + +/* eslint-disable unused-imports/no-unused-vars */ + +// This function is covered +function first() { + return 1 +} + +first() + +// This function is covered +export function second() { + fifth() + return 2 +} + +// This function is NOT covered +export function third() { + throw new Error('Do not call this function') +} + +// This function is NOT covered +function fourth() { + return 4 +} + +// This function is covered +function fifth() { + return 5 +} diff --git a/test/coverage-test/test/coverage.test.ts b/test/coverage-test/test/coverage.test.ts index 389a57ae83c5..73007f564392 100644 --- a/test/coverage-test/test/coverage.test.ts +++ b/test/coverage-test/test/coverage.test.ts @@ -1,6 +1,7 @@ import { expect, test } from 'vitest' import { implicitElse } from '../src/implicitElse' import { useImportEnv } from '../src/importEnv' +import { second } from '../src/function-count' const { pythagoras } = await (() => { if ('__vitest_browser__' in globalThis) @@ -22,3 +23,7 @@ test('implicit else', () => { test('import meta env', () => { expect(useImportEnv()).toBe(true) }) + +test('cover function counts', () => { + expect(second()).toBe(2) +})