Skip to content

Commit 23f1ce5

Browse files
committed
feat(plugin-coverage): do not halt plugin execution on fail
1 parent 2cb815b commit 23f1ce5

File tree

4 files changed

+45
-37
lines changed

4 files changed

+45
-37
lines changed

packages/plugin-coverage/src/lib/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ export const coveragePluginConfigSchema = z.object({
3838
.optional(),
3939
})
4040
.optional(),
41+
continueOnCommandFail: z
42+
.boolean({
43+
description:
44+
'Continue on coverage tool command failure or error. Defaults to true.',
45+
})
46+
.default(true),
4147
coverageTypes: z
4248
.array(coverageTypeSchema, {
4349
description: 'Coverage types measured. Defaults to all available types.',

packages/plugin-coverage/src/lib/runner/index.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export async function executeRunner({
2424
runnerConfigPath,
2525
runnerOutputPath,
2626
}: RunnerFilesPaths): Promise<void> {
27-
const { reports, coverageToolCommand, coverageTypes } =
27+
const { reports, coverageToolCommand, continueOnCommandFail, coverageTypes } =
2828
await readJsonFile<FinalCoveragePluginConfig>(runnerConfigPath);
2929

3030
// Run coverage tool if provided
@@ -34,15 +34,20 @@ export async function executeRunner({
3434
await executeProcess({ command, args });
3535
} catch (error) {
3636
if (error instanceof ProcessError) {
37-
ui().logger.error(bold('stdout from failed coverage tool process:'));
38-
ui().logger.error(error.stdout);
39-
ui().logger.error(bold('stderr from failed coverage tool process:'));
40-
ui().logger.error(error.stderr);
37+
const loggingFn = continueOnCommandFail
38+
? ui().logger.warning.bind(ui().logger)
39+
: ui().logger.error.bind(ui().logger);
40+
loggingFn(bold('stdout from failed coverage tool process:'));
41+
loggingFn(error.stdout);
42+
loggingFn(bold('stderr from failed coverage tool process:'));
43+
loggingFn(error.stderr);
4144
}
4245

43-
throw new Error(
44-
'Coverage plugin: Running coverage tool failed. Make sure all your provided tests are passing.',
45-
);
46+
if (!continueOnCommandFail) {
47+
throw new Error(
48+
'Coverage plugin: Running coverage tool failed. Make sure all your provided tests are passing.',
49+
);
50+
}
4651
}
4752
}
4853

packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,37 +55,34 @@ export async function lcovResultsToAuditOutputs(
5555
export async function parseLcovFiles(
5656
results: CoverageResult[],
5757
): Promise<LCOVRecord[]> {
58-
const parsedResults = await Promise.all(
59-
results.map(async result => {
60-
const resultsPath =
61-
typeof result === 'string' ? result : result.resultsPath;
62-
const lcovFileContent = await readTextFile(resultsPath);
63-
if (lcovFileContent.trim() === '') {
64-
ui().logger.warning(
65-
`Coverage plugin: Empty lcov report file detected at ${resultsPath}.`,
66-
);
67-
}
68-
const parsedRecords = parseLcov(toUnixNewlines(lcovFileContent));
69-
return parsedRecords.map<LCOVRecord>(record => ({
70-
...record,
71-
file:
72-
typeof result === 'string' || result.pathToProject == null
73-
? record.file
74-
: path.join(result.pathToProject, record.file),
75-
}));
76-
}),
77-
);
78-
if (parsedResults.length !== results.length) {
79-
throw new Error('Some provided LCOV results were not valid.');
80-
}
81-
82-
const flatResults = parsedResults.flat();
58+
const parsedResults = (
59+
await Promise.all(
60+
results.map(async result => {
61+
const resultsPath =
62+
typeof result === 'string' ? result : result.resultsPath;
63+
const lcovFileContent = await readTextFile(resultsPath);
64+
if (lcovFileContent.trim() === '') {
65+
ui().logger.warning(
66+
`Coverage plugin: Empty lcov report file detected at ${resultsPath}.`,
67+
);
68+
}
69+
const parsedRecords = parseLcov(toUnixNewlines(lcovFileContent));
70+
return parsedRecords.map<LCOVRecord>(record => ({
71+
...record,
72+
file:
73+
typeof result === 'string' || result.pathToProject == null
74+
? record.file
75+
: path.join(result.pathToProject, record.file),
76+
}));
77+
}),
78+
)
79+
).flat();
8380

84-
if (flatResults.length === 0) {
85-
throw new Error('All provided results are empty.');
81+
if (parsedResults.length === 0) {
82+
throw new Error('All provided coverage results are empty.');
8683
}
8784

88-
return flatResults;
85+
return parsedResults;
8986
}
9087

9188
/**

packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ end_of_record
8989
it('should throw for only empty reports', async () => {
9090
await expect(() =>
9191
parseLcovFiles([path.join('coverage', 'lcov.info')]),
92-
).rejects.toThrow('All provided results are empty.');
92+
).rejects.toThrow('All provided coverage results are empty.');
9393
});
9494

9595
it('should warn about an empty lcov file', async () => {

0 commit comments

Comments
 (0)