Skip to content
Merged
168 changes: 95 additions & 73 deletions packages/models/docs/models-reference.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,7 @@ export {
type Tree,
} from './lib/tree.js';
export { uploadConfigSchema, type UploadConfig } from './lib/upload-config.js';
export {
artifactGenerationCommand as toolCommandSchema,
pluginArtefactOptionsSchema,
} from './lib/configuration';
24 changes: 24 additions & 0 deletions packages/models/src/lib/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { z } from 'zod';

/**
* Generic schema for a tool command configuration, reusable across plugins.
*/
export const artifactGenerationCommand = z.object({
command: z.string({ description: 'Command to run the tool.' }).min(1),
args: z
.array(z.string(), {
description: 'Arguments to be passed to the tool.',
})
.optional(),
});

export type ArtefactGenerationCommand = z.infer<
typeof artifactGenerationCommand
>;

export const pluginArtefactOptionsSchema = z.object({
generateArtefacts: artifactGenerationCommand.optional(),
artefactsPaths: z.union([z.string(), z.array(z.string())]),
});

export type PluginArtefactOptions = z.infer<typeof pluginArtefactOptionsSchema>;
95 changes: 95 additions & 0 deletions packages/models/src/lib/configuration.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { describe, expect, it } from 'vitest';
import {
artifactGenerationCommand,
pluginArtefactOptionsSchema,
} from './configuration.js';

describe('artifactGenerationCommand', () => {
it('should validate a command with required fields', () => {
const data = { command: 'npx' };
const result = artifactGenerationCommand.safeParse(data);
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.command).toBe('npx');
expect(result.data.args).toBeUndefined();
}
});

it('should validate a command with args', () => {
const data = { command: 'npx', args: ['eslint', 'src/'] };
const result = artifactGenerationCommand.safeParse(data);
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.command).toBe('npx');
expect(result.data.args).toEqual(['eslint', 'src/']);
}
});

it('should fail if command is missing', () => {
const data = { args: ['eslint', 'src/'] };
const result = artifactGenerationCommand.safeParse(data);
expect(result.success).toBe(false);
});

it('should fail if command is empty', () => {
const data = { command: '' };
const result = artifactGenerationCommand.safeParse(data);
expect(result.success).toBe(false);
});

it('should fail if args is not an array of strings', () => {
const data = { command: 'npx', args: [123, true] };
const result = artifactGenerationCommand.safeParse(data);
expect(result.success).toBe(false);
});
});

describe('pluginArtefactOptionsSchema', () => {
it('should validate with only artefactsPaths as string', () => {
const data = { artefactsPaths: 'dist/report.json' };
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(true);
});

it('should validate with artefactsPaths as array of strings', () => {
const data = { artefactsPaths: ['dist/report.json', 'dist/summary.json'] };
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(true);
});

it('should fail if artefactsPaths is an empty array', () => {
const data = { artefactsPaths: [] };
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(false);
});

it('should validate with generateArtefacts and artefactsPaths', () => {
const data = {
generateArtefacts: { command: 'npm', args: ['run', 'build'] },
artefactsPaths: ['dist/report.json'],
};
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(true);
});

it('should fail if artefactsPaths is missing', () => {
const data = { generateArtefacts: { command: 'npm' } };
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(false);
});

it('should fail if artefactsPaths is not string or array of strings', () => {
const data = { artefactsPaths: 123 };
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(false);
});

it('should fail if generateArtefacts is invalid', () => {
const data = {
generateArtefacts: { command: '' },
artefactsPaths: 'dist/report.json',
};
const { success } = pluginArtefactOptionsSchema.safeParse(data);
expect(success).toBe(false);
});
});
14 changes: 2 additions & 12 deletions packages/plugin-coverage/src/lib/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from 'zod';
import { toolCommandSchema } from '@code-pushup/models';

export const coverageTypeSchema = z.enum(['function', 'branch', 'line']);
export type CoverageType = z.infer<typeof coverageTypeSchema>;
Expand Down Expand Up @@ -26,18 +27,7 @@ export const coverageResultSchema = z.union([
export type CoverageResult = z.infer<typeof coverageResultSchema>;

export const coveragePluginConfigSchema = z.object({
coverageToolCommand: z
.object({
command: z
.string({ description: 'Command to run coverage tool.' })
.min(1),
args: z
.array(z.string(), {
description: 'Arguments to be passed to the coverage tool.',
})
.optional(),
})
.optional(),
coverageToolCommand: toolCommandSchema.optional(),
continueOnCommandFail: z
.boolean({
description:
Expand Down
Loading
Loading