Skip to content

Commit 9484315

Browse files
committed
refactor(models): polish models, mocks and comments
1 parent d4bcc89 commit 9484315

File tree

10 files changed

+114
-100
lines changed

10 files changed

+114
-100
lines changed

packages/models/src/lib/core-config.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from 'vitest';
22
import { coreConfigSchema } from './core-config';
3-
import { mockCategory, mockConfig, mockPluginConfig } from '../../test';
3+
import { mockCategory, mockCoreConfig, mockPluginConfig } from '../../test';
44

55
/*
66
- plugin slug: es-lint
@@ -14,7 +14,7 @@ import { mockCategory, mockConfig, mockPluginConfig } from '../../test';
1414
*/
1515
describe('CoreConfig', () => {
1616
it('should parse if configuration is valid', () => {
17-
const cfg = mockConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
17+
const cfg = mockCoreConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
1818
cfg.categories = [
1919
mockCategory({
2020
pluginSlug: 'test',
@@ -26,7 +26,7 @@ describe('CoreConfig', () => {
2626

2727
it('should parse if configuration and groups are valid', () => {
2828
const pluginSlug = 'plg';
29-
const cfg = mockConfig();
29+
const cfg = mockCoreConfig();
3030
cfg.plugins = [
3131
mockPluginConfig({ pluginSlug, auditSlug: 'lcp', groupSlug: 'perf' }),
3232
];
@@ -42,7 +42,7 @@ describe('CoreConfig', () => {
4242
});
4343

4444
it('should throw if the category slugs are not unique', () => {
45-
const cfg = mockConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
45+
const cfg = mockCoreConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
4646
const duplicatedSlug = 'test';
4747
cfg.categories.push(
4848
mockCategory({
@@ -60,7 +60,7 @@ describe('CoreConfig', () => {
6060
});
6161

6262
it('should throw if ref in a category does not exist in audits', () => {
63-
const cfg = mockConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
63+
const cfg = mockCoreConfig({ pluginSlug: 'test', auditSlug: ['a', 'b'] });
6464
cfg.categories = [
6565
mockCategory({
6666
pluginSlug: 'test',
@@ -74,7 +74,7 @@ describe('CoreConfig', () => {
7474
});
7575

7676
it('should throw if ref in a category does not exist in groups', () => {
77-
const cfg = mockConfig({
77+
const cfg = mockCoreConfig({
7878
pluginSlug: 'test',
7979
auditSlug: ['a', 'b'],
8080
groupSlug: 'a',

packages/models/src/lib/implementation/schemas.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function executionMetaSchema(
1010
descriptionDuration: string;
1111
} = {
1212
descriptionDate: 'Execution start date and time',
13-
descriptionDuration: 'Execution duration',
13+
descriptionDuration: 'Execution duration in ms',
1414
},
1515
) {
1616
return z.object({
@@ -26,18 +26,15 @@ export function executionMetaSchema(
2626
export function slugSchema(
2727
description = 'Unique ID (human-readable, URL-safe)',
2828
) {
29-
return (
30-
z
31-
.string({ description })
32-
// also validates ``and ` `
33-
.regex(slugRegex, {
34-
message:
35-
'The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug',
36-
})
37-
.max(128, {
38-
message: 'slug can be max 128 characters long',
39-
})
40-
);
29+
return z
30+
.string({ description })
31+
.regex(slugRegex, {
32+
message:
33+
'The slug has to follow the pattern [0-9a-z] followed by multiple optional groups of -[0-9a-z]. e.g. my-slug',
34+
})
35+
.max(128, {
36+
message: 'slug can be max 128 characters long',
37+
});
4138
}
4239

4340
/**

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

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
hasMissingStrings,
1818
} from './implementation/utils';
1919

20-
export const pluginMetadataSchema = packageVersionSchema({
20+
export const pluginSchema = packageVersionSchema({
2121
optional: true,
2222
})
2323
.merge(
@@ -110,7 +110,7 @@ export const pluginConfigSchema = z
110110
}),
111111
),
112112
})
113-
.merge(pluginMetadataSchema)
113+
.merge(pluginSchema)
114114
// every listed group ref points to an audit within the plugin
115115
.refine(
116116
pluginCfg => !getMissingRefsFromGroups(pluginCfg),
@@ -190,10 +190,9 @@ export const issueSchema = z.object(
190190
);
191191
export type Issue = z.infer<typeof issueSchema>;
192192

193-
export const auditOutputSchema = z
194-
.object(
193+
export const auditOutputSchema = auditSchema.merge(
194+
z.object(
195195
{
196-
slug: slugSchema('References audit. ID (unique within pluginOutput)'),
197196
displayValue: z
198197
.string({ description: "Formatted value (e.g. '0.9 s', '2.1 MB')" })
199198
.optional(),
@@ -215,14 +214,8 @@ export const auditOutputSchema = z
215214
.optional(),
216215
},
217216
{ description: 'Audit information' },
218-
)
219-
.merge(
220-
metaSchema({
221-
titleDescription: 'Audit title',
222-
descriptionDescription: 'Audit description',
223-
docsUrlDescription: 'Audit docs URL',
224-
}),
225-
);
217+
),
218+
);
226219
export type AuditOutput = z.infer<typeof auditOutputSchema>;
227220

228221
export const auditOutputsSchema = z
@@ -237,20 +230,19 @@ export const auditOutputsSchema = z
237230
);
238231
export type AuditOutputs = z.infer<typeof auditOutputsSchema>;
239232

240-
export const pluginOutputSchema = executionMetaSchema()
241-
.merge(metaSchema()) // @TODO create reusable meta info for audit, plugin, category
233+
export const pluginOutputSchema = pluginSchema
234+
.merge(executionMetaSchema()) // @TODO create reusable meta info for audit, plugin, category
242235
.merge(
243-
z.object(
244-
{
245-
slug: slugSchema('Plugin slug'),
246-
audits: auditOutputsSchema
247-
},
248-
{
249-
description:
250-
'List of JSON formatted audit output emitted by the runner process of a plugin',
251-
},
252-
),
253-
);
236+
z.object(
237+
{
238+
audits: auditOutputsSchema,
239+
},
240+
{
241+
description:
242+
'List of JSON formatted audit output emitted by the runner process of a plugin',
243+
},
244+
),
245+
);
254246

255247
export type PluginOutput = z.infer<typeof pluginOutputSchema>;
256248

packages/models/src/lib/report.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,21 @@ export type PluginReport = z.infer<typeof pluginReportSchema>;
3232

3333
export const reportSchema = packageVersionSchema({
3434
versionDescription: 'NPM version of the CLI',
35-
}).merge(
36-
z.object(
37-
{
38-
date: z.string({ description: 'Start date and time of the collect run' }),
39-
duration: z.number({ description: 'Duration of the collect run in ms' }),
40-
plugins: z.array(pluginReportSchema),
41-
},
42-
{ description: 'Collect output data.' },
43-
),
44-
);
35+
})
36+
.merge(
37+
executionMetaSchema({
38+
descriptionDate: 'Start date and time of the collect run',
39+
descriptionDuration: 'Duration of the collect run in ms',
40+
}),
41+
)
42+
.merge(
43+
z.object(
44+
{
45+
plugins: z.array(pluginReportSchema),
46+
},
47+
{ description: 'Collect output data' },
48+
),
49+
);
4550

4651
export type Report = z.infer<typeof reportSchema>;
4752

packages/models/test/schema.mock.ts

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
AuditOutputs,
1111
AuditReport,
1212
UploadConfig,
13+
AuditOutput,
14+
Issue,
1315
} from '../src/index';
1416

1517
const __pluginSlug__ = 'mock-plugin-slug';
@@ -77,7 +79,7 @@ export function mockAuditConfig(opt?: { auditSlug?: string }): Audit {
7779
title: auditSlug + ' title',
7880
description: 'audit description',
7981
docsUrl: 'http://www.my-docs.dev',
80-
};
82+
} satisfies Required<Audit>;
8183
}
8284

8385
export function mockPersistConfig(opt?: Partial<PersistConfig>): PersistConfig {
@@ -87,7 +89,7 @@ export function mockPersistConfig(opt?: Partial<PersistConfig>): PersistConfig {
8789
return {
8890
outputPath,
8991
format,
90-
};
92+
} satisfies Required<PersistConfig>;
9193
}
9294

9395
export function mockGroupConfig(opt?: {
@@ -113,7 +115,7 @@ export function mockGroupConfig(opt?: {
113115
weight: randWeight(),
114116
},
115117
],
116-
};
118+
} satisfies Required<AuditGroup>;
117119
}
118120

119121
export function mockCategory(opt?: {
@@ -172,8 +174,9 @@ export function mockCategory(opt?: {
172174
.map(word => word.slice(0, 1).toUpperCase() + word.slice(1))
173175
.join(' ')}`,
174176
description: `This is the category description of ${categorySlug}. Enjoy dummy text and data to the full.`,
177+
docsUrl: 'https://category.dev?' + categorySlug,
175178
refs: categoryAuditRefs.concat(categoryGroupRefs),
176-
};
179+
} satisfies Required<CategoryConfig>;
177180
}
178181

179182
export function mockReport(opt?: {
@@ -203,28 +206,25 @@ export function mockPluginReport(opt?: {
203206
date: new Date().toDateString(),
204207
duration: randDuration(),
205208
slug: pluginSlug,
206-
docsUrl: `http://plugin.io/docs/${pluginSlug}`,
207209
title: 'Mock plugin Name',
210+
description: 'Plugin description of ' + pluginSlug,
211+
docsUrl: `http://plugin.io/docs/${pluginSlug}`,
208212
icon: 'socket',
209213
audits: Array.isArray(auditSlug)
210214
? auditSlug.map(a => mockAuditReport({ auditSlug: a }))
211215
: [mockAuditReport({ auditSlug })],
212-
};
216+
} satisfies Required<PluginReport>;
213217
}
214218

215219
export function mockAuditReport(opt?: { auditSlug: string }): AuditReport {
216220
let { auditSlug } = opt || {};
217221
auditSlug = auditSlug || __auditSlug__;
218222
return {
219-
slug: auditSlug,
220-
displayValue: 'mocked value',
221-
value: Math.floor(Math.random() * 100),
222-
score: Math.round(Math.random()),
223-
title: auditSlug,
224-
};
223+
...(mockAuditOutput({ auditSlug }) as Required<AuditOutput>),
224+
} satisfies Required<AuditReport>;
225225
}
226226

227-
export function mockConfig(opt?: {
227+
export function mockCoreConfig(opt?: {
228228
outputPath?: string;
229229
categorySlug?: string | string[];
230230
pluginSlug?: string | string[];
@@ -235,6 +235,7 @@ export function mockConfig(opt?: {
235235
opt || {};
236236
return {
237237
persist: mockPersistConfig({ outputPath }),
238+
upload: mockUploadConfig(),
238239
plugins: Array.isArray(pluginSlug)
239240
? pluginSlug.map(slug =>
240241
mockPluginConfig({ pluginSlug: slug, auditSlug, groupSlug }),
@@ -245,7 +246,7 @@ export function mockConfig(opt?: {
245246
mockCategory({ categorySlug: slug, auditSlug, groupSlug }),
246247
)
247248
: [mockCategory({ categorySlug, auditSlug, groupSlug })],
248-
};
249+
} satisfies Required<CoreConfig>;
249250
}
250251

251252
export function mockUploadConfig(opt?: Partial<UploadConfig>): UploadConfig {
@@ -261,23 +262,40 @@ export function mockAuditOutputs(opt?: {
261262
}): AuditOutputs {
262263
let { auditSlug } = opt || {};
263264
auditSlug = auditSlug || 'mock-audit-output-slug';
264-
const audits = Array.isArray(auditSlug)
265-
? auditSlug.map((slug, idx) => ({
266-
slug,
267-
title: 'Title of ' + slug,
268-
value: idx,
269-
displayValue: '',
270-
score: 0,
271-
}))
272-
: [
273-
{
274-
slug: auditSlug,
275-
title: 'Title of ' + auditSlug,
276-
value: 12,
277-
displayValue: '',
278-
score: 0,
279-
},
280-
];
265+
return Array.isArray(auditSlug)
266+
? auditSlug.map((slug, idx) => mockAuditOutput({ auditSlug: slug }))
267+
: [mockAuditOutput({ auditSlug })];
268+
}
269+
270+
export function mockAuditOutput(opt?: { auditSlug: string }): AuditOutput {
271+
let { auditSlug } = opt || {};
272+
auditSlug = auditSlug || 'mock-audit-output-slug';
273+
return {
274+
slug: auditSlug,
275+
title: 'Title of ' + auditSlug,
276+
description: 'Description of ' + auditSlug,
277+
docsUrl: 'https://audit.dev?' + auditSlug,
278+
details: {
279+
issues: [mockIssueOutput()],
280+
},
281+
value: 12,
282+
displayValue: '',
283+
score: 0,
284+
} satisfies Required<AuditOutput>;
285+
}
281286

282-
return audits;
287+
export function mockIssueOutput(): Issue {
288+
return {
289+
severity: 'error',
290+
message: '',
291+
source: {
292+
file: 'the-file.ts',
293+
position: {
294+
startLine: 1,
295+
startColumn: 2,
296+
endLine: 3,
297+
endColumn: 4,
298+
},
299+
},
300+
} satisfies Required<Issue>;
283301
}

packages/models/test/test-data/config-and-report-dummy.mock.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
mockCategory,
3-
mockConfig,
3+
mockCoreConfig,
44
mockPluginConfig,
55
mockReport,
66
} from '../schema.mock';
@@ -10,7 +10,7 @@ const auditSlug0 = ['0a', '0b', '0c', '0d'];
1010
const auditSlug1 = ['1a', '1b', '1c'];
1111
const auditSlug2 = ['2a', '2b', '2c', '2d', '2e'];
1212

13-
export const dummyConfig = mockConfig({ outputPath: 'out' });
13+
export const dummyConfig = mockCoreConfig({ outputPath: 'out' });
1414
dummyConfig.plugins = [
1515
mockPluginConfig({ pluginSlug: pluginSlug[0], auditSlug: auditSlug0 }),
1616
mockPluginConfig({ pluginSlug: pluginSlug[1], auditSlug: auditSlug1 }),

packages/models/test/test-data/config-and-report-lighthouse.mock.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PluginConfig } from '../../src/index';
2-
import { mockConfig, mockReport } from '../schema.mock';
2+
import { mockCoreConfig, mockReport } from '../schema.mock';
33

44
export const lighthousePlugin: () => PluginConfig = () =>
55
({
@@ -938,7 +938,7 @@ export const lighthousePlugin: () => PluginConfig = () =>
938938
],
939939
} satisfies PluginConfig);
940940

941-
export const lighthouseConfig = mockConfig();
941+
export const lighthouseConfig = mockCoreConfig();
942942
lighthouseConfig.plugins = [lighthousePlugin()];
943943
lighthouseConfig.categories = [
944944
{

0 commit comments

Comments
 (0)