From 1209ed209db6c652c1c52b6fa0b3f64f14f6503b Mon Sep 17 00:00:00 2001 From: AS Date: Sun, 27 Jul 2025 10:54:57 +0300 Subject: [PATCH 01/17] feat: add artifaction options to plugin-eslint --- packages/models/src/index.ts | 1 + packages/plugin-eslint/src/lib/config.ts | 2 + .../src/lib/eslint-plugin.int.test.ts | 26 +++++++++ .../plugin-eslint/src/lib/eslint-plugin.ts | 13 ++++- .../plugin-eslint/src/lib/runner/index.ts | 57 ++++++++++++++++--- 5 files changed, 87 insertions(+), 12 deletions(-) diff --git a/packages/models/src/index.ts b/packages/models/src/index.ts index 91c22fb10..eac353271 100644 --- a/packages/models/src/index.ts +++ b/packages/models/src/index.ts @@ -138,3 +138,4 @@ export { artifactGenerationCommandSchema, pluginArtifactOptionsSchema, } from './lib/configuration.js'; +export type { PluginArtifactOptions } from './lib/configuration.js'; diff --git a/packages/plugin-eslint/src/lib/config.ts b/packages/plugin-eslint/src/lib/config.ts index 4a3133d2c..2d4006205 100644 --- a/packages/plugin-eslint/src/lib/config.ts +++ b/packages/plugin-eslint/src/lib/config.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { pluginArtifactOptionsSchema } from '@code-pushup/models'; import { toArray } from '@code-pushup/utils'; const patternsSchema = z.union([z.string(), z.array(z.string()).min(1)], { @@ -64,5 +65,6 @@ export type CustomGroup = z.infer; export const eslintPluginOptionsSchema = z.object({ groups: z.array(customGroupSchema).optional(), + artifacts: pluginArtifactOptionsSchema.optional(), }); export type ESLintPluginOptions = z.infer; diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts index 245611811..4a466d7fc 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts @@ -160,4 +160,30 @@ describe('eslintPlugin', () => { eslintPlugin({ eslintrc: '.eslintrc.yml', patterns: '**/*.js' }), ).rejects.toThrow(/Failed to load url .*\.eslintrc.yml/); }); + + it('should initialize with artifact options', async () => { + cwdSpy.mockReturnValue(path.join(fixturesDir, 'todos-app')); + const plugin = await eslintPlugin( + { + eslintrc: 'eslint.config.js', + patterns: ['src/**/*.js'], + }, + { + artifacts: { + artifactsPaths: './artifacts/eslint-output.json', + generateArtifactsCommand: 'echo "Generating artifacts"', + }, + }, + ); + + expect(typeof plugin.runner).toBe('object'); + const runnerConfig = plugin.runner as { + command: string; + args?: string[]; + outputFile: string; + }; + expect(runnerConfig.command).toBe('node'); + expect(runnerConfig.args).toContain('echo "Generating artifacts"'); + expect(runnerConfig.outputFile).toBe('./artifacts/eslint-output.json'); + }); }); diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.ts b/packages/plugin-eslint/src/lib/eslint-plugin.ts index 285a39e50..7f4513557 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.ts @@ -41,12 +41,14 @@ export async function eslintPlugin( schemaType: 'ESLint plugin config', }); - const customGroups = options + const parsedOptions = options ? parseSchema(eslintPluginOptionsSchema, options, { schemaType: 'ESLint plugin options', - }).groups + }) : undefined; + const customGroups = parsedOptions?.groups; + const { audits, groups } = await listAuditsAndGroups(targets, customGroups); const runnerScriptPath = path.join( @@ -71,6 +73,11 @@ export async function eslintPlugin( audits, groups, - runner: await createRunnerConfig(runnerScriptPath, audits, targets), + runner: await createRunnerConfig( + runnerScriptPath, + audits, + targets, + parsedOptions?.artifacts, + ), }; } diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index 7e5e8ee9d..ebe0f1a6f 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -3,9 +3,11 @@ import path from 'node:path'; import type { Audit, AuditOutput, + PluginArtifactOptions, RunnerConfig, RunnerFilesPaths, } from '@code-pushup/models'; +import { pluginArtifactOptionsSchema } from '@code-pushup/models'; import { asyncSequential, createRunnerFiles, @@ -51,23 +53,60 @@ export async function createRunnerConfig( scriptPath: string, audits: Audit[], targets: ESLintTarget[], + artifactOptions?: PluginArtifactOptions, ): Promise { + const parsedOptions = artifactOptions + ? pluginArtifactOptionsSchema.parse(artifactOptions) + : undefined; + const config: ESLintPluginRunnerConfig = { targets, - slugs: audits.map(audit => audit.slug), + slugs: audits.map(a => a.slug), }; - const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles( - 'eslint', - JSON.stringify(config), - ); + + const { runnerConfigPath, runnerOutputPath } = parsedOptions + ? await createCustomRunnerPaths(parsedOptions, config) + : await createRunnerFiles('eslint', JSON.stringify(config)); + + const args = [ + filePathToCliArg(scriptPath), + ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), + ...resolveCommandArgs(parsedOptions?.generateArtifactsCommand), + ]; return { command: 'node', - args: [ - filePathToCliArg(scriptPath), - ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), - ], + args, configFile: runnerConfigPath, outputFile: runnerOutputPath, }; } + +async function createCustomRunnerPaths( + options: PluginArtifactOptions, + config: ESLintPluginRunnerConfig, +): Promise { + const artifactPaths = Array.isArray(options.artifactsPaths) + ? options.artifactsPaths + : [options.artifactsPaths]; + + const runnerOutputPath = artifactPaths[0] ?? ''; + const runnerConfigPath = path.join( + path.dirname(runnerOutputPath), + 'plugin-config.json', + ); + + await ensureDirectoryExists(path.dirname(runnerConfigPath)); + await writeFile(runnerConfigPath, JSON.stringify(config)); + + return { runnerConfigPath, runnerOutputPath }; +} + +function resolveCommandArgs( + command?: string | { command: string; args?: string[] }, +): string[] { + if (!command) return []; + return typeof command === 'string' + ? [command] + : [command.command, ...(command.args ?? [])]; +} From 687badaf1e123f4f07f52581f8b3e36855d0cc14 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Wed, 27 Aug 2025 18:42:07 +0200 Subject: [PATCH 02/17] feat(plugin-eslint): use artifacts options --- .../src/lib/eslint-plugin.int.test.ts | 12 +- .../plugin-eslint/src/lib/eslint-plugin.ts | 23 +--- .../plugin-eslint/src/lib/runner/index.ts | 106 +++++++----------- .../src/lib/runner/index.unit.test.ts | 32 +++++- 4 files changed, 74 insertions(+), 99 deletions(-) diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts index 2be608294..3e6fbcbbb 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts @@ -152,7 +152,7 @@ describe('eslintPlugin', () => { await expect( // @ts-expect-error simulating invalid non-TS config eslintPlugin({ eslintrc: '.eslintrc.json' }), - ).rejects.toThrow('Invalid input'); + ).rejects.toThrow('Failed parsing ESLint plugin config'); }); it("should throw if eslintrc file doesn't exist", async () => { @@ -176,14 +176,6 @@ describe('eslintPlugin', () => { }, ); - expect(typeof plugin.runner).toBe('object'); - const runnerConfig = plugin.runner as { - command: string; - args?: string[]; - outputFile: string; - }; - expect(runnerConfig.command).toBe('node'); - expect(runnerConfig.args).toContain('echo "Generating artifacts"'); - expect(runnerConfig.outputFile).toBe('./artifacts/eslint-output.json'); + expect(typeof plugin.runner).toBe('function'); }); }); diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.ts b/packages/plugin-eslint/src/lib/eslint-plugin.ts index 19001c75b..49f6ea228 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.ts @@ -1,6 +1,4 @@ import { createRequire } from 'node:module'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import type { PluginConfig } from '@code-pushup/models'; import { parseSchema } from '@code-pushup/utils'; import { @@ -11,7 +9,7 @@ import { } from './config.js'; import { ESLINT_PLUGIN_SLUG } from './constants.js'; import { listAuditsAndGroups } from './meta/index.js'; -import { createRunnerConfig } from './runner/index.js'; +import { createRunnerFunction } from './runner/index.js'; /** * Instantiates Code PushUp ESLint plugin for use in core config. @@ -42,22 +40,14 @@ export async function eslintPlugin( schemaType: 'ESLint plugin config', }); - const parsedOptions = options + const { groups: customGroups, artifacts } = options ? parseSchema(eslintPluginOptionsSchema, options, { schemaType: 'ESLint plugin options', }) - : undefined; - - const customGroups = parsedOptions?.groups; + : {}; const { audits, groups } = await listAuditsAndGroups(targets, customGroups); - const runnerScriptPath = path.join( - fileURLToPath(path.dirname(import.meta.url)), - '..', - 'bin.js', - ); - const packageJson = createRequire(import.meta.url)( '../../package.json', ) as typeof import('../../package.json'); @@ -74,11 +64,10 @@ export async function eslintPlugin( audits, groups, - runner: await createRunnerConfig( - runnerScriptPath, + runner: await createRunnerFunction({ audits, targets, - parsedOptions?.artifacts, - ), + ...(artifacts ? { artifacts } : {}), + }), }; } diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index 6fa36ab2f..8daa7b0bd 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -4,11 +4,12 @@ import type { Audit, AuditOutput, AuditOutputs, + PersistConfig, PluginArtifactOptions, RunnerConfig, RunnerFilesPaths, + RunnerFunction, } from '@code-pushup/models'; -import { pluginArtifactOptionsSchema } from '@code-pushup/models'; import { asyncSequential, createRunnerFiles, @@ -55,91 +56,62 @@ export async function createRunnerConfig( scriptPath: string, audits: Audit[], targets: ESLintTarget[], - artifactOptions?: PluginArtifactOptions, ): Promise { - const parsedOptions = artifactOptions - ? pluginArtifactOptionsSchema.parse(artifactOptions) - : undefined; - const config: ESLintPluginRunnerConfig = { targets, - slugs: audits.map(a => a.slug), + slugs: audits.map(audit => audit.slug), }; - - const { runnerConfigPath, runnerOutputPath } = parsedOptions - ? await createCustomRunnerPaths(parsedOptions, config) - : await createRunnerFiles('eslint', JSON.stringify(config)); - - const args = [ - filePathToCliArg(scriptPath), - ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), - ...resolveCommandArgs(parsedOptions?.generateArtifactsCommand), - ]; + const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles( + 'eslint', + JSON.stringify(config), + ); return { command: 'node', - args, + args: [ + filePathToCliArg(scriptPath), + ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), + ], configFile: runnerConfigPath, outputFile: runnerOutputPath, }; } -export async function generateAuditOutputs(options: { +export function createRunnerFunction(options: { audits: Audit[]; targets: ESLintTarget[]; artifacts?: PluginArtifactOptions; -}): Promise { +}): RunnerFunction { const { audits, targets, artifacts } = options; const config: ESLintPluginRunnerConfig = { targets, slugs: audits.map(audit => audit.slug), }; - ui().logger.log(`ESLint plugin executing ${targets.length} lint targets`); - - const linterOutputs = artifacts - ? await loadArtifacts(artifacts) - : await asyncSequential(targets, lint); - const lintResults = mergeLinterOutputs(linterOutputs); - const failedAudits = lintResultsToAudits(lintResults); - - return config.slugs.map( - (slug): AuditOutput => - failedAudits.find(audit => audit.slug === slug) ?? { - slug, - score: 1, - value: 0, - displayValue: 'passed', - details: { issues: [] }, - }, - ); -} - -async function createCustomRunnerPaths( - options: PluginArtifactOptions, - config: ESLintPluginRunnerConfig, -): Promise { - const artifactPaths = Array.isArray(options.artifactsPaths) - ? options.artifactsPaths - : [options.artifactsPaths]; - - const runnerOutputPath = artifactPaths[0] ?? ''; - const runnerConfigPath = path.join( - path.dirname(runnerOutputPath), - 'plugin-config.json', - ); - - await ensureDirectoryExists(path.dirname(runnerConfigPath)); - await writeFile(runnerConfigPath, JSON.stringify(config)); - - return { runnerConfigPath, runnerOutputPath }; -} - -function resolveCommandArgs( - command?: string | { command: string; args?: string[] }, -): string[] { - if (!command) return []; - return typeof command === 'string' - ? [command] - : [command.command, ...(command.args ?? [])]; + return async ({ outputDir }: PersistConfig): Promise => { + ui().logger.log(`ESLint plugin executing ${targets.length} lint targets`); + + const linterOutputs = artifacts + ? await loadArtifacts(artifacts) + : await asyncSequential( + targets.map(target => ({ + ...target, + outputDir, + })), + lint, + ); + const lintResults = mergeLinterOutputs(linterOutputs); + const failedAudits = lintResultsToAudits(lintResults); + + return config.slugs.map( + (slug): AuditOutput => + failedAudits.find(audit => audit.slug === slug) ?? { + slug, + score: 1, + value: 0, + displayValue: 'passed', + details: { issues: [] }, + }, + ); + }; } diff --git a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts index 07e12f5c1..76275ffe2 100644 --- a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts @@ -7,12 +7,33 @@ import type { } from '@code-pushup/models'; import { ui } from '@code-pushup/utils'; import type { ESLintTarget } from '../config.js'; -import { generateAuditOutputs } from './index.js'; +import { createRunnerFunction } from './index.js'; import * as lintModule from './lint.js'; import type { LinterOutput } from './types.js'; import * as utilsFileModule from './utils.js'; -describe('generateAuditOutputs', () => { +describe('call createRunnerFunction', () => { + it('should create runnerFunction correctly', () => { + expect( + createRunnerFunction({ + audits: [ + { slug: 'max-lines', title: 'Max lines', description: 'Test' }, + { + slug: 'no-unused-vars', + title: 'No unused vars', + description: 'Test', + }, + ], + targets: [{ patterns: ['src/**/*.ts'] }], + artifacts: { + artifactsPaths: ['path/to/artifacts.json'], + }, + }), + ).toStrictEqual(expect.any(Function)); + }); +}); + +describe('execute created runnerFunction', () => { const loadArtifactsSpy = vi.spyOn(utilsFileModule, 'loadArtifacts'); const lintSpy = vi.spyOn(lintModule, 'lint'); @@ -120,11 +141,11 @@ describe('generateAuditOutputs', () => { loadArtifactsSpy.mockResolvedValue(mockLinterOutputs); await expect( - generateAuditOutputs({ + createRunnerFunction({ audits: mockAudits, targets: mockTargets, artifacts, - }), + })({}), ).resolves.toStrictEqual(mockedAuditOutputs); expect(loadArtifactsSpy).toHaveBeenCalledWith(artifacts); @@ -137,9 +158,10 @@ describe('generateAuditOutputs', () => { lintSpy.mockResolvedValueOnce(mockLinterOutputs.at(0)!); await expect( - generateAuditOutputs({ + createRunnerFunction({ audits: mockAudits, targets: mockTargets, + })({ outputDir: 'custom-output', }), ).resolves.toStrictEqual(mockedAuditOutputs); From a1732d4f00c64edd185386d08631cda49c615d5d Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Wed, 27 Aug 2025 18:59:23 +0200 Subject: [PATCH 03/17] refactor(plugin-eslint): fix int tests --- .../eslint-plugin.int.test.ts.snap | 11 +------- .../src/lib/eslint-plugin.int.test.ts | 26 ++----------------- 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.int.test.ts.snap b/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.int.test.ts.snap index 388229cba..957e81e7b 100644 --- a/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.int.test.ts.snap +++ b/packages/plugin-eslint/src/lib/__snapshots__/eslint-plugin.int.test.ts.snap @@ -346,16 +346,7 @@ exports[`eslintPlugin > should initialize ESLint plugin for React application 1` ], "icon": "eslint", "packageName": "@code-pushup/eslint-plugin", - "runner": { - "args": [ - ""/bin.js"", - "--runnerConfigPath="node_modules/.code-pushup/eslint//plugin-config.json"", - "--runnerOutputPath="node_modules/.code-pushup/eslint//runner-output.json"", - ], - "command": "node", - "configFile": "node_modules/.code-pushup/eslint//plugin-config.json", - "outputFile": "node_modules/.code-pushup/eslint//runner-output.json", - }, + "runner": [Function], "slug": "eslint", "title": "ESLint", "version": Any, diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts index 3e6fbcbbb..2fce6fa8f 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts @@ -3,8 +3,7 @@ import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import type { MockInstance } from 'vitest'; -import type { Audit, PluginConfig, RunnerConfig } from '@code-pushup/models'; -import { toUnixPath } from '@code-pushup/utils'; +import type { Audit } from '@code-pushup/models'; import { eslintPlugin } from './eslint-plugin.js'; describe('eslintPlugin', () => { @@ -15,27 +14,6 @@ describe('eslintPlugin', () => { let cwdSpy: MockInstance<[], string>; let platformSpy: MockInstance<[], NodeJS.Platform>; - const replaceAbsolutePath = (plugin: PluginConfig): PluginConfig => ({ - ...plugin, - runner: { - ...(plugin.runner as RunnerConfig), - args: (plugin.runner as RunnerConfig).args?.map(arg => - toUnixPath(arg.replace(path.dirname(thisDir), '')).replace( - /\/eslint\/\d+\//, - '/eslint//', - ), - ), - ...((plugin.runner as RunnerConfig).configFile && { - configFile: toUnixPath( - (plugin.runner as RunnerConfig).configFile!, - ).replace(/\/eslint\/\d+\//, '/eslint//'), - }), - outputFile: toUnixPath( - (plugin.runner as RunnerConfig).outputFile, - ).replace(/\/eslint\/\d+\//, '/eslint//'), - }, - }); - beforeAll(() => { cwdSpy = vi.spyOn(process, 'cwd'); // Linux produces extra quotation marks for globs @@ -55,7 +33,7 @@ describe('eslintPlugin', () => { patterns: ['src/**/*.js', 'src/**/*.jsx'], }); - expect(replaceAbsolutePath(plugin)).toMatchSnapshot({ + expect(plugin).toMatchSnapshot({ version: expect.any(String), }); }); From 5d24b82740239899061ee5ee9b74533f6bee762e Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 16:42:20 +0200 Subject: [PATCH 04/17] refactor: remove unused code --- packages/plugin-eslint/src/bin.ts | 7 -- .../plugin-eslint/src/lib/runner/index.ts | 67 +------------------ 2 files changed, 1 insertion(+), 73 deletions(-) delete mode 100644 packages/plugin-eslint/src/bin.ts diff --git a/packages/plugin-eslint/src/bin.ts b/packages/plugin-eslint/src/bin.ts deleted file mode 100644 index fc625dd73..000000000 --- a/packages/plugin-eslint/src/bin.ts +++ /dev/null @@ -1,7 +0,0 @@ -import process from 'node:process'; -import { Parser } from 'yargs/helpers'; -import { executeRunner } from './lib/runner/index.js'; - -const { runnerConfigPath, runnerOutputPath } = Parser(process.argv); - -await executeRunner({ runnerConfigPath, runnerOutputPath }); diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index 8daa7b0bd..a633c932c 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -1,82 +1,17 @@ -import { writeFile } from 'node:fs/promises'; -import path from 'node:path'; import type { Audit, AuditOutput, AuditOutputs, PersistConfig, PluginArtifactOptions, - RunnerConfig, - RunnerFilesPaths, RunnerFunction, } from '@code-pushup/models'; -import { - asyncSequential, - createRunnerFiles, - ensureDirectoryExists, - filePathToCliArg, - objectToCliArgs, - readJsonFile, - ui, -} from '@code-pushup/utils'; +import { asyncSequential, ui } from '@code-pushup/utils'; import type { ESLintPluginRunnerConfig, ESLintTarget } from '../config.js'; import { lint } from './lint.js'; import { lintResultsToAudits, mergeLinterOutputs } from './transform.js'; import { loadArtifacts } from './utils.js'; -export async function executeRunner({ - runnerConfigPath, - runnerOutputPath, -}: RunnerFilesPaths): Promise { - const { slugs, targets } = - await readJsonFile(runnerConfigPath); - - ui().logger.log(`ESLint plugin executing ${targets.length} lint targets`); - - const linterOutputs = await asyncSequential(targets, lint); - const lintResults = mergeLinterOutputs(linterOutputs); - const failedAudits = lintResultsToAudits(lintResults); - - const audits = slugs.map( - (slug): AuditOutput => - failedAudits.find(audit => audit.slug === slug) ?? { - slug, - score: 1, - value: 0, - displayValue: 'passed', - details: { issues: [] }, - }, - ); - - await ensureDirectoryExists(path.dirname(runnerOutputPath)); - await writeFile(runnerOutputPath, JSON.stringify(audits)); -} - -export async function createRunnerConfig( - scriptPath: string, - audits: Audit[], - targets: ESLintTarget[], -): Promise { - const config: ESLintPluginRunnerConfig = { - targets, - slugs: audits.map(audit => audit.slug), - }; - const { runnerConfigPath, runnerOutputPath } = await createRunnerFiles( - 'eslint', - JSON.stringify(config), - ); - - return { - command: 'node', - args: [ - filePathToCliArg(scriptPath), - ...objectToCliArgs({ runnerConfigPath, runnerOutputPath }), - ], - configFile: runnerConfigPath, - outputFile: runnerOutputPath, - }; -} - export function createRunnerFunction(options: { audits: Audit[]; targets: ESLintTarget[]; From 5454e032e63ee8e39eba75df9c827fabae45f9e3 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 18:35:12 +0200 Subject: [PATCH 05/17] refactor: fix int tests 1 --- packages/plugin-eslint/package.json | 6 +- .../plugin-eslint/src/lib/runner.int.test.ts | 59 +++++++++---------- packages/plugin-js-packages/package.json | 6 +- packages/plugin-jsdocs/package.json | 6 +- packages/plugin-lighthouse/package.json | 6 +- packages/plugin-typescript/package.json | 6 +- packages/utils/package.json | 4 +- 7 files changed, 45 insertions(+), 48 deletions(-) diff --git a/packages/plugin-eslint/package.json b/packages/plugin-eslint/package.json index 3992516e2..03288291d 100644 --- a/packages/plugin-eslint/package.json +++ b/packages/plugin-eslint/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/eslint-plugin", - "version": "0.76.0", + "version": "0.77.0", "license": "MIT", "description": "Code PushUp plugin for detecting problems in source code using ESLint.📋", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-eslint#readme", @@ -39,8 +39,8 @@ "type": "module", "dependencies": { "glob": "^11.0.0", - "@code-pushup/utils": "0.76.0", - "@code-pushup/models": "0.76.0", + "@code-pushup/utils": "0.77.0", + "@code-pushup/models": "0.77.0", "yargs": "^17.7.2", "zod": "^4.0.5" }, diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index cd97a78bd..32dc84890 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -3,37 +3,23 @@ import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import { type MockInstance, describe, expect, it } from 'vitest'; -import type { - AuditOutput, - AuditOutputs, - Issue, - RunnerFilesPaths, -} from '@code-pushup/models'; +import type { Audit, AuditOutput, Issue } from '@code-pushup/models'; import { osAgnosticAuditOutputs } from '@code-pushup/test-utils'; -import { readJsonFile } from '@code-pushup/utils'; import type { ESLintTarget } from './config.js'; import { listAuditsAndGroups } from './meta/index.js'; -import { createRunnerConfig, executeRunner } from './runner/index.js'; +import { createRunnerFunction } from './runner/index.js'; describe('executeRunner', () => { let cwdSpy: MockInstance<[], string>; let platformSpy: MockInstance<[], NodeJS.Platform>; - const createPluginConfig = async ( + const createAudits = async ( eslintrc: ESLintTarget['eslintrc'], - ): Promise => { + ): Promise => { const patterns = ['src/**/*.js', 'src/**/*.jsx']; const targets: ESLintTarget[] = [{ eslintrc, patterns }]; const { audits } = await listAuditsAndGroups(targets); - const { outputFile, configFile } = await createRunnerConfig( - 'bin.js', - audits, - targets, - ); - return { - runnerOutputPath: outputFile, - runnerConfigPath: configFile!, - }; + return audits; }; const appDir = path.join( @@ -57,24 +43,35 @@ describe('executeRunner', () => { }); it('should execute ESLint and create audit results for React application', async () => { - const runnerPaths = await createPluginConfig('eslint.config.js'); - await executeRunner(runnerPaths); - - const json = await readJsonFile(runnerPaths.runnerOutputPath); - expect(osAgnosticAuditOutputs(json)).toMatchSnapshot(); + const eslintTarget = 'eslint.config.js'; + const runnerFn = await createRunnerFunction({ + audits: await createAudits(eslintTarget), + targets: [ + { + eslintrc: eslintTarget, + patterns: '.', + }, + ], + }); + const res = await runnerFn({ outputDir: '' }); + await expect(osAgnosticAuditOutputs(res)).resolves.toMatchSnapshot(); }); it.skipIf(process.platform === 'win32')( 'should execute runner with custom config using @code-pushup/eslint-config', async () => { - const runnerPaths = await createPluginConfig( - 'code-pushup.eslint.config.mjs', - ); - await executeRunner(runnerPaths); + const eslintTarget = 'eslint.config.js'; + const runnerFn = await createRunnerFunction({ + audits: await createAudits(eslintTarget), + targets: [ + { + eslintrc: 'code-pushup.eslint.config.mjs', + patterns: '.', + }, + ], + }); - const json = await readJsonFile( - runnerPaths.runnerOutputPath, - ); + const json = await runnerFn({ outputDir: '' }); // expect warnings from unicorn/filename-case rule from default config expect(json).toContainEqual( expect.objectContaining>({ diff --git a/packages/plugin-js-packages/package.json b/packages/plugin-js-packages/package.json index 6f630d164..2c7e76077 100644 --- a/packages/plugin-js-packages/package.json +++ b/packages/plugin-js-packages/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/js-packages-plugin", - "version": "0.76.0", + "version": "0.77.0", "description": "Code PushUp plugin for JavaScript packages 🛡️", "license": "MIT", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-js-packages#readme", @@ -37,8 +37,8 @@ }, "type": "module", "dependencies": { - "@code-pushup/models": "0.76.0", - "@code-pushup/utils": "0.76.0", + "@code-pushup/models": "0.77.0", + "@code-pushup/utils": "0.77.0", "build-md": "^0.4.1", "semver": "^7.6.0", "yargs": "^17.7.2", diff --git a/packages/plugin-jsdocs/package.json b/packages/plugin-jsdocs/package.json index 599c9501d..1c70679a7 100644 --- a/packages/plugin-jsdocs/package.json +++ b/packages/plugin-jsdocs/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/jsdocs-plugin", - "version": "0.76.0", + "version": "0.77.0", "description": "Code PushUp plugin for tracking documentation coverage 📚", "license": "MIT", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-jsdocs#readme", @@ -35,8 +35,8 @@ }, "type": "module", "dependencies": { - "@code-pushup/models": "0.76.0", - "@code-pushup/utils": "0.76.0", + "@code-pushup/models": "0.77.0", + "@code-pushup/utils": "0.77.0", "zod": "^4.0.5", "ts-morph": "^24.0.0" }, diff --git a/packages/plugin-lighthouse/package.json b/packages/plugin-lighthouse/package.json index 58bfb1fab..07ecb9aca 100644 --- a/packages/plugin-lighthouse/package.json +++ b/packages/plugin-lighthouse/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/lighthouse-plugin", - "version": "0.76.0", + "version": "0.77.0", "license": "MIT", "description": "Code PushUp plugin for measuring web performance and quality with Lighthouse 🔥", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-lighthouse#readme", @@ -36,8 +36,8 @@ }, "type": "module", "dependencies": { - "@code-pushup/models": "0.76.0", - "@code-pushup/utils": "0.76.0", + "@code-pushup/models": "0.77.0", + "@code-pushup/utils": "0.77.0", "ansis": "^3.3.0", "chrome-launcher": "^1.1.1", "lighthouse": "^12.0.0", diff --git a/packages/plugin-typescript/package.json b/packages/plugin-typescript/package.json index 276ec84ef..ad3c4c47a 100644 --- a/packages/plugin-typescript/package.json +++ b/packages/plugin-typescript/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/typescript-plugin", - "version": "0.76.0", + "version": "0.77.0", "license": "MIT", "description": "Code PushUp plugin for incrementally adopting strict compilation flags in TypeScript projects", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/plugin-typescript#readme", @@ -23,8 +23,8 @@ }, "type": "module", "dependencies": { - "@code-pushup/models": "0.76.0", - "@code-pushup/utils": "0.76.0", + "@code-pushup/models": "0.77.0", + "@code-pushup/utils": "0.77.0", "zod": "^4.0.5" }, "peerDependencies": { diff --git a/packages/utils/package.json b/packages/utils/package.json index 58267ae37..c0cdf448e 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@code-pushup/utils", - "version": "0.76.0", + "version": "0.77.0", "description": "Low-level utilities (helper functions, etc.) used by Code PushUp CLI", "license": "MIT", "homepage": "https://github.com/code-pushup/cli/tree/main/packages/utils#readme", @@ -27,7 +27,7 @@ "node": ">=17.0.0" }, "dependencies": { - "@code-pushup/models": "0.76.0", + "@code-pushup/models": "0.77.0", "@isaacs/cliui": "^8.0.2", "@poppinss/cliui": "^6.4.0", "ansis": "^3.3.0", From b71d2115e0856dacfbc5c0e5db790cdd62e43e3f Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 18:52:33 +0200 Subject: [PATCH 06/17] refactor: fix int tests 2 --- .../src/lib/eslint-plugin.int.test.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts index 2fce6fa8f..23987e263 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts @@ -46,18 +46,17 @@ describe('eslintPlugin', () => { }); // expect rule from extended base eslint.config.js - expect(plugin.audits).toContainEqual( - expect.objectContaining({ - slug: expect.stringMatching(/^nx-enforce-module-boundaries/), - title: expect.any(String), - description: expect.stringContaining('sourceTag'), - }), - ); - // expect rule from nx-plugin project's eslint.config.js - expect(plugin.audits).toContainEqual( - expect.objectContaining>({ - slug: 'nx-nx-plugin-checks', - }), + expect(plugin.audits).toStrictEqual( + expect.arrayContaining([ + expect.objectContaining({ + slug: expect.stringMatching(/^nx-enforce-module-boundaries/), + title: expect.any(String), + description: expect.stringContaining('sourceTag'), + }), + expect.objectContaining>({ + slug: 'nx-nx-plugin-checks', + }), + ]), ); }); From cb1dbbc5f483173379498386f8b69d1b834ae601 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 18:53:39 +0200 Subject: [PATCH 07/17] refactor: fix lint 1 --- packages/plugin-eslint/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/plugin-eslint/package.json b/packages/plugin-eslint/package.json index 03288291d..506b21136 100644 --- a/packages/plugin-eslint/package.json +++ b/packages/plugin-eslint/package.json @@ -41,7 +41,6 @@ "glob": "^11.0.0", "@code-pushup/utils": "0.77.0", "@code-pushup/models": "0.77.0", - "yargs": "^17.7.2", "zod": "^4.0.5" }, "peerDependencies": { From 1757b7d95666efdf2d15c23fc29ab58bfa6718b4 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 18:57:33 +0200 Subject: [PATCH 08/17] refactor: fix int test 4 --- packages/plugin-eslint/src/lib/runner.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index 32dc84890..693e980dd 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -54,7 +54,7 @@ describe('executeRunner', () => { ], }); const res = await runnerFn({ outputDir: '' }); - await expect(osAgnosticAuditOutputs(res)).resolves.toMatchSnapshot(); + expect(osAgnosticAuditOutputs(res)).toMatchSnapshot(); }); it.skipIf(process.platform === 'win32')( From f00a6d77b3957da6a7092fb01c2a3ad0016d2cd6 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Thu, 28 Aug 2025 19:03:21 +0200 Subject: [PATCH 09/17] refactor: fix int test 6 --- packages/plugin-eslint/src/lib/runner.int.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index 693e980dd..95ebaef28 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -3,7 +3,12 @@ import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import { type MockInstance, describe, expect, it } from 'vitest'; -import type { Audit, AuditOutput, Issue } from '@code-pushup/models'; +import type { + Audit, + AuditOutput, + AuditOutputs, + Issue, +} from '@code-pushup/models'; import { osAgnosticAuditOutputs } from '@code-pushup/test-utils'; import type { ESLintTarget } from './config.js'; import { listAuditsAndGroups } from './meta/index.js'; @@ -53,19 +58,19 @@ describe('executeRunner', () => { }, ], }); - const res = await runnerFn({ outputDir: '' }); + const res: AuditOutputs = await runnerFn({ outputDir: '' }); expect(osAgnosticAuditOutputs(res)).toMatchSnapshot(); }); it.skipIf(process.platform === 'win32')( 'should execute runner with custom config using @code-pushup/eslint-config', async () => { - const eslintTarget = 'eslint.config.js'; + const eslintTarget = 'code-pushup.eslint.config.mjs'; const runnerFn = await createRunnerFunction({ audits: await createAudits(eslintTarget), targets: [ { - eslintrc: 'code-pushup.eslint.config.mjs', + eslintrc: eslintTarget, patterns: '.', }, ], From 11ca96e130466202ea52c0831a92137e74c09ead Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 17:59:26 +0200 Subject: [PATCH 10/17] Update packages/plugin-eslint/src/lib/runner.int.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/runner.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index 95ebaef28..a55727b2f 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -76,7 +76,7 @@ describe('executeRunner', () => { ], }); - const json = await runnerFn({ outputDir: '' }); + const json = await runnerFn({}); // expect warnings from unicorn/filename-case rule from default config expect(json).toContainEqual( expect.objectContaining>({ From 33af94d53c6a7b4a78099f0918c69294c4817566 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:00:05 +0200 Subject: [PATCH 11/17] Update packages/plugin-eslint/src/lib/runner.int.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/runner.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index a55727b2f..2217c1f8e 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -58,7 +58,7 @@ describe('executeRunner', () => { }, ], }); - const res: AuditOutputs = await runnerFn({ outputDir: '' }); + const res = (await runnerFn({})) as AuditOutputs; expect(osAgnosticAuditOutputs(res)).toMatchSnapshot(); }); From c1951f18f52d981741c81a7dff0b745d863ccba3 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:01:05 +0200 Subject: [PATCH 12/17] Update packages/plugin-eslint/src/lib/runner/index.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/runner/index.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index a633c932c..37e9931f1 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -29,10 +29,7 @@ export function createRunnerFunction(options: { const linterOutputs = artifacts ? await loadArtifacts(artifacts) : await asyncSequential( - targets.map(target => ({ - ...target, - outputDir, - })), + targets.map(target => ({ ...target, outputDir })), lint, ); const lintResults = mergeLinterOutputs(linterOutputs); From b55b1ca49101bb5d7d4360b5dfcbca28e1bb82dd Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:01:13 +0200 Subject: [PATCH 13/17] Update packages/plugin-eslint/src/lib/runner/index.unit.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/runner/index.unit.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts index 76275ffe2..cfc59bbfe 100644 --- a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts @@ -33,7 +33,7 @@ describe('call createRunnerFunction', () => { }); }); -describe('execute created runnerFunction', () => { +describe('createRunnerFunction', () => { const loadArtifactsSpy = vi.spyOn(utilsFileModule, 'loadArtifacts'); const lintSpy = vi.spyOn(lintModule, 'lint'); From cd996fd0d2e61459927145a8ca10d7bd34da581b Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:01:57 +0200 Subject: [PATCH 14/17] Update packages/plugin-eslint/src/lib/runner/index.unit.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- .../src/lib/runner/index.unit.test.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts index cfc59bbfe..bc9413d56 100644 --- a/packages/plugin-eslint/src/lib/runner/index.unit.test.ts +++ b/packages/plugin-eslint/src/lib/runner/index.unit.test.ts @@ -12,27 +12,6 @@ import * as lintModule from './lint.js'; import type { LinterOutput } from './types.js'; import * as utilsFileModule from './utils.js'; -describe('call createRunnerFunction', () => { - it('should create runnerFunction correctly', () => { - expect( - createRunnerFunction({ - audits: [ - { slug: 'max-lines', title: 'Max lines', description: 'Test' }, - { - slug: 'no-unused-vars', - title: 'No unused vars', - description: 'Test', - }, - ], - targets: [{ patterns: ['src/**/*.ts'] }], - artifacts: { - artifactsPaths: ['path/to/artifacts.json'], - }, - }), - ).toStrictEqual(expect.any(Function)); - }); -}); - describe('createRunnerFunction', () => { const loadArtifactsSpy = vi.spyOn(utilsFileModule, 'loadArtifacts'); const lintSpy = vi.spyOn(lintModule, 'lint'); From f838cfbd700ff82497fa1cd584192cd6fc7abbe9 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:02:26 +0200 Subject: [PATCH 15/17] Update packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts index 23987e263..eef2cf872 100644 --- a/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts +++ b/packages/plugin-eslint/src/lib/eslint-plugin.int.test.ts @@ -153,6 +153,6 @@ describe('eslintPlugin', () => { }, ); - expect(typeof plugin.runner).toBe('function'); + expect(plugin.runner).toBeTypeOf('function'); }); }); From 67c27941374f6323fd61665b6fb84ebea9381997 Mon Sep 17 00:00:00 2001 From: Michael Hladky <10064416+BioPhoton@users.noreply.github.com> Date: Fri, 29 Aug 2025 18:04:44 +0200 Subject: [PATCH 16/17] Update packages/plugin-eslint/src/lib/runner.int.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matěj Chalk <34691111+matejchalk@users.noreply.github.com> --- packages/plugin-eslint/src/lib/runner.int.test.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index 2217c1f8e..c69efdc09 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -48,16 +48,8 @@ describe('executeRunner', () => { }); it('should execute ESLint and create audit results for React application', async () => { - const eslintTarget = 'eslint.config.js'; - const runnerFn = await createRunnerFunction({ - audits: await createAudits(eslintTarget), - targets: [ - { - eslintrc: eslintTarget, - patterns: '.', - }, - ], - }); + const args = await prepareRunnerArgs('eslint.config.js'); + const runnerFn = await createRunnerFunction(args); const res = (await runnerFn({})) as AuditOutputs; expect(osAgnosticAuditOutputs(res)).toMatchSnapshot(); }); From 51a431e2472e6c9086affa8c0bb1a904e916ddb1 Mon Sep 17 00:00:00 2001 From: Michael Hladky Date: Fri, 29 Aug 2025 18:14:54 +0200 Subject: [PATCH 17/17] refactor: improve tests --- .../plugin-eslint/src/lib/runner.int.test.ts | 31 +++++++++---------- .../plugin-eslint/src/lib/runner/index.ts | 2 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/packages/plugin-eslint/src/lib/runner.int.test.ts b/packages/plugin-eslint/src/lib/runner.int.test.ts index c69efdc09..05f8bb004 100644 --- a/packages/plugin-eslint/src/lib/runner.int.test.ts +++ b/packages/plugin-eslint/src/lib/runner.int.test.ts @@ -3,11 +3,12 @@ import path from 'node:path'; import process from 'node:process'; import { fileURLToPath } from 'node:url'; import { type MockInstance, describe, expect, it } from 'vitest'; -import type { - Audit, - AuditOutput, - AuditOutputs, - Issue, +import { + type Audit, + type AuditOutput, + type AuditOutputs, + DEFAULT_PERSIST_OUTPUT_DIR, + type Issue, } from '@code-pushup/models'; import { osAgnosticAuditOutputs } from '@code-pushup/test-utils'; import type { ESLintTarget } from './config.js'; @@ -18,13 +19,13 @@ describe('executeRunner', () => { let cwdSpy: MockInstance<[], string>; let platformSpy: MockInstance<[], NodeJS.Platform>; - const createAudits = async ( + const prepareRunnerArgs = async ( eslintrc: ESLintTarget['eslintrc'], - ): Promise => { + ): Promise<{ audits: Audit[]; targets: ESLintTarget[] }> => { const patterns = ['src/**/*.js', 'src/**/*.jsx']; const targets: ESLintTarget[] = [{ eslintrc, patterns }]; const { audits } = await listAuditsAndGroups(targets); - return audits; + return { audits, targets }; }; const appDir = path.join( @@ -50,7 +51,9 @@ describe('executeRunner', () => { it('should execute ESLint and create audit results for React application', async () => { const args = await prepareRunnerArgs('eslint.config.js'); const runnerFn = await createRunnerFunction(args); - const res = (await runnerFn({})) as AuditOutputs; + const res = (await runnerFn({ + outputDir: DEFAULT_PERSIST_OUTPUT_DIR, + })) as AuditOutputs; expect(osAgnosticAuditOutputs(res)).toMatchSnapshot(); }); @@ -59,16 +62,10 @@ describe('executeRunner', () => { async () => { const eslintTarget = 'code-pushup.eslint.config.mjs'; const runnerFn = await createRunnerFunction({ - audits: await createAudits(eslintTarget), - targets: [ - { - eslintrc: eslintTarget, - patterns: '.', - }, - ], + ...(await prepareRunnerArgs(eslintTarget)), }); - const json = await runnerFn({}); + const json = await runnerFn({ outputDir: DEFAULT_PERSIST_OUTPUT_DIR }); // expect warnings from unicorn/filename-case rule from default config expect(json).toContainEqual( expect.objectContaining>({ diff --git a/packages/plugin-eslint/src/lib/runner/index.ts b/packages/plugin-eslint/src/lib/runner/index.ts index 37e9931f1..79a4abdfc 100644 --- a/packages/plugin-eslint/src/lib/runner/index.ts +++ b/packages/plugin-eslint/src/lib/runner/index.ts @@ -29,7 +29,7 @@ export function createRunnerFunction(options: { const linterOutputs = artifacts ? await loadArtifacts(artifacts) : await asyncSequential( - targets.map(target => ({ ...target, outputDir })), + targets.map(target => ({ ...target, outputDir })), lint, ); const lintResults = mergeLinterOutputs(linterOutputs);