690 files changed
+12045
-33943
No files matched your search
@@ -0,0 +1,104 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { PermissionDeniedError, assertCanAccessAppointment, canAccessAppointment } from "../authorization";
|
||||
|
||||
/**
|
||||
* The registered-customer branch never touches the database (it's a plain
|
||||
* userId comparison), so it's tested here in isolation. The guest-token
|
||||
* branch's real hash/expiry/revocation behaviour is covered against a real
|
||||
* database in customer-booking.integration.test.ts — this file only checks
|
||||
* that authorization.ts calls into validateGuestAccessToken correctly and
|
||||
* respects its result.
|
||||
*/
|
||||
vi.mock("@/services/scheduling/guest-access.service", () => ({
|
||||
validateGuestAccessToken: vi.fn(),
|
||||
}));
|
||||
|
||||
const { validateGuestAccessToken } = await import("@/services/scheduling/guest-access.service");
|
||||
const mockValidate = vi.mocked(validateGuestAccessToken);
|
||||
|
||||
beforeEach(() => {
|
||||
mockValidate.mockClear();
|
||||
});
|
||||
|
||||
// Not a real PrismaClient — the mocked guest-access service never touches it.
|
||||
const prisma = {} as never;
|
||||
|
||||
describe("assertCanAccessAppointment", () => {
|
||||
it("allows a registered customer to access their own appointment", async () => {
|
||||
await expect(
|
||||
assertCanAccessAppointment(prisma, { id: "a1", customer: { userId: "user_1" } }, { sessionUserId: "user_1" }),
|
||||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("denies a different signed-in user from accessing a registered customer's appointment", async () => {
|
||||
await expect(
|
||||
assertCanAccessAppointment(prisma, { id: "a1", customer: { userId: "user_1" } }, { sessionUserId: "user_2" }),
|
||||
).rejects.toThrow(PermissionDeniedError);
|
||||
});
|
||||
|
||||
it("denies an unauthenticated caller from accessing a registered customer's appointment", async () => {
|
||||
await expect(
|
||||
assertCanAccessAppointment(prisma, { id: "a1", customer: { userId: "user_1" } }, { sessionUserId: undefined }),
|
||||
).rejects.toThrow(PermissionDeniedError);
|
||||
});
|
||||
|
||||
it("never even calls the guest-token validator for a registered customer's appointment", async () => {
|
||||
mockValidate.mockClear();
|
||||
await assertCanAccessAppointment(
|
||||
prisma,
|
||||
{ id: "a1", customer: { userId: "user_1" } },
|
||||
{ sessionUserId: "user_1" },
|
||||
).catch(() => {});
|
||||
expect(mockValidate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows a guest appointment when the guest-token validator confirms the token", async () => {
|
||||
mockValidate.mockResolvedValueOnce(true);
|
||||
await expect(
|
||||
assertCanAccessAppointment(
|
||||
prisma,
|
||||
{ id: "a1", customer: { userId: null } },
|
||||
{ sessionUserId: undefined, guestToken: "correct-token" },
|
||||
),
|
||||
).resolves.toBeUndefined();
|
||||
expect(mockValidate).toHaveBeenCalledWith(prisma, { appointmentId: "a1", rawToken: "correct-token" });
|
||||
});
|
||||
|
||||
it("denies a guest appointment when no token is supplied at all — the appointment id is no longer sufficient", async () => {
|
||||
await expect(
|
||||
assertCanAccessAppointment(prisma, { id: "a1", customer: { userId: null } }, { sessionUserId: undefined }),
|
||||
).rejects.toThrow(PermissionDeniedError);
|
||||
expect(mockValidate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("denies a guest appointment when the guest-token validator rejects the token", async () => {
|
||||
mockValidate.mockResolvedValueOnce(false);
|
||||
await expect(
|
||||
assertCanAccessAppointment(
|
||||
prisma,
|
||||
{ id: "a1", customer: { userId: null } },
|
||||
{ sessionUserId: undefined, guestToken: "wrong-token" },
|
||||
),
|
||||
).rejects.toThrow(PermissionDeniedError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("canAccessAppointment", () => {
|
||||
it("mirrors assertCanAccessAppointment as a boolean", async () => {
|
||||
expect(
|
||||
await canAccessAppointment(prisma, { id: "a1", customer: { userId: "user_1" } }, { sessionUserId: "user_1" }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
await canAccessAppointment(prisma, { id: "a1", customer: { userId: "user_1" } }, { sessionUserId: "user_2" }),
|
||||
).toBe(false);
|
||||
|
||||
mockValidate.mockResolvedValueOnce(true);
|
||||
expect(
|
||||
await canAccessAppointment(
|
||||
prisma,
|
||||
{ id: "a1", customer: { userId: null } },
|
||||
{ sessionUserId: undefined, guestToken: "correct-token" },
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user