101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
#!/usr/bin/env tsx
|
|
|
|
/**
|
|
* Validate the example documents under `examples/` against the generated
|
|
* `schema.json`. Each example is run against `#/$defs/ServerCard` and
|
|
* against the schema's expected acceptance — `valid/` examples must validate
|
|
* cleanly, `invalid/` examples must fail at least one constraint.
|
|
*/
|
|
|
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
import addFormats from "ajv-formats";
|
|
import { readdirSync, readFileSync } from "fs";
|
|
import { join } from "path";
|
|
|
|
const SCHEMA_JSON = "schema.json";
|
|
const EXAMPLES_DIR = "examples";
|
|
|
|
type Outcome = {
|
|
name: string;
|
|
expected: "valid" | "invalid";
|
|
passed: boolean;
|
|
message: string;
|
|
};
|
|
|
|
function loadSchema() {
|
|
const schema = JSON.parse(readFileSync(SCHEMA_JSON, "utf-8"));
|
|
const ajv = new Ajv2020({ allErrors: true, strict: false });
|
|
addFormats.default(ajv);
|
|
ajv.addSchema(schema, "schema.json");
|
|
return ajv;
|
|
}
|
|
|
|
function listJsonFiles(dir: string): string[] {
|
|
try {
|
|
return readdirSync(dir)
|
|
.filter((f) => f.endsWith(".json"))
|
|
.map((f) => join(dir, f));
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function runServerCardExamples(ajv: Ajv2020): Outcome[] {
|
|
const root = join(EXAMPLES_DIR, "ServerCard");
|
|
const outcomes: Outcome[] = [];
|
|
|
|
const validate = ajv.getSchema(`schema.json#/$defs/ServerCard`);
|
|
if (!validate) {
|
|
throw new Error(`Could not resolve ServerCard schema in ${SCHEMA_JSON}`);
|
|
}
|
|
|
|
for (const expected of ["valid", "invalid"] as const) {
|
|
const dir = join(root, expected);
|
|
for (const file of listJsonFiles(dir)) {
|
|
const data = JSON.parse(readFileSync(file, "utf-8"));
|
|
const ok = validate(data);
|
|
const passed = expected === "valid" ? !!ok : !ok;
|
|
const errors = validate.errors ?? [];
|
|
outcomes.push({
|
|
name: `ServerCard/${expected}/${file.split("/").pop()}`,
|
|
expected,
|
|
passed,
|
|
message: passed
|
|
? expected === "valid"
|
|
? "validated cleanly"
|
|
: `rejected (${errors.length} error(s))`
|
|
: expected === "valid"
|
|
? `unexpectedly invalid: ${ajv.errorsText(errors)}`
|
|
: `unexpectedly valid (no errors raised)`,
|
|
});
|
|
}
|
|
}
|
|
|
|
return outcomes;
|
|
}
|
|
|
|
function main(): void {
|
|
const ajv = loadSchema();
|
|
const outcomes = runServerCardExamples(ajv);
|
|
|
|
if (outcomes.length === 0) {
|
|
console.error(`No examples found under ${EXAMPLES_DIR}/.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
let failed = 0;
|
|
for (const o of outcomes) {
|
|
const status = o.passed ? "✓" : "✗";
|
|
console.log(`${status} ${o.name} — ${o.message}`);
|
|
if (!o.passed) failed++;
|
|
}
|
|
|
|
console.log();
|
|
if (failed > 0) {
|
|
console.error(`${failed} of ${outcomes.length} example(s) failed.`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`All ${outcomes.length} example(s) passed.`);
|
|
}
|
|
|
|
main();
|