fix: harden dashboard model validation
This commit is contained in:
parent
7cfd5b4069
commit
74651a49de
4 changed files with 288 additions and 13 deletions
|
|
@ -54,6 +54,77 @@ describe("dashboard model validation", () => {
|
|||
}
|
||||
});
|
||||
|
||||
it("includes offending additional property names in errors", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.metadata.unexpected = true;
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
if (!result.valid) {
|
||||
expect(result.errors.join(" ")).toContain("unexpected");
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects non-finite numbers that cannot roundtrip through JSON", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.telemetry[0].value.value = Number.NaN;
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
if (!result.valid) {
|
||||
expect(result.errors.join(" ")).toContain("finite JSON number");
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects dangling layout references", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.layout.telemetry.push("missing-card");
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
if (!result.valid) {
|
||||
expect(result.errors.join(" ")).toContain("missing-card");
|
||||
expect(result.errors.join(" ")).toContain("must reference an existing item");
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects duplicate IDs within collections", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.telemetry[1].id = invalid.telemetry[0].id;
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
if (!result.valid) {
|
||||
expect(result.errors.join(" ")).toContain("must be unique");
|
||||
expect(result.errors.join(" ")).toContain(invalid.telemetry[0].id);
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects string values for numeric metric kinds", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.telemetry[0].value.value = "not a percent";
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects contradictory warning and danger thresholds", () => {
|
||||
const invalid = JSON.parse(JSON.stringify(genericDashboardFixture));
|
||||
invalid.telemetry[0].thresholds = { warning: 90, danger: 80 };
|
||||
|
||||
const result = validateDashboardDocument(invalid);
|
||||
|
||||
expect(result.valid).toBe(false);
|
||||
if (!result.valid) {
|
||||
expect(result.errors.join(" ")).toContain("warning threshold");
|
||||
}
|
||||
});
|
||||
|
||||
it("exports JSON Schema for external tool contracts", () => {
|
||||
expect(dashboardDocumentJsonSchema.$id).toContain("dashboard-document.v1");
|
||||
expect(dashboardDocumentJsonSchema.properties).toHaveProperty("schemaVersion");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue