import { describe, expect, it } from "vitest"; import { readFileSync } from "node:fs"; import { resolve } from "node:path"; const readProjectMembers = () => readFileSync(resolve(__dirname, "./ProjectMembers.vue"), "utf8"); describe("ProjectMembers user directory access", () => { it("does not load the admin-only global user directory", () => { const source = readProjectMembers(); expect(source).not.toContain("fetchUsers"); expect(source).not.toContain("../../api/users"); expect(source).toContain('const canManageMembers = computed(() => permission.can("project.members.manage"));'); expect(source).toContain("if (!canManageMembers.value"); expect(source).toContain("return;"); expect(source).toContain('v-if="canManageMembers"'); expect(source).toContain("listMemberCandidates(projectId.value, { limit: 500 })"); }); it("uses the member API embedded user data when the global directory is unavailable", () => { const source = readProjectMembers(); expect(source).toContain("users.value = members.value"); expect(source).toContain(".map((member) => member.user)"); expect(source).toContain("users.value.find((u) => u.id === m.user_id) || m.user"); }); it("prevents project managers from editing themselves or assigning higher roles", () => { const source = readProjectMembers(); expect(source).toContain("const roleRank: Record"); expect(source).toContain("if (row.user_id === auth.user?.id) return false;"); expect(source).toContain("if (row.user?.is_admin) return false;"); expect(source).toContain("const canAssignRole = (role: string)"); expect(source).toContain(':disabled="!canAssignRole(\'ADMIN\')"'); expect(source).toContain(':disabled="!canEditMember(scope.row)'); }); it("does not offer QA as a project member role preset", () => { const source = readProjectMembers(); expect(source).not.toContain('value="QA"'); expect(source).not.toContain("canAssignRole('QA')"); expect(source).not.toContain("QA: 60"); }); });