From 1d65755a3ba0715f976c8f5f7a5eb1287377e9e7 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 30 Sep 2026 18:56:46 +0200 Subject: [PATCH] Test: catalog write arguments and the catalog refusal's names and message Stryker on 43ed9396..3763a53c left 20 survivors, in two places: - cultMeshCatalogWriteArguments. No test wrote through a catalog's replace or submitPrediction, so which argument was the context went unobserved. A test now writes through both, in every calling form, and checks the context and value that reached the document. - The catalog refusal's schema names and message. The refusal test now checks both names and that the message names both types. Co-Authored-By: Claude Opus 5.5 --- packages/cultmesh-ts/test/cultmesh.test.ts | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/cultmesh-ts/test/cultmesh.test.ts b/packages/cultmesh-ts/test/cultmesh.test.ts index a665ea00..6b0494f8 100644 --- a/packages/cultmesh-ts/test/cultmesh.test.ts +++ b/packages/cultmesh-ts/test/cultmesh.test.ts @@ -211,6 +211,8 @@ test("CultMesh TS catalogs hold one type per schema and refuse a second, typed", assert.throws(() => catalog.add(kind.handle(second, "doc:second") as any), (error: unknown) => { assert.ok(error instanceof SchemaConflictError, String(error)); assert.equal(error.schemaId, second.schemaId); + assert.deepEqual(error.schemaNames, ["cultmesh.note", "cultmesh.note"]); + assert.ok(error.message.includes(`type "${second.type}"`) && error.message.includes(`type "${first.type}"`), error.message); assert.equal(error.recordKey, ""); return true; }); @@ -229,6 +231,40 @@ test("CultMesh TS catalogs hold one type per schema and refuse a second, typed", } }); +test("CultMesh TS catalog writes take (value, options) or (context, value)", async () => { + const writes: string[] = []; + let current = { noteId: "note:writes", body: "initial" }; + const record = (kind: string) => async (context: { runtimeId: string }, value: Note) => { + writes.push(`${kind}:${context.runtimeId}:${value.body}`); + current = value; + }; + const catalog = CultMesh.documents(CultMesh.document("note:writes", noteDocument, async () => current, { + replaceDocument: record("replace"), + submitPrediction: record("predict"), + })); + const note = (body: string) => ({ noteId: "note:writes", body }); + + await catalog.replace(noteDocument, note("r1")); + await catalog.replace(noteDocument, note("r2"), {}); + await catalog.replace(noteDocument, note("r3"), { context: "pilot-a" }); + await catalog.replace(noteDocument, "pilot-b", note("r4")); + await catalog.replace(noteDocument, CultMesh.queryContext("pilot-c"), note("r5")); + await catalog.submitPrediction(noteDocument, note("p1")); + await catalog.submitPrediction(noteDocument, note("p2"), { context: "pilot-a" }); + await catalog.submitPrediction(noteDocument, "pilot-b", note("p3")); + + assert.deepEqual(writes, [ + "replace:local:r1", + "replace:local:r2", + "replace:pilot-a:r3", + "replace:pilot-b:r4", + "replace:pilot-c:r5", + "predict:local:p1", + "predict:pilot-a:p2", + "predict:pilot-b:p3", + ]); +}); + test("CultMesh TS document handles submit predictions through configured authority hooks", async () => { let current = { noteId: "note:prediction",