UNPKG

@code-pushup/coverage-plugin

Version:
94 lines 4.63 kB
import { bold } from 'ansis'; import path from 'node:path'; import { importModule, ui } from '@code-pushup/utils'; /** * @param targets nx targets to be used for measuring coverage, test by default * @returns An array of coverage result information for the coverage plugin. */ export async function getNxCoveragePaths(targets = ['test'], verbose) { if (verbose) { ui().logger.info(bold('💡 Gathering coverage from the following nx projects:')); } const { createProjectGraphAsync } = await import('@nx/devkit'); const { nodes } = await createProjectGraphAsync({ exitOnError: false }); const coverageResults = await Promise.all(targets.map(async (target) => { const relevantNodes = Object.values(nodes).filter(graph => hasNxTarget(graph, target)); return await Promise.all(relevantNodes.map(async ({ name, data }) => { const coveragePaths = await getCoveragePathsForTarget(data, target); if (verbose) { ui().logger.info(`- ${name}: ${target}`); } return coveragePaths; })); })); if (verbose) { ui().logger.info('\n'); } return coverageResults.flat(); } function hasNxTarget(project, target) { return project.data.targets != null && target in project.data.targets; } export async function getCoveragePathsForTarget(project, target) { const targetConfig = project.targets?.[target]; if (!targetConfig) { throw new Error(`No configuration found for target ${target} in project ${project.name}`); } if (targetConfig.executor?.includes('@nx/vite')) { return getCoveragePathForVitest(targetConfig.options, project, target); } if (targetConfig.executor?.includes('@nx/jest')) { return getCoveragePathForJest(targetConfig.options, project, target); } throw new Error(`Unsupported executor ${targetConfig.executor}. Only @nx/vite and @nx/jest are currently supported.`); } export async function getCoveragePathForVitest(options, project, target) { const { default: { normalizeViteConfigFilePathWithTree }, } = await import('@nx/vite'); const config = normalizeViteConfigFilePathWithTree( // HACK: only tree.exists is called, so injecting existSync from node:fs instead // eslint-disable-next-line @typescript-eslint/consistent-type-assertions { exists: (await import('node:fs')).existsSync }, project.root, options.configFile); if (!config) { throw new Error(`Could not find Vitest config file for target ${target} in project ${project.name}`); } const vitestConfig = await importModule({ filepath: config, format: 'esm', }); const reportsDirectory = options.reportsDirectory ?? vitestConfig.test.coverage?.reportsDirectory; const reporter = vitestConfig.test.coverage?.reporter; if (reportsDirectory == null) { throw new Error(`Vitest coverage configuration at ${config} does not include coverage path for target ${target} in project ${project.name}. Add the path under coverage > reportsDirectory.`); } if (!reporter?.some(format => format === 'lcov' || format === 'lcovonly')) { throw new Error(`Vitest coverage configuration at ${config} does not include LCOV report format for target ${target} in project ${project.name}. Add 'lcov' format under coverage > reporter.`); } if (path.isAbsolute(reportsDirectory)) { return path.join(reportsDirectory, 'lcov.info'); } return { pathToProject: project.root, resultsPath: path.join(project.root, reportsDirectory, 'lcov.info'), }; } export async function getCoveragePathForJest(options, project, target) { const { jestConfig } = options; const testConfig = await importModule({ filepath: jestConfig, }); const { coverageDirectory, coverageReporters } = { ...testConfig, ...options, }; if (coverageDirectory == null) { throw new Error(`Jest coverage configuration at ${jestConfig} does not include coverage path for target ${target} in ${project.name}. Add the path under coverageDirectory.`); } if (!coverageReporters?.includes('lcov') && !('preset' in testConfig)) { throw new Error(`Jest coverage configuration at ${jestConfig} does not include LCOV report format for target ${target} in ${project.name}. Add 'lcov' format under coverageReporters.`); } if (path.isAbsolute(coverageDirectory)) { return path.join(coverageDirectory, 'lcov.info'); } return path.join(project.root, coverageDirectory, 'lcov.info'); } //# sourceMappingURL=coverage-paths.js.map