test.govlab/context/core/validators/field.validator.test.ts
test.govlab/context/core/validators/field.validator.test.ts is a file in Codebase Testing. 79 lines of code and 0 definitions.
import {
danglingFields,
emptyFields,
recordDefects,
refuseRecord,
} from "@govlab/context/core/validators/field.validator.ts";
import assert from "node:assert/strict";
import { bundledReason } from "./ontology.fixture.ts";
import { schemaOf } from "@govlab/context/core/selectors/reason.selector.ts";
import { test } from "vitest";
const SCHEMA = {
id: { required: true, type: "label" },
nested: { required: false, type: "object" },
"nested.note": { required: false, type: "text" },
parts: { required: true, target: "reasoning:part", type: "refs" },
size: { required: false, type: "flag" },
text: { required: true, type: "text" },
} as const;
const CLEAN = { id: "a-record", parts: ["p1"], text: "a statement" };
test("recordDefects passes a clean record and names each missing, mistyped or ill-formed field", () => {
assert.deepEqual(recordDefects(SCHEMA, CLEAN), []);
assert.deepEqual(recordDefects(SCHEMA, { id: "a-record", parts: ["p1", 2], size: "big" }), [
"has parts set to something other than a list of record ids",
"has size set to something other than true or false",
"has no text, which its kind requires",
]);
assert.deepEqual(recordDefects(SCHEMA, { ...CLEAN, id: "A_Record" }), [
'has the id "A_Record", which is not kebab-case',
]);
assert.deepEqual(recordDefects(SCHEMA, { ...CLEAN, nested: { note: 3 } }), [
"has nested.note set to something other than a string",
]);
});
test("recordDefects leaves a present but blank required value to emptyFields", () => {
const blank = { ...CLEAN, parts: [], text: " " };
assert.deepEqual(recordDefects(SCHEMA, blank), []);
assert.deepEqual(emptyFields(SCHEMA, blank), ["parts", "text"]);
});
test("emptyFields accepts none with a reason and refuses a bare none", () => {
assert.deepEqual(emptyFields(SCHEMA, { ...CLEAN, text: "none: nothing enforces it yet" }), []);
assert.deepEqual(emptyFields(SCHEMA, { ...CLEAN, text: "none" }), ["text"]);
});
test("refuseRecord throws with the subject, kind, id and every defect", () => {
assert.doesNotThrow(() => {
refuseRecord("probe", "sample", SCHEMA, CLEAN);
});
assert.throws(
() => {
refuseRecord("probe", "sample", SCHEMA, { id: "a-record", parts: [] });
},
{ message: 'probe: the sample "a-record" has no text, which its kind requires' },
);
});
test("a bundled technique with no fails field is refused at load", () => {
const [technique] = bundledReason().techniques;
assert.ok(technique, "the bundled reasoning data holds a technique");
const failless = Object.fromEntries(Object.entries(technique).filter(([key]) => key !== "fails"));
assert.throws(
() => {
refuseRecord("reason", "technique", schemaOf("technique"), failless);
},
{ message: `reason: the technique "${technique.id}" has no fails, which its kind requires` },
);
});
const members = (target: string): ReadonlySet<string> | undefined =>
target === "reasoning:part" ? new Set(["p1"]) : undefined;
test("danglingFields reports each value its target kind does not hold, and skips an unknown target", () => {
const records = [
{ id: "kept", parts: ["p1"] },
{ id: "lost", parts: ["p1", "p9"] },
];
assert.deepEqual(danglingFields("sample", SCHEMA, records, members), [
{ field: "parts", id: "lost", kind: "sample", target: "reasoning:part", value: "p9" },
]);
assert.deepEqual(
danglingFields("sample", SCHEMA, records, () => {}),
[],
);
});