import { describe, expect, it } from "vitest"; import { ROLE_ACTIONS, canRole, shareVisibility, type Share } from "./rules.js"; const user = { userId: "u_1", userTeams: ["tms_1", "tms_2"] }; const outsider = { userId: "u_2", userTeams: ["tms_3"] }; describe("canRole — static matrix", () => { it("owner can do everything", () => { for (const action of ROLE_ACTIONS) { expect(canRole("owner", action), action).toBe(true); } }); it("admin can manage but not delete the workspace", () => { expect(canRole("admin", "manage_members")).toBe(true); expect(canRole("admin", "invite")).toBe(true); expect(canRole("admin", "manage_permissions")).toBe(true); expect(canRole("admin", "manage_settings")).toBe(true); expect(canRole("admin", "delete_workspace")).toBe(false); expect(canRole("admin", "export_data")).toBe(true); }); it("member has no management actions", () => { for (const action of ROLE_ACTIONS) { expect(canRole("member", action), action).toBe(false); } }); it("guest has no management actions", () => { for (const action of ROLE_ACTIONS) { expect(canRole("guest", action), action).toBe(false); } }); it("throws on unknown roles", () => { expect(() => canRole("superuser" as never, "invite")).toThrow(/unknown workspace role/); }); }); describe("shareVisibility", () => { const shares: [string, Share][] = [ ["public", { scope: "public", level: "view", slug: "abc" }], ["workspace", { scope: "workspace", level: "comment" }], ["team (member)", { scope: "team", level: "edit", teamId: "tms_1" }], ["team (other)", { scope: "team", level: "edit", teamId: "tms_9" }], ["users (listed)", { scope: "users", level: "view", userIds: ["u_1", "u_3"] }], ["users (unlisted)", { scope: "users", level: "view", userIds: ["u_3"] }], ["private", { scope: "private", level: "full_access" }], ]; it.each(shares)( "%s: visible to in-scope user, not to outsider (except public/workspace)", (label, share) => { const expectedUser = share.scope === "public" || share.scope === "workspace" || (share.scope === "team" && share.teamId === "tms_1") || (share.scope === "users" && (share.userIds ?? []).includes("u_1")); const expectedOutsider = share.scope === "public" || share.scope === "workspace" || (share.scope === "team" && share.teamId === "tms_3") || (share.scope === "users" && (share.userIds ?? []).includes("u_2")); expect(shareVisibility(share, user)).toBe(expectedUser); expect(shareVisibility(share, outsider)).toBe(expectedOutsider); }, ); it("private shares are never visible", () => { expect(shareVisibility({ scope: "private", level: "view" }, user)).toBe(false); expect(shareVisibility({ scope: "private", level: "view" }, outsider)).toBe(false); }); it("password/slug do not affect visibility", () => { const base: Share = { scope: "public", level: "view" }; const withExtras: Share = { scope: "public", level: "view", password: "hunter2", slug: "x" }; expect(shareVisibility(withExtras, user)).toBe(shareVisibility(base, user)); }); });