Skip to content

Commit

Permalink
feat(plugin-coverage): allow passing results as strings
Browse files Browse the repository at this point in the history
  • Loading branch information
Tlacenka committed Feb 14, 2024
1 parent b3c6a3d commit 6813021
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 47 deletions.
7 changes: 1 addition & 6 deletions e2e/cli-e2e/mocks/fixtures/code-pushup.config.coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ export default {
],
plugins: [
await coveragePlugin({
reports: [
{
resultsPath: join('e2e', 'cli-e2e', 'mocks', 'fixtures', 'lcov.info'),
pathToProject: join('packages', 'cli'),
},
],
reports: [join('e2e', 'cli-e2e', 'mocks', 'fixtures', 'lcov.info')],
}),
],
} satisfies CoreConfig;
16 changes: 8 additions & 8 deletions e2e/cli-e2e/tests/__snapshots__/collect.e2e.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "Function formatReportScore is not called in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/partly-covered/utils.ts",
"file": "src/lib/partly-covered/utils.ts",
"position": {
"startLine": 2,
},
Expand All @@ -38,7 +38,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "Function sortReport is not called in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/not-covered/sorting.ts",
"file": "src/lib/not-covered/sorting.ts",
"position": {
"startLine": 1,
},
Expand All @@ -60,7 +60,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "2nd branch is not taken in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/partly-covered/utils.ts",
"file": "src/lib/partly-covered/utils.ts",
"position": {
"startLine": 6,
},
Expand All @@ -70,7 +70,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "2nd branch is not taken in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/partly-covered/utils.ts",
"file": "src/lib/partly-covered/utils.ts",
"position": {
"startLine": 10,
},
Expand All @@ -80,7 +80,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "1st branch is not taken in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/not-covered/sorting.ts",
"file": "src/lib/not-covered/sorting.ts",
"position": {
"startLine": 7,
},
Expand All @@ -90,7 +90,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "2nd branch is not taken in any test case.",
"severity": "error",
"source": {
"file": "packages/cli/src/lib/not-covered/sorting.ts",
"file": "src/lib/not-covered/sorting.ts",
"position": {
"startLine": 7,
},
Expand All @@ -112,7 +112,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "Lines 7-9 are not covered in any test case.",
"severity": "warning",
"source": {
"file": "packages/cli/src/lib/partly-covered/utils.ts",
"file": "src/lib/partly-covered/utils.ts",
"position": {
"endLine": 9,
"startLine": 7,
Expand All @@ -123,7 +123,7 @@ exports[`CLI collect > should run Code coverage plugin and create report.json 1`
"message": "Lines 1-5 are not covered in any test case.",
"severity": "warning",
"source": {
"file": "packages/cli/src/lib/not-covered/sorting.ts",
"file": "src/lib/not-covered/sorting.ts",
"position": {
"endLine": 5,
"startLine": 1,
Expand Down
7 changes: 4 additions & 3 deletions packages/plugin-coverage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Measured coverage types are mapped to Code PushUp audits in the following way
plugins: [
// ...
await coveragePlugin({
reports: [{ resultsPath: 'coverage/lcov.info' }],
reports: ['coverage/lcov.info'],
coverageToolCommand: {
command: 'npx',
args: ['jest', '--coverage', '--coverageReporters=lcov'],
Expand Down Expand Up @@ -119,8 +119,9 @@ It recognises the following entities:
The plugin accepts the following parameters:

- `coverageTypes`: An array of types of coverage that you wish to track. Supported values: `function`, `branch`, `line`. Defaults to all available types.
- `reports`: Array of information about files with code coverage results - paths to results, path to project root the results belong to. LCOV format is supported for now.
- If you have an Nx monorepo, you can adjust our helper function `getNxCoveragePaths` to get the path information automatically.
- `reports`: Array of information about files with code coverage results. LCOV format is supported for now.
- For a single project, providing paths to results as strings is enough.
- If you have a monorepo, both path to results (`resultsPath`) and path from the root to project the results belong to (`pathToProject`) need to be provided for the LCOV format. For Nx monorepos, you can use our helper function `getNxCoveragePaths` to get the path information automatically.
- (optional) `coverageToolCommand`: If you wish to run your coverage tool to generate the results first, you may define it here.
- (optional) `perfectScoreThreshold`: If your coverage goal is not 100%, you may define it here in range 0-1. Any score above the defined threshold will be given the perfect score. The value will stay unaffected.

Expand Down
25 changes: 18 additions & 7 deletions packages/plugin-coverage/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,26 @@ import { z } from 'zod';
export const coverageTypeSchema = z.enum(['function', 'branch', 'line']);
export type CoverageType = z.infer<typeof coverageTypeSchema>;

export const coverageResultSchema = z.object({
resultsPath: z.string().includes('lcov'),
pathToProject: z
export const coverageResultSchema = z.union([
z.object({
resultsPath: z
.string({
description: 'Path to coverage results for Nx setup.',
})
.includes('lcov'),
pathToProject: z
.string({
description:
'Path from workspace root to project root. Necessary for LCOV reports which provide a relative path.',
})
.optional(),
}),
z
.string({
description:
'Path from workspace root to project root. Necessary for LCOV reports.',
description: 'Path to coverage results for a single project setup.',
})
.optional(),
});
.includes('lcov'),
]);
export type CoverageResult = z.infer<typeof coverageResultSchema>;

export const coveragePluginConfigSchema = z.object({
Expand Down
10 changes: 5 additions & 5 deletions packages/plugin-coverage/src/lib/config.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ describe('coveragePluginConfigSchema', () => {
it('accepts a minimal code coverage configuration', () => {
expect(() =>
coveragePluginConfigSchema.parse({
reports: [{ resultsPath: 'coverage/cli/lcov.info' }],
reports: ['coverage/cli/lcov.info'],
} satisfies CoveragePluginConfig),
).not.toThrow();
});

it('replaces undefined coverage with all available types', () => {
const config = {
reports: [{ resultsPath: 'coverage/cli/lcov.info' }],
reports: ['coverage/cli/lcov.info'],
} satisfies CoveragePluginConfig;
expect(() => coveragePluginConfigSchema.parse(config)).not.toThrow();

Expand All @@ -51,7 +51,7 @@ describe('coveragePluginConfigSchema', () => {
expect(() =>
coveragePluginConfigSchema.parse({
coverageTypes: [],
reports: [{ resultsPath: 'coverage/cli/lcov.info' }],
reports: ['coverage/cli/lcov.info'],
} satisfies CoveragePluginConfig),
).toThrow('too_small');
});
Expand All @@ -69,7 +69,7 @@ describe('coveragePluginConfigSchema', () => {
expect(() =>
coveragePluginConfigSchema.parse({
coverageTypes: ['line'],
reports: [{ resultsPath: 'coverage/cli/coverage-final.json' }],
reports: ['coverage/cli/coverage-final.json'],
} satisfies CoveragePluginConfig),
).toThrow(/Invalid input: must include.+lcov/);
});
Expand All @@ -90,7 +90,7 @@ describe('coveragePluginConfigSchema', () => {
expect(() =>
coveragePluginConfigSchema.parse({
coverageTypes: ['line'],
reports: [{ resultsPath: 'coverage/cli/lcov.info' }],
reports: ['coverage/cli/lcov.info'],
perfectScoreThreshold: 1.1,
} satisfies CoveragePluginConfig),
).toThrow('too_big');
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-coverage/src/lib/coverage-plugin.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('coveragePlugin', () => {
await expect(
coveragePlugin({
coverageTypes: ['function'],
reports: [{ resultsPath: LCOV_PATH }],
reports: [LCOV_PATH],
}),
).resolves.toStrictEqual(
expect.objectContaining({
Expand All @@ -39,7 +39,7 @@ describe('coveragePlugin', () => {
await expect(
coveragePlugin({
coverageTypes: ['function', 'branch'],
reports: [{ resultsPath: LCOV_PATH }],
reports: [LCOV_PATH],
}),
).resolves.toStrictEqual(
expect.objectContaining({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`lcovResultsToAuditOutputs > should correctly convert lcov results to AuditOutputs 1`] = `
exports[`lcovResultsToAuditOutputs > should correctly convert lcov results to AuditOutputs and prepend project paths 1`] = `
[
{
"details": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { describe, it } from 'vitest';
import { lcovResultsToAuditOutputs } from './lcov-runner';

describe('lcovResultsToAuditOutputs', () => {
it('should correctly convert lcov results to AuditOutputs', async () => {
it('should correctly convert lcov results to AuditOutputs and prepend project paths', async () => {
/**
* The stats passed in the fixture are as follows
* Functions: 2 found, 2 covered (100% coverage)
Expand Down
6 changes: 4 additions & 2 deletions packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ async function parseLcovFiles(
): Promise<LCOVRecord[]> {
const parsedResults = await Promise.all(
results.map(async result => {
const lcovFileContent = await readTextFile(result.resultsPath);
const resultsPath =
typeof result === 'string' ? result : result.resultsPath;
const lcovFileContent = await readTextFile(resultsPath);
const parsedRecords = parseLcov(toUnixNewlines(lcovFileContent));
return parsedRecords.map<LCOVRecord>(record => ({
...record,
file:
result.pathToProject == null
typeof result === 'string' || result.pathToProject == null
? record.file
: join(result.pathToProject, record.file),
}));
Expand Down
22 changes: 10 additions & 12 deletions packages/plugin-coverage/src/lib/runner/runner.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { PLUGIN_CONFIG_PATH, RUNNER_OUTPUT_PATH, WORKDIR } from './constants';
describe('createRunnerConfig', () => {
it('should create a valid runner config', async () => {
const runnerConfig = await createRunnerConfig('executeRunner.ts', {
reports: [{ resultsPath: 'coverage/lcov.info' }],
reports: ['coverage/lcov.info'],
coverageTypes: ['branch'],
perfectScoreThreshold: 85,
});
Expand All @@ -28,7 +28,7 @@ describe('createRunnerConfig', () => {

const pluginConfig: FinalCoveragePluginConfig = {
coverageTypes: ['line'],
reports: [{ resultsPath: 'coverage/lcov.info' }],
reports: ['coverage/lcov.info'],
coverageToolCommand: { command: 'npm', args: ['run', 'test'] },
perfectScoreThreshold: 85,
};
Expand All @@ -46,16 +46,14 @@ describe('executeRunner', () => {
it('should successfully execute runner', async () => {
const config: FinalCoveragePluginConfig = {
reports: [
{
resultsPath: join(
fileURLToPath(dirname(import.meta.url)),
'..',
'..',
'..',
'mocks',
'single-record-lcov.info',
),
},
join(
fileURLToPath(dirname(import.meta.url)),
'..',
'..',
'..',
'mocks',
'single-record-lcov.info',
),
],
coverageTypes: ['line'],
};
Expand Down

0 comments on commit 6813021

Please sign in to comment.