diff --git a/e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap b/e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
index 47a9e0f07..35945e037 100644
--- a/e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
+++ b/e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
@@ -1,425 +1,5 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-exports[`CLI collect > should run Code coverage plugin that runs coverage tool and creates report.json 1`] = `
-{
- "categories": [
- {
- "refs": [
- {
- "plugin": "coverage",
- "slug": "coverage",
- "type": "group",
- "weight": 1,
- },
- ],
- "slug": "code-coverage",
- "title": "Code coverage",
- },
- ],
- "packageName": "@code-pushup/core",
- "plugins": [
- {
- "audits": [
- {
- "description": "Measures how many functions were called in at least one test.",
- "details": {
- "issues": [
- {
- "message": "Function onSubmit is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "examples/react-todos-app/src/components/CreateTodo.jsx",
- "position": {
- "startLine": 13,
- },
- },
- },
- {
- "message": "Function onInput is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "examples/react-todos-app/src/components/CreateTodo.jsx",
- "position": {
- "startLine": 21,
- },
- },
- },
- {
- "message": "Function onInput is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "examples/react-todos-app/src/components/TodoFilter.jsx",
- "position": {
- "startLine": 9,
- },
- },
- },
- {
- "message": "Function onChange is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "examples/react-todos-app/src/components/TodoFilter.jsx",
- "position": {
- "startLine": 17,
- },
- },
- },
- ],
- },
- "displayValue": "55.6 %",
- "score": 0.5556,
- "slug": "function-coverage",
- "title": "Function coverage",
- "value": 55.55555555555556,
- },
- {
- "description": "Measures how many branches were executed after conditional statements in at least one test.",
- "details": {
- "issues": [
- {
- "message": "1st branch is not taken in any test case.",
- "severity": "error",
- "source": {
- "file": "examples/react-todos-app/src/index.jsx",
- "position": {
- "startLine": 1,
- },
- },
- },
- ],
- },
- "displayValue": "87.5 %",
- "score": 0.875,
- "slug": "branch-coverage",
- "title": "Branch coverage",
- "value": 87.5,
- },
- {
- "description": "Measures how many lines of code were executed in at least one test.",
- "details": {
- "issues": [
- {
- "message": "Lines 1-6 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/index.jsx",
- "position": {
- "endLine": 6,
- "startLine": 1,
- },
- },
- },
- {
- "message": "Lines 14-17 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/components/CreateTodo.jsx",
- "position": {
- "endLine": 17,
- "startLine": 14,
- },
- },
- },
- {
- "message": "Lines 22-23 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/components/CreateTodo.jsx",
- "position": {
- "endLine": 23,
- "startLine": 22,
- },
- },
- },
- {
- "message": "Lines 10-11 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/components/TodoFilter.jsx",
- "position": {
- "endLine": 11,
- "startLine": 10,
- },
- },
- },
- {
- "message": "Lines 18-19 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/components/TodoFilter.jsx",
- "position": {
- "endLine": 19,
- "startLine": 18,
- },
- },
- },
- {
- "message": "Lines 7-28 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/components/TodoList.jsx",
- "position": {
- "endLine": 28,
- "startLine": 7,
- },
- },
- },
- {
- "message": "Lines 12-13 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/hooks/useTodos.js",
- "position": {
- "endLine": 13,
- "startLine": 12,
- },
- },
- },
- {
- "message": "Lines 18-37 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/hooks/useTodos.js",
- "position": {
- "endLine": 37,
- "startLine": 18,
- },
- },
- },
- {
- "message": "Lines 41-45 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/hooks/useTodos.js",
- "position": {
- "endLine": 45,
- "startLine": 41,
- },
- },
- },
- {
- "message": "Lines 54-60 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "examples/react-todos-app/src/hooks/useTodos.js",
- "position": {
- "endLine": 60,
- "startLine": 54,
- },
- },
- },
- ],
- },
- "displayValue": "62.1 %",
- "score": 0.6211,
- "slug": "line-coverage",
- "title": "Line coverage",
- "value": 62.10526315789474,
- },
- ],
- "description": "Official Code PushUp code coverage plugin.",
- "docsUrl": "https://www.npmjs.com/package/@code-pushup/coverage-plugin/",
- "groups": [
- {
- "description": "Group containing all defined coverage types as audits.",
- "refs": [
- {
- "slug": "function-coverage",
- "weight": 6,
- },
- {
- "slug": "branch-coverage",
- "weight": 3,
- },
- {
- "slug": "line-coverage",
- "weight": 1,
- },
- ],
- "slug": "coverage",
- "title": "Code coverage metrics",
- },
- ],
- "icon": "folder-coverage-open",
- "packageName": "@code-pushup/coverage-plugin",
- "slug": "coverage",
- "title": "Code coverage",
- },
- ],
-}
-`;
-
-exports[`CLI collect > should run Code coverage plugin which collects passed results and creates report.json 1`] = `
-{
- "categories": [
- {
- "refs": [
- {
- "plugin": "coverage",
- "slug": "coverage",
- "type": "group",
- "weight": 1,
- },
- ],
- "slug": "code-coverage",
- "title": "Code coverage",
- },
- ],
- "packageName": "@code-pushup/core",
- "plugins": [
- {
- "audits": [
- {
- "description": "Measures how many functions were called in at least one test.",
- "details": {
- "issues": [
- {
- "message": "Function formatReportScore is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/partly-covered/utils.ts",
- "position": {
- "startLine": 2,
- },
- },
- },
- {
- "message": "Function sortReport is not called in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/not-covered/sorting.ts",
- "position": {
- "startLine": 1,
- },
- },
- },
- ],
- },
- "displayValue": "60 %",
- "score": 0.6,
- "slug": "function-coverage",
- "title": "Function coverage",
- "value": 60,
- },
- {
- "description": "Measures how many branches were executed after conditional statements in at least one test.",
- "details": {
- "issues": [
- {
- "message": "2nd branch is not taken in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/partly-covered/utils.ts",
- "position": {
- "startLine": 6,
- },
- },
- },
- {
- "message": "2nd branch is not taken in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/partly-covered/utils.ts",
- "position": {
- "startLine": 10,
- },
- },
- },
- {
- "message": "1st branch is not taken in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/not-covered/sorting.ts",
- "position": {
- "startLine": 7,
- },
- },
- },
- {
- "message": "2nd branch is not taken in any test case.",
- "severity": "error",
- "source": {
- "file": "src/lib/not-covered/sorting.ts",
- "position": {
- "startLine": 7,
- },
- },
- },
- ],
- },
- "displayValue": "76.5 %",
- "score": 0.7647,
- "slug": "branch-coverage",
- "title": "Branch coverage",
- "value": 76.47058823529412,
- },
- {
- "description": "Measures how many lines of code were executed in at least one test.",
- "details": {
- "issues": [
- {
- "message": "Lines 7-9 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "src/lib/partly-covered/utils.ts",
- "position": {
- "endLine": 9,
- "startLine": 7,
- },
- },
- },
- {
- "message": "Lines 1-5 are not covered in any test case.",
- "severity": "warning",
- "source": {
- "file": "src/lib/not-covered/sorting.ts",
- "position": {
- "endLine": 5,
- "startLine": 1,
- },
- },
- },
- ],
- },
- "displayValue": "68 %",
- "score": 0.68,
- "slug": "line-coverage",
- "title": "Line coverage",
- "value": 68,
- },
- ],
- "description": "Official Code PushUp code coverage plugin.",
- "docsUrl": "https://www.npmjs.com/package/@code-pushup/coverage-plugin/",
- "groups": [
- {
- "description": "Group containing all defined coverage types as audits.",
- "refs": [
- {
- "slug": "function-coverage",
- "weight": 6,
- },
- {
- "slug": "branch-coverage",
- "weight": 3,
- },
- {
- "slug": "line-coverage",
- "weight": 1,
- },
- ],
- "slug": "coverage",
- "title": "Code coverage metrics",
- },
- ],
- "icon": "folder-coverage-open",
- "packageName": "@code-pushup/coverage-plugin",
- "slug": "coverage",
- "title": "Code coverage",
- },
- ],
-}
-`;
-
exports[`CLI collect > should run ESLint plugin and create report.json 1`] = `
{
"categories": [
diff --git a/e2e/cli-e2e/tests/collect.e2e.test.ts b/e2e/cli-e2e/tests/collect.e2e.test.ts
index 5e301ab29..269fae9fb 100644
--- a/e2e/cli-e2e/tests/collect.e2e.test.ts
+++ b/e2e/cli-e2e/tests/collect.e2e.test.ts
@@ -1,5 +1,3 @@
-import { dirname, join } from 'node:path';
-import { fileURLToPath } from 'node:url';
import {
type AuditReport,
type PluginReport,
@@ -65,59 +63,6 @@ describe('CLI collect', () => {
expect(omitVariableReportData(report as Report)).toMatchSnapshot();
});
- it('should run Code coverage plugin which collects passed results and creates report.json', async () => {
- /**
- * The stats passed in the fixture are as follows
- * 3 files: one partially covered, one with no coverage, one with full coverage
- * Functions: 2 + 1 + 2 found | 1 + 0 + 2 covered (60% coverage)
- * Branches: 10 + 2 + 5 found | 8 + 0 + 5 covered (76% coverage)
- * Lines: 10 + 5 + 10 found | 7 + 0 + 10 covered (68% coverage)
- */
-
- const configPath = join(
- fileURLToPath(dirname(import.meta.url)),
- '..',
- 'mocks',
- 'fixtures',
- 'code-pushup.config.ts',
- );
-
- const { code, stderr } = await executeProcess({
- command: 'code-pushup',
- args: [
- 'collect',
- '--no-progress',
- `--config=${configPath}`,
- '--persist.outputDir=tmp/e2e',
- '--onlyPlugins=coverage',
- ],
- });
-
- expect(code).toBe(0);
- expect(stderr).toBe('');
-
- const report = await readJsonFile(join('tmp', 'e2e', 'report.json'));
-
- expect(() => reportSchema.parse(report)).not.toThrow();
- expect(omitVariableReportData(report as Report)).toMatchSnapshot();
- });
-
- it('should run Code coverage plugin that runs coverage tool and creates report.json', async () => {
- const { code, stderr } = await executeProcess({
- command: 'code-pushup',
- args: ['collect', '--no-progress', '--onlyPlugins=coverage'],
- cwd: 'examples/react-todos-app',
- });
-
- expect(code).toBe(0);
- expect(stderr).toBe('');
-
- const report = await readJsonFile('tmp/e2e/react-todos-app/report.json');
-
- expect(() => reportSchema.parse(report)).not.toThrow();
- expect(omitVariableReportData(report as Report)).toMatchSnapshot();
- });
-
it('should create report.md', async () => {
const { code, stderr } = await executeProcess({
command: 'code-pushup',
diff --git a/e2e/plugin-coverage-e2e/.eslintrc.json b/e2e/plugin-coverage-e2e/.eslintrc.json
new file mode 100644
index 000000000..7ef7b6dc8
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/.eslintrc.json
@@ -0,0 +1,12 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*", "code-pushup.config*.ts"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "parserOptions": {
+ "project": ["e2e/plugin-coverage-e2e/tsconfig.*?.json"]
+ }
+ }
+ ]
+}
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/code-pushup.config.ts b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/code-pushup.config.ts
new file mode 100644
index 000000000..8d506c569
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/code-pushup.config.ts
@@ -0,0 +1,27 @@
+import coveragePlugin from '@code-pushup/coverage-plugin';
+
+export default {
+ plugins: [
+ await coveragePlugin({
+ reports: ['coverage/lcov.info'],
+ coverageToolCommand: {
+ command: 'npm',
+ args: ['run', 'test'],
+ },
+ }),
+ ],
+ categories: [
+ {
+ slug: 'code-coverage',
+ title: 'Code coverage',
+ refs: [
+ {
+ type: 'group',
+ plugin: 'coverage',
+ slug: 'coverage',
+ weight: 1,
+ },
+ ],
+ },
+ ],
+};
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/package.json b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/package.json
new file mode 100644
index 000000000..61a96ca4c
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "coverage-e2e-env",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "test": "npx vitest run --coverage"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ },
+ "description": ""
+}
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.mjs b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.mjs
new file mode 100644
index 000000000..b698a1fac
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.mjs
@@ -0,0 +1,15 @@
+export function untested() {
+ console.log('This function is not tested');
+}
+
+export function get42() {
+ return 42;
+}
+
+export function isEven(num) {
+ if (num === undefined) {
+ return false;
+ }
+ const parsedNumber = parseInt(num, 10);
+ return parsedNumber % 2 === 0;
+}
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.test.mjs b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.test.mjs
new file mode 100644
index 000000000..d02988166
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/src/index.test.mjs
@@ -0,0 +1,18 @@
+import { describe, expect, it } from 'vitest';
+import { get42, isEven, untested } from './index.mjs';
+
+describe('get42', () => {
+ it('should return 42', async () => {
+ expect(get42()).toBe(42);
+ });
+});
+
+describe('isEven', () => {
+ it('should return true for even number 42', async () => {
+ expect(isEven(42)).toBe(true);
+ });
+
+ it.todo('should return false for odd number 1');
+});
+
+describe.todo('untested', () => {});
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/vite.config.ts b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/vite.config.ts
new file mode 100644
index 000000000..7a6636feb
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/basic-setup/vite.config.ts
@@ -0,0 +1,25 @@
+///
+import { dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ root: fileURLToPath(dirname(import.meta.url)),
+ cacheDir: 'node_modules/.vite/coverage-e2e-env',
+
+ test: {
+ reporters: ['basic'],
+ globals: true,
+ cache: {
+ dir: 'node_modules/.vitest',
+ },
+ coverage: {
+ reporter: ['lcov', 'text'],
+ provider: 'v8',
+ reportsDirectory: 'coverage',
+ include: ['src/**/*.{js,mjs}'],
+ },
+ environment: 'node',
+ include: ['src/**/*.{test,spec}.{js,mjs}'],
+ },
+});
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/code-pushup.config.ts b/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/code-pushup.config.ts
new file mode 100644
index 000000000..d955bbba0
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/code-pushup.config.ts
@@ -0,0 +1,25 @@
+import { join } from 'node:path';
+import coveragePlugin from '@code-pushup/coverage-plugin';
+import type { CoreConfig } from '@code-pushup/models';
+
+export default {
+ plugins: [
+ await coveragePlugin({
+ reports: [join('coverage', 'lcov.info')],
+ }),
+ ],
+ categories: [
+ {
+ slug: 'code-coverage',
+ title: 'Code coverage',
+ refs: [
+ {
+ type: 'group',
+ plugin: 'coverage',
+ slug: 'coverage',
+ weight: 1,
+ },
+ ],
+ },
+ ],
+} satisfies CoreConfig;
diff --git a/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/coverage/lcov.info b/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/coverage/lcov.info
new file mode 100644
index 000000000..474ad74e7
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/mocks/fixtures/existing-report/coverage/lcov.info
@@ -0,0 +1,78 @@
+TN:
+SF:src\lib\partly-covered\utils.ts
+FN:2,formatReportScore
+FN:6,calcDuration
+FNF:2
+FNH:1
+FNDA:0,formatReportScore
+FNDA:6,calcDuration
+DA:1,1
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:6,1
+DA:7,0
+DA:8,0
+DA:9,0
+DA:10,1
+LF:10
+LH:7
+BRDA:1,0,0,6
+BRDA:1,1,0,5
+BRDA:2,4,0,1
+BRDA:4,5,0,17
+BRDA:5,6,0,4
+BRDA:6,7,0,13
+BRDA:6,10,1,0
+BRDA:7,11,0,3
+BRDA:10,12,0,12
+BRDA:10,13,1,0
+BRF:10
+BRH:8
+end_of_record
+SF:src\lib\not-covered\sorting.ts
+FN:1,sortReport
+FNF:1
+FNH:0
+FNDA:0,sortReport
+DA:1,0
+DA:2,0
+DA:3,0
+DA:4,0
+DA:5,0
+LF:5
+LH:0
+BRDA:7,1,0,0
+BRDA:7,2,1,0
+BRF:2
+BRH:0
+end_of_record
+TN:
+SF:src\lib\fully-covered\scoring.ts
+FN:2,scoreReport
+FN:8,calculateScore
+FNF:2
+FNH:2
+FNDA:3,scoreReport
+FNDA:5,calculateScore
+DA:1,1
+DA:2,1
+DA:3,1
+DA:4,1
+DA:5,1
+DA:6,1
+DA:7,1
+DA:8,1
+DA:9,1
+DA:10,1
+LF:10
+LH:10
+BRDA:1,0,0,5
+BRDA:2,1,0,1
+BRDA:2,2,1,4
+BRDA:2,3,2,3
+BRDA:6,4,0,4
+BRF:5
+BRH:5
+end_of_record
diff --git a/e2e/plugin-coverage-e2e/project.json b/e2e/plugin-coverage-e2e/project.json
new file mode 100644
index 000000000..8a0932adf
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/project.json
@@ -0,0 +1,23 @@
+{
+ "name": "plugin-coverage-e2e",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "e2e/plugin-coverage-e2e/src",
+ "projectType": "application",
+ "targets": {
+ "lint": {
+ "executor": "@nx/linter:eslint",
+ "outputs": ["{options.outputFile}"],
+ "options": {
+ "lintFilePatterns": ["e2e/plugin-coverage-e2e/**/*.ts"]
+ }
+ },
+ "e2e": {
+ "executor": "@nx/vite:test",
+ "options": {
+ "configFile": "e2e/plugin-coverage-e2e/vite.config.e2e.ts"
+ }
+ }
+ },
+ "implicitDependencies": ["cli", "plugin-coverage"],
+ "tags": ["scope:plugin", "type:e2e"]
+}
diff --git a/e2e/plugin-coverage-e2e/tests/__snapshots__/collect.e2e.test.ts.snap b/e2e/plugin-coverage-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
new file mode 100644
index 000000000..d15a8626b
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
@@ -0,0 +1,303 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`collect report with coverage-plugin NPM package > should run Code coverage plugin that runs coverage tool and creates report.json 1`] = `
+{
+ "categories": [
+ {
+ "refs": [
+ {
+ "plugin": "coverage",
+ "slug": "coverage",
+ "type": "group",
+ "weight": 1,
+ },
+ ],
+ "slug": "code-coverage",
+ "title": "Code coverage",
+ },
+ ],
+ "packageName": "@code-pushup/core",
+ "plugins": [
+ {
+ "audits": [
+ {
+ "description": "Measures how many functions were called in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "Function formatReportScore is not called in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/partly-covered/utils.ts",
+ "position": {
+ "startLine": 2,
+ },
+ },
+ },
+ {
+ "message": "Function sortReport is not called in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/not-covered/sorting.ts",
+ "position": {
+ "startLine": 1,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "60 %",
+ "score": 0.6,
+ "slug": "function-coverage",
+ "title": "Function coverage",
+ "value": 60,
+ },
+ {
+ "description": "Measures how many branches were executed after conditional statements in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "2nd branch is not taken in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/partly-covered/utils.ts",
+ "position": {
+ "startLine": 6,
+ },
+ },
+ },
+ {
+ "message": "2nd branch is not taken in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/partly-covered/utils.ts",
+ "position": {
+ "startLine": 10,
+ },
+ },
+ },
+ {
+ "message": "1st branch is not taken in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/not-covered/sorting.ts",
+ "position": {
+ "startLine": 7,
+ },
+ },
+ },
+ {
+ "message": "2nd branch is not taken in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/not-covered/sorting.ts",
+ "position": {
+ "startLine": 7,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "76.5 %",
+ "score": 0.7647,
+ "slug": "branch-coverage",
+ "title": "Branch coverage",
+ "value": 76.47058823529412,
+ },
+ {
+ "description": "Measures how many lines of code were executed in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "Lines 7-9 are not covered in any test case.",
+ "severity": "warning",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/partly-covered/utils.ts",
+ "position": {
+ "endLine": 9,
+ "startLine": 7,
+ },
+ },
+ },
+ {
+ "message": "Lines 1-5 are not covered in any test case.",
+ "severity": "warning",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/existing-report/src/lib/not-covered/sorting.ts",
+ "position": {
+ "endLine": 5,
+ "startLine": 1,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "68 %",
+ "score": 0.68,
+ "slug": "line-coverage",
+ "title": "Line coverage",
+ "value": 68,
+ },
+ ],
+ "description": "Official Code PushUp code coverage plugin.",
+ "docsUrl": "https://www.npmjs.com/package/@code-pushup/coverage-plugin/",
+ "groups": [
+ {
+ "description": "Group containing all defined coverage types as audits.",
+ "refs": [
+ {
+ "slug": "function-coverage",
+ "weight": 6,
+ },
+ {
+ "slug": "branch-coverage",
+ "weight": 3,
+ },
+ {
+ "slug": "line-coverage",
+ "weight": 1,
+ },
+ ],
+ "slug": "coverage",
+ "title": "Code coverage metrics",
+ },
+ ],
+ "icon": "folder-coverage-open",
+ "packageName": "@code-pushup/coverage-plugin",
+ "slug": "coverage",
+ "title": "Code coverage",
+ },
+ ],
+}
+`;
+
+exports[`collect report with coverage-plugin NPM package > should run Code coverage plugin which collects passed results and creates report.json 1`] = `
+{
+ "categories": [
+ {
+ "refs": [
+ {
+ "plugin": "coverage",
+ "slug": "coverage",
+ "type": "group",
+ "weight": 1,
+ },
+ ],
+ "slug": "code-coverage",
+ "title": "Code coverage",
+ },
+ ],
+ "packageName": "@code-pushup/core",
+ "plugins": [
+ {
+ "audits": [
+ {
+ "description": "Measures how many functions were called in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "Function untested is not called in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/basic-setup/src/index.mjs",
+ "position": {
+ "startLine": 1,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "66.7 %",
+ "score": 0.6667,
+ "slug": "function-coverage",
+ "title": "Function coverage",
+ "value": 66.66666666666666,
+ },
+ {
+ "description": "Measures how many branches were executed after conditional statements in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "1st branch is not taken in any test case.",
+ "severity": "error",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/basic-setup/src/index.mjs",
+ "position": {
+ "startLine": 10,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "66.7 %",
+ "score": 0.6667,
+ "slug": "branch-coverage",
+ "title": "Branch coverage",
+ "value": 66.66666666666666,
+ },
+ {
+ "description": "Measures how many lines of code were executed in at least one test.",
+ "details": {
+ "issues": [
+ {
+ "message": "Lines 2-3 are not covered in any test case.",
+ "severity": "warning",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/basic-setup/src/index.mjs",
+ "position": {
+ "endLine": 3,
+ "startLine": 2,
+ },
+ },
+ },
+ {
+ "message": "Lines 11-12 are not covered in any test case.",
+ "severity": "warning",
+ "source": {
+ "file": "tmp/e2e/plugin-coverage-e2e/basic-setup/src/index.mjs",
+ "position": {
+ "endLine": 12,
+ "startLine": 11,
+ },
+ },
+ },
+ ],
+ },
+ "displayValue": "73.3 %",
+ "score": 0.7333,
+ "slug": "line-coverage",
+ "title": "Line coverage",
+ "value": 73.33333333333333,
+ },
+ ],
+ "description": "Official Code PushUp code coverage plugin.",
+ "docsUrl": "https://www.npmjs.com/package/@code-pushup/coverage-plugin/",
+ "groups": [
+ {
+ "description": "Group containing all defined coverage types as audits.",
+ "refs": [
+ {
+ "slug": "function-coverage",
+ "weight": 6,
+ },
+ {
+ "slug": "branch-coverage",
+ "weight": 3,
+ },
+ {
+ "slug": "line-coverage",
+ "weight": 1,
+ },
+ ],
+ "slug": "coverage",
+ "title": "Code coverage metrics",
+ },
+ ],
+ "icon": "folder-coverage-open",
+ "packageName": "@code-pushup/coverage-plugin",
+ "slug": "coverage",
+ "title": "Code coverage",
+ },
+ ],
+}
+`;
diff --git a/e2e/plugin-coverage-e2e/tests/collect.e2e.test.ts b/e2e/plugin-coverage-e2e/tests/collect.e2e.test.ts
new file mode 100644
index 000000000..673c56d63
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/tests/collect.e2e.test.ts
@@ -0,0 +1,60 @@
+import { cp } from 'node:fs/promises';
+import { join } from 'node:path';
+import { afterAll, afterEach, beforeAll } from 'vitest';
+import { type Report, reportSchema } from '@code-pushup/models';
+import { teardownTestFolder } from '@code-pushup/test-setup';
+import { omitVariableReportData } from '@code-pushup/test-utils';
+import { executeProcess, readJsonFile } from '@code-pushup/utils';
+
+describe('collect report with coverage-plugin NPM package', () => {
+ const envRoot = 'tmp/e2e/plugin-coverage-e2e';
+ const fixtureDir = join('e2e', 'plugin-coverage-e2e', 'mocks', 'fixtures');
+ const basicDir = join(envRoot, 'basic-setup');
+ const existingDir = join(envRoot, 'existing-report');
+
+ beforeAll(async () => {
+ await cp(fixtureDir, envRoot, { recursive: true });
+ });
+ afterAll(async () => {
+ await teardownTestFolder(basicDir);
+ await teardownTestFolder(existingDir);
+ });
+ afterEach(async () => {
+ await teardownTestFolder(join(basicDir, '.code-pushup'));
+ await teardownTestFolder(join(existingDir, '.code-pushup'));
+ });
+
+ it('should run Code coverage plugin which collects passed results and creates report.json', async () => {
+ const { code } = await executeProcess({
+ command: 'npx',
+ args: ['@code-pushup/cli', 'collect', '--no-progress'],
+ cwd: basicDir,
+ });
+
+ expect(code).toBe(0);
+
+ const report = await readJsonFile(
+ join(basicDir, '.code-pushup', 'report.json'),
+ );
+
+ expect(() => reportSchema.parse(report)).not.toThrow();
+ expect(omitVariableReportData(report as Report)).toMatchSnapshot();
+ });
+
+ it('should run Code coverage plugin that runs coverage tool and creates report.json', async () => {
+ const { code } = await executeProcess({
+ command: 'npx',
+ args: ['@code-pushup/cli', 'collect', '--no-progress'],
+ cwd: existingDir,
+ });
+
+ expect(code).toBe(0);
+
+ const report = await readJsonFile(
+ join(existingDir, '.code-pushup', 'report.json'),
+ );
+
+ expect(() => reportSchema.parse(report)).not.toThrow();
+ expect(omitVariableReportData(report as Report)).toMatchSnapshot();
+ });
+});
diff --git a/e2e/plugin-coverage-e2e/tsconfig.json b/e2e/plugin-coverage-e2e/tsconfig.json
new file mode 100644
index 000000000..f5a2f890a
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "module": "ESNext",
+ "forceConsistentCasingInFileNames": true,
+ "strict": true,
+ "noImplicitOverride": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ "types": ["vitest"]
+ },
+ "files": [],
+ "include": [],
+ "references": [
+ {
+ "path": "./tsconfig.test.json"
+ }
+ ]
+}
diff --git a/e2e/plugin-coverage-e2e/tsconfig.test.json b/e2e/plugin-coverage-e2e/tsconfig.test.json
new file mode 100644
index 000000000..22ad6e52a
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/tsconfig.test.json
@@ -0,0 +1,15 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"],
+ "target": "ES2020"
+ },
+ "exclude": [],
+ "include": [
+ "vite.config.e2e.ts",
+ "tests/**/*.e2e.test.ts",
+ "tests/**/*.d.ts",
+ "mocks/**/*.ts"
+ ]
+}
diff --git a/e2e/plugin-coverage-e2e/vite.config.e2e.ts b/e2e/plugin-coverage-e2e/vite.config.e2e.ts
new file mode 100644
index 000000000..3956da52e
--- /dev/null
+++ b/e2e/plugin-coverage-e2e/vite.config.e2e.ts
@@ -0,0 +1,21 @@
+///
+import { defineConfig } from 'vite';
+import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases';
+
+export default defineConfig({
+ cacheDir: '../../node_modules/.vite/plugin-lighthouse-e2e',
+ test: {
+ reporters: ['basic'],
+ testTimeout: 120_000,
+ globals: true,
+ alias: tsconfigPathAliases(),
+ pool: 'threads',
+ poolOptions: { threads: { singleThread: true } },
+ cache: {
+ dir: '../../node_modules/.vitest',
+ },
+ environment: 'node',
+ include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
+ setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'],
+ },
+});
diff --git a/examples/react-todos-app/code-pushup.config.js b/examples/react-todos-app/code-pushup.config.js
index dcef94a7f..988dca804 100644
--- a/examples/react-todos-app/code-pushup.config.js
+++ b/examples/react-todos-app/code-pushup.config.js
@@ -1,4 +1,3 @@
-import coveragePlugin from '../../dist/packages/plugin-coverage';
import eslintPlugin from '../../dist/packages/plugin-eslint';
const eslintAuditRef = (slug, weight) => ({
@@ -13,31 +12,12 @@ export default {
outputDir: '../../tmp/e2e/react-todos-app',
},
plugins: [
- await coveragePlugin({
- reports: ['../../coverage/react-todos-app/lcov.info'],
- coverageToolCommand: {
- command: 'npx',
- args: ['vitest', 'run', '--coverage'],
- },
- }),
await eslintPlugin({
eslintrc: '.eslintrc.js',
patterns: ['src/**/*.js', 'src/**/*.jsx'],
}),
],
categories: [
- {
- slug: 'code-coverage',
- title: 'Code coverage',
- refs: [
- {
- type: 'group',
- plugin: 'coverage',
- slug: 'coverage',
- weight: 1,
- },
- ],
- },
{
slug: 'bug-prevention',
title: 'Bug prevention',
@@ -60,7 +40,6 @@ export default {
eslintAuditRef('react-hooks-exhaustive-deps', 2),
],
},
-
{
slug: 'code-style',
title: 'Code style',
diff --git a/nx.json b/nx.json
index bebd69d65..299156fe9 100644
--- a/nx.json
+++ b/nx.json
@@ -28,6 +28,10 @@
"e2e": {
"dependsOn": ["^build"]
},
+ "nxv-e2e": {},
+ "nxv-env-setup": {
+ "executor": "@push-based/nx-verdaccio:env-setup"
+ },
"@nx/vite:test": {
"cache": true,
"inputs": ["default", "^production"],
@@ -68,23 +72,7 @@
"appsDir": "examples",
"libsDir": "packages"
},
- "generators": {
- "@nx/react": {
- "application": {
- "style": "css",
- "linter": "eslint",
- "bundler": "vite",
- "babel": true
- },
- "component": {
- "style": "css"
- },
- "library": {
- "style": "css",
- "linter": "eslint"
- }
- }
- },
+ "generators": {},
"release": {
"projects": ["packages/*"],
"projectsRelationship": "fixed",
diff --git a/package-lock.json b/package-lock.json
index 80639ae4b..960950fda 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,7 +49,7 @@
"@nx/react": "17.3.2",
"@nx/vite": "17.3.2",
"@nx/workspace": "17.3.2",
- "@push-based/nx-verdaccio": "0.0.0-alpha.25",
+ "@push-based/nx-verdaccio": "0.0.0-alpha.26",
"@swc-node/register": "^1.10.9",
"@swc/cli": "~0.1.62",
"@swc/core": "^1.3.99",
@@ -5457,9 +5457,9 @@
}
},
"node_modules/@push-based/nx-verdaccio": {
- "version": "0.0.0-alpha.25",
- "resolved": "https://registry.npmjs.org/@push-based/nx-verdaccio/-/nx-verdaccio-0.0.0-alpha.25.tgz",
- "integrity": "sha512-5keAr9Gpw0TjUEwtMZVu/qweBYPPHHxHRNaRJgw94uOGSwcQwFcYn92w3+Z4/VdXhM0/RINALGc+/DgG1PV5fg==",
+ "version": "0.0.0-alpha.26",
+ "resolved": "https://registry.npmjs.org/@push-based/nx-verdaccio/-/nx-verdaccio-0.0.0-alpha.26.tgz",
+ "integrity": "sha512-Go11Dg+w5Ntl5Ig8YNzVVPbpOG85aVszjyBIK0FvVBX+/QllQY1F4fP8K8fYnMJnO9v5Tao3cryGFY5Zo9i+/g==",
"dev": true,
"dependencies": {
"@nx/devkit": "19.8.0",
diff --git a/package.json b/package.json
index da4f9fb46..354f89a4b 100644
--- a/package.json
+++ b/package.json
@@ -61,7 +61,7 @@
"@nx/react": "17.3.2",
"@nx/vite": "17.3.2",
"@nx/workspace": "17.3.2",
- "@push-based/nx-verdaccio": "0.0.0-alpha.25",
+ "@push-based/nx-verdaccio": "0.0.0-alpha.26",
"@swc-node/register": "^1.10.9",
"@swc/cli": "~0.1.62",
"@swc/core": "^1.3.99",