Skip to content

Commit f52592f

Browse files
author
tuanductran
committed
test(schemas): expand valibot integrity coverage
1 parent dd39d63 commit f52592f

3 files changed

Lines changed: 83 additions & 24 deletions

File tree

packages/nextdns-scripts/src/__tests__/audit.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { join } from 'node:path';
44
import { describe, expect, it } from 'vitest';
55

66
import { formatAuditText, runAudit } from '../commands/audit.js';
7+
import { parseAuditReport } from '../core/schemas.js';
78
import { getPackageVersion } from '../core/version.js';
89

910
function createFixture(rule: string, skill = '[Example](rules/example.md)') {
@@ -52,6 +53,13 @@ describe('runAudit', () => {
5253
expect(report.statistics.totalRules).toBe(report.ruleCount);
5354
});
5455

56+
it('round-trips the repository report through the Valibot schema', () => {
57+
const report = runAudit();
58+
const parsed = parseAuditReport(JSON.parse(JSON.stringify(report)));
59+
60+
expect(parsed).toEqual(report);
61+
});
62+
5563
it('formats a concise human-readable summary', () => {
5664
const report = runAudit();
5765
const output = formatAuditText(report);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import {
4+
AuditCheckSchema,
5+
AuditReportSchema,
6+
parseAuditReport,
7+
parseStatsReport,
8+
SkillStatsSchema,
9+
StatsReportSchema,
10+
} from '../index.js';
11+
12+
describe('maintenance package public schema API', () => {
13+
it('exports all Valibot schema objects from the package root', () => {
14+
expect(AuditCheckSchema).toBeDefined();
15+
expect(AuditReportSchema).toBeDefined();
16+
expect(SkillStatsSchema).toBeDefined();
17+
expect(StatsReportSchema).toBeDefined();
18+
});
19+
20+
it('exports callable report parsers from the package root', () => {
21+
expect(typeof parseAuditReport).toBe('function');
22+
expect(typeof parseStatsReport).toBe('function');
23+
});
24+
});

packages/nextdns-scripts/src/__tests__/schemas.test.ts

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,55 +29,82 @@ const validChecks = [
2929
{ name: 'duplicate-tags', passed: true, errors: 0, warnings: 0 },
3030
];
3131

32+
function validAuditReport(overrides: Record<string, unknown> = {}) {
33+
return {
34+
generatedAt: '2026-08-18T00:00:00.000Z',
35+
passed: true,
36+
ruleCount: 1,
37+
checks: validChecks,
38+
statistics: validStatistics,
39+
...overrides,
40+
};
41+
}
42+
3243
describe('schema parsing', () => {
3344
it('accepts a complete audit report', () => {
34-
const report = parseAuditReport({
35-
generatedAt: '2026-08-18T00:00:00.000Z',
36-
passed: true,
37-
ruleCount: 1,
38-
checks: validChecks,
39-
statistics: validStatistics,
40-
});
45+
const report = parseAuditReport(validAuditReport());
4146

4247
expect(report.statistics.totalRules).toBe(1);
4348
expect(report.checks).toHaveLength(5);
4449
});
4550

51+
it.each([validChecks.slice(0, 4), [...validChecks, ...validChecks.slice(0, 1)]])(
52+
'rejects an audit report with %s checks',
53+
(checks) => {
54+
expect(() => parseAuditReport(validAuditReport({ checks }))).toThrow();
55+
}
56+
);
57+
4658
it('rejects an unknown audit check name', () => {
4759
expect(() =>
48-
parseAuditReport({
49-
generatedAt: '2026-08-18T00:00:00.000Z',
50-
passed: false,
51-
ruleCount: 1,
52-
checks: [
53-
...validChecks.slice(0, 4),
54-
{ name: 'unknown-check', passed: false, errors: 1, warnings: 0 },
55-
],
56-
statistics: validStatistics,
57-
})
60+
parseAuditReport(
61+
validAuditReport({
62+
passed: false,
63+
checks: [
64+
...validChecks.slice(0, 4),
65+
{ name: 'unknown-check', passed: false, errors: 1, warnings: 0 },
66+
],
67+
})
68+
)
5869
).toThrow();
5970
});
6071

6172
it('rejects missing nested statistics', () => {
73+
const { statistics, ...reportWithoutStatistics } = validAuditReport();
74+
75+
expect(statistics).toBeDefined();
76+
expect(() => parseAuditReport(reportWithoutStatistics)).toThrow();
77+
});
78+
79+
it('rejects wrong primitive types', () => {
80+
expect(() => parseAuditReport(validAuditReport({ passed: 'true' }))).toThrow();
81+
expect(() => parseAuditReport(validAuditReport({ ruleCount: '1' }))).toThrow();
82+
});
83+
84+
it('rejects non-integer or negative counters', () => {
85+
expect(() => parseStatsReport({ ...validStatistics, totalRules: 1.5 })).toThrow();
6286
expect(() =>
63-
parseAuditReport({
64-
generatedAt: '2026-08-18T00:00:00.000Z',
65-
passed: true,
66-
ruleCount: 1,
67-
checks: validChecks,
87+
parseStatsReport({
88+
...validStatistics,
89+
impactDistribution: { HIGH: -1, MEDIUM: 0, LOW: 0 },
6890
})
6991
).toThrow();
7092
});
7193

72-
it('rejects negative counters', () => {
94+
it('rejects incomplete nested skill statistics', () => {
7395
expect(() =>
7496
parseStatsReport({
7597
...validStatistics,
76-
totalRules: -1,
98+
skills: [{ name: 'nextdns-api', total: 1 }],
7799
})
78100
).toThrow();
79101
});
80102

103+
it('rejects unknown input', () => {
104+
expect(() => parseAuditReport(null)).toThrow();
105+
expect(() => parseStatsReport('not-a-report')).toThrow();
106+
});
107+
81108
it('returns type-safe stats data for a valid report', () => {
82109
const report = parseStatsReport(validStatistics);
83110

0 commit comments

Comments
 (0)