Implement RPC contract validation baseline

This commit is contained in:
2026-05-14 15:41:51 -04:00
parent 379c07b50c
commit df367756d0
60 changed files with 10704 additions and 47 deletions

View File

@@ -0,0 +1,33 @@
import { describe, expect, it } from "vitest";
import { RpcRequestSchemas, RpcResponseSchemas, parseRpcRequest } from "./rpcSchemas.js";
describe("RPC schemas", () => {
it("defines request and response schemas for every method", () => {
expect(Object.keys(RpcRequestSchemas).sort()).toEqual(Object.keys(RpcResponseSchemas).sort());
});
it("accepts valid payloads and trims bounded strings", () => {
expect(parseRpcRequest("portfolio.addHolding", { ticker: " cost " })).toEqual({ ticker: "cost" });
expect(parseRpcRequest("model.updateCell", { companyId: "cost", tab: "base", row: 0, col: 1, value: "42" })).toEqual({
companyId: "cost",
tab: "base",
row: 0,
col: 1,
value: "42",
});
});
it("rejects invalid payloads", () => {
expect(() => parseRpcRequest("portfolio.addHolding", { ticker: "" })).toThrow();
expect(() => parseRpcRequest("model.updateCell", { companyId: "cost", tab: "base", row: -1, col: 0, value: "42" })).toThrow();
});
it("rejects scope-mismatched settings updates", () => {
expect(() => parseRpcRequest("settings.update", { scope: "client", changes: { sidebarWidth: 40 } })).toThrow();
expect(() => parseRpcRequest("settings.update", { scope: "server", changes: { dataSources: { sec: "yes" } } })).toThrow();
});
it("catches malformed handler output", () => {
expect(RpcResponseSchemas["memo.updateSection"].safeParse({ section: {}, status: "draft", savedAt: "now" }).success).toBe(false);
});
});