59 lines
2.8 KiB
TypeScript
59 lines
2.8 KiB
TypeScript
// What the generated tenant-isolation suite (test/isolation.test.ts) needs of this module, from this
|
|
// folder: the rows it seeds in each tenant, and one fixture per tenant-scoped procedure. The suite
|
|
// finds this file by its place, so a module added with `pnpm new:module` has its fixtures read
|
|
// without a line outside its folder; a procedure with no fixture fails the suite by name.
|
|
//
|
|
// A fixture is built from the *other* tenant's ids: the call is made as a member of one
|
|
// organization with another's slugs and ids, and has to be refused -- for being another tenant's, not
|
|
// for naming nothing, which is why `seed` leaves a note, a file and a link in every tenant.
|
|
|
|
import type { TransportCaller } from "@conusai-kit/core"
|
|
import { type IsolationFixture, type IsolationTenant, uploadViaProcedures } from "@conusai-kit/testing"
|
|
|
|
/** What a module's isolation file exports: the shape the suite reads, so it needs no import of the suite. */
|
|
export interface ModuleIsolation {
|
|
seed(
|
|
call: TransportCaller,
|
|
inProject: { org: string; workspace: string; project: string },
|
|
): Promise<Record<string, string>>
|
|
fixtures: Record<string, IsolationFixture>
|
|
}
|
|
|
|
const NOWHERE = "00000000-0000-0000-0000-000000000000"
|
|
const inProjectOf = (t: IsolationTenant) => ({ org: t.orgSlug, workspace: t.workspaceSlug, project: t.projectSlug })
|
|
const noteOf = (t: IsolationTenant) => t.extra.noteId ?? NOWHERE
|
|
|
|
export const isolation: ModuleIsolation = {
|
|
async seed(call, inProject) {
|
|
const note = (await call.callByName("notes.note.create", { ...inProject, title: "Seed note", body: "Seed" })) as {
|
|
noteId: string
|
|
}
|
|
const file = await uploadViaProcedures(call, inProject, {
|
|
filename: "notes-seed.txt",
|
|
contentType: "text/plain",
|
|
bytes: new TextEncoder().encode("seed"),
|
|
})
|
|
const link = (await call.callByName("notes.attachment.add", {
|
|
...inProject,
|
|
noteId: note.noteId,
|
|
fileId: file.fileId,
|
|
})) as { attachmentId: string }
|
|
return { noteId: note.noteId, noteFileId: file.fileId, attachmentId: link.attachmentId }
|
|
},
|
|
fixtures: {
|
|
"notes.note.list": { input: (t) => inProjectOf(t) },
|
|
"notes.note.get": { input: (t) => ({ ...inProjectOf(t), noteId: noteOf(t) }) },
|
|
"notes.note.create": { input: (t) => ({ ...inProjectOf(t), title: "Intruder", body: "x" }) },
|
|
"notes.note.update": {
|
|
input: (t) => ({ ...inProjectOf(t), noteId: noteOf(t), title: "Intruder", body: "x", expectedVersion: 1 }),
|
|
},
|
|
"notes.note.delete": { input: (t) => ({ ...inProjectOf(t), noteId: noteOf(t) }) },
|
|
"notes.attachment.add": {
|
|
input: (t) => ({ ...inProjectOf(t), noteId: noteOf(t), fileId: t.extra.noteFileId ?? NOWHERE }),
|
|
},
|
|
"notes.attachment.remove": {
|
|
input: (t) => ({ ...inProjectOf(t), noteId: noteOf(t), attachmentId: t.extra.attachmentId ?? NOWHERE }),
|
|
},
|
|
},
|
|
}
|