testParameterSchemasCheckNetworkArguments

tcmts.core.test.hash.testParameterSchemasCheckNetworkArguments · #e47rabcd · term

Parameter schemas check arguments arriving from the network.

import { checkArgs } from "#codebase/tcmts/core/schema";
import { analyze } from "#codebase/tcmts/core/test/hash";
import assert from "node:assert/strict";

export const testParameterSchemasCheckNetworkArguments = async () => {
  const [def] = analyze(`
    type Tree = { v: number; kids: Tree[] };
    export async function save(name: string, opts: { limit?: number; tags: string[] }, when: Date, mode: "a" | "b", tree: Tree, ...extra: number[]) {}
  `).defs.filter((d) => d.nameHint === "save");
  const p = def!.params!;
  assert.deepEqual(p.params.map((x) => x.name), ["name", "opts", "when", "mode", "tree", "extra"]);
  const tree = { v: 1, kids: [{ v: 2, kids: [] }] };
  const ok = ["ada", { tags: ["x"] }, new Date(0), "a", tree, 1, 2];
  assert.equal(checkArgs(p, ok), undefined);
  assert.match(checkArgs(p, [42, ...ok.slice(1)])!, /argument `name` should be a string, got number 42/);
  assert.match(checkArgs(p, ["ada", { tags: ["x"], isAdmin: true }, ...ok.slice(2)])!, /`opts`\.isAdmin isn't a field it accepts/);
  assert.match(checkArgs(p, ["ada", {}, ...ok.slice(2)])!, /`opts`\.tags is missing/);
  assert.match(checkArgs(p, ["ada", { tags: ["x"] }, new Date(0), "c", tree])!, /mode` should be "a" \| "b"/);
  assert.match(checkArgs(p, ["ada", { tags: ["x"] }, new Date(0), "a", { v: 1, kids: [{ v: "deep", kids: [] }] }])!, /tree`\.kids\[0\]\.v should be a number/);
  assert.match(checkArgs(p, [...ok.slice(0, 5), 1, "two"])!, /extra`\[1\] should be a number/);
}

uses