63 lines
2.1 KiB
TypeScript
63 lines
2.1 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import {
|
|
createPersistentTenantDirectory,
|
|
memoryTenantDirectoryStore,
|
|
migrateTenants,
|
|
postgresTenantDirectoryStore,
|
|
} from "../src/index.ts";
|
|
|
|
test("persistent tenant directory stores memberships, workspace access and quota usage", async () => {
|
|
const events: string[] = [];
|
|
const directory = createPersistentTenantDirectory(memoryTenantDirectoryStore(), {
|
|
audit: (event) => {
|
|
events.push(event.action);
|
|
},
|
|
});
|
|
await directory.addMembership({
|
|
tenantId: "acme",
|
|
userId: "u1",
|
|
roles: ["admin"],
|
|
workspaceIds: ["w1"],
|
|
});
|
|
expect(await directory.membership("acme", "u1")).toMatchObject({ roles: ["admin"] });
|
|
expect(await directory.switchWorkspace("acme", "u1", "w1")).toEqual({
|
|
tenantId: "acme",
|
|
workspaceId: "w1",
|
|
});
|
|
await directory.setQuota("acme", "projects", 2);
|
|
expect(await directory.consumeQuota("acme", "projects", 1)).toMatchObject({ usage: 1 });
|
|
await expect(directory.consumeQuota("acme", "projects", 2)).rejects.toThrow("QUOTA");
|
|
expect(events).toEqual(["membership.added", "workspace.switched"]);
|
|
});
|
|
|
|
test("tenant migration orchestrator bounds concurrency and reports isolated failures", async () => {
|
|
let active = 0,
|
|
peak = 0;
|
|
const result = await migrateTenants(
|
|
[{ id: "a" }, { id: "b" }, { id: "bad" }],
|
|
async (tenant) => {
|
|
active++;
|
|
peak = Math.max(peak, active);
|
|
await Promise.resolve();
|
|
active--;
|
|
if (tenant.id === "bad") throw new Error("migration failed");
|
|
},
|
|
{ concurrency: 2, continueOnError: true },
|
|
);
|
|
expect(result.migrated.sort()).toEqual(["a", "b"]);
|
|
expect(result.failed[0]?.tenantId).toBe("bad");
|
|
expect(peak).toBeLessThanOrEqual(2);
|
|
});
|
|
|
|
test("PostgreSQL tenant store parameterizes identities", async () => {
|
|
const calls: unknown[][] = [];
|
|
const store = postgresTenantDirectoryStore({
|
|
async query<T>(_sql: string, params?: unknown[]) {
|
|
calls.push(params ?? []);
|
|
return { rows: [] as T[] };
|
|
},
|
|
});
|
|
await store.putMembership({ tenantId: "tenant", userId: "user" });
|
|
expect(calls[0]?.slice(0, 2)).toEqual(["tenant", "user"]);
|
|
});
|