Files
template-app/modules/documents/__tests__/convex-inclusion.test.ts
T
2026-11-14 09:56:45 +00:00

87 lines
4.1 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
import { readdirSync, readFileSync } from "node:fs"
import { generateConvex } from "@conusai-kit/data-convex"
import { describe, expect, it, vi } from "vitest"
const inclusion = vi.hoisted(() => ({
schemaVersion: 1,
selected: [] as string[],
everAdopted: [] as string[],
}))
vi.mock("../../dist/inclusion.js", () => ({
moduleInclusion: inclusion,
moduleSelected: (id: string) => inclusion.selected.includes(id),
}))
const load = async (selected: string[], adopted = selected) => {
inclusion.selected = selected
inclusion.everAdopted = adopted
vi.resetModules()
const runtime = await import("../../../convex/lib/runtime.js")
const { accountDataOf } = await import("@conusai-kit/tenancy")
return { ...runtime, accountShares: accountDataOf(runtime.registry) }
}
describe("Convex optional inclusion projection (preview only)", () => {
it("commits exactly the generated schema and wrappers for the selected defaults", async () => {
const defaults = JSON.parse(readFileSync(new URL("../../inclusion.json", import.meta.url), "utf8"))
const fresh = await load(defaults.selected, defaults.everAdopted)
const root = new URL("../../../convex/", import.meta.url)
const files = generateConvex(fresh.registry, {
header: "// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0\n",
})
for (const file of files) expect(readFileSync(new URL(file.path, root), "utf8"), file.path).toBe(file.content)
expect(
readdirSync(new URL("generated/", root))
.filter((name) => name.endsWith(".ts"))
.sort(),
).toEqual(
[
...files.filter(({ path }) => path.startsWith("generated/")).map(({ path }) => path.split("/").at(-1)),
"procedures.ts",
...["documents.ts", "guides.ts", "support.ts"].filter(
(name) => !files.some(({ path }) => path === `generated/${name}`),
),
].sort(),
)
})
it("omits fresh optional behavior and preserves original adopted schema and rights on off", async () => {
const ids = ["documents", "guides", "support"]
const fresh = await load([])
// An explicitly empty selection has no callable wrappers, independently of the
// source template's default-on assistance selection.
const freshFiles = generateConvex(fresh.registry)
for (const id of ids) expect(freshFiles.some(({ path }) => path === `generated/${id}.ts`)).toBe(false)
expect(fresh.deployableModules.map(({ id }) => id)).toEqual([
"tenancy",
"auth",
"files",
"proposals",
"notifications",
"branding",
"notes", // kit:notes
"account",
])
expect([...fresh.registry.procedures.keys()].filter((name) => /^(documents|guides|support)\./.test(name))).toEqual(
[],
)
expect(fresh.deployableModules.find(({ id }) => id === "notes")?.extends ?? []).toEqual([]) // kit:notes
expect(fresh.convexCapabilities.actions).not.toContain("documentsActions:process")
const on = await load(ids)
expect(on.convexCapabilities.procedures).toContain("documents.document.list")
const guidesRequirements = on.deployableModules.find(({ id }) => id === "guides")?.serviceRequirements ?? []
expect(guidesRequirements.flatMap(({ operations }) => Object.keys(operations))).toContain(
"guides.runtime.bootstrap",
)
expect(guidesRequirements.flatMap(({ operations }) => Object.keys(operations))).not.toContain(
"guides.runtime.uploadFile",
)
expect(on.deployableModules.find(({ id }) => id === "notes")?.extends?.length).toBeGreaterThan(0) // kit:notes
const off = await load([], ids)
expect(off.convexCapabilities.schema).toEqual(on.convexCapabilities.schema)
expect(off.deployableModules.filter(({ id }) => ids.includes(id)).map(({ id }) => id)).toEqual(ids)
expect(off.convexCapabilities.procedures.filter((name) => /^(documents|guides|support)\./.test(name))).toEqual([])
expect(off.accountShares.map(({ key }) => key)).toEqual(on.accountShares.map(({ key }) => key))
expect(off.convexCapabilities.actions).not.toContain("documentsActions:process")
})
})