mirror of
https://github.com/hanzoai/calendar.git
synced 2026-09-24 22:42:24 +00:00
106 lines
3.9 KiB
TypeScript
106 lines
3.9 KiB
TypeScript
import { vi, describe, it, expect, afterEach } from "vitest";
|
|
|
|
// We want to test that the UID cookie set by reserveSlotHandler is configured with the correct
|
|
// SameSite and Secure attributes depending on the environment (http vs https).
|
|
// reserveSlotHandler relies on WEBAPP_URL being evaluated at import time, so we need to reset modules
|
|
// between tests after tweaking process.env to simulate different deployment environments.
|
|
//
|
|
// The handler also calls into Prisma and the SelectedSlotRepository, so we stub those parts out.
|
|
|
|
// We alias the module path once we know WEBAPP_URL has been configured.
|
|
const dynamicImportHandler = async () => await import("./reserveSlot.handler");
|
|
|
|
// The repository instance method is used to check for an existing reservation by someone else.
|
|
// To keep this unit test isolated from the database layer, we stub this to always resolve falsey.
|
|
vi.mock("@calcom/features/selectedSlots/repositories/PrismaSelectedSlotRepository", () => ({
|
|
PrismaSelectedSlotRepository: vi.fn().mockImplementation(function () {
|
|
return {
|
|
findReservedByOthers: vi.fn().mockResolvedValue(null),
|
|
};
|
|
}),
|
|
}));
|
|
|
|
// A tiny helper to build a canned handler context with stubbed Prisma methods.
|
|
const buildContext = () => {
|
|
const prismaStub = {
|
|
eventType: {
|
|
// Return a minimal event type that will exercise the happy path.
|
|
findUnique: vi.fn().mockResolvedValue({ users: [{ id: 1 }], seatsPerTimeSlot: null }),
|
|
},
|
|
booking: {
|
|
findFirst: vi.fn().mockResolvedValue(null),
|
|
},
|
|
selectedSlots: {
|
|
upsert: vi.fn().mockResolvedValue(null),
|
|
},
|
|
} as unknown as any;
|
|
|
|
// Capture header values to assert on.
|
|
let cookieHeaderValue: string | null = null;
|
|
const resStub = {
|
|
setHeader: vi.fn((_name: string, value: string) => {
|
|
cookieHeaderValue = value;
|
|
}),
|
|
};
|
|
|
|
const reqStub = {
|
|
cookies: {},
|
|
};
|
|
|
|
return { prismaStub, resStub, reqStub, getCookieHeader: () => cookieHeaderValue };
|
|
};
|
|
|
|
describe("reserveSlotHandler cookie settings", () => {
|
|
const originalWebappUrl = process.env.NEXT_PUBLIC_WEBAPP_URL;
|
|
|
|
afterEach(() => {
|
|
// Reset the module registry and restore the WEBAPP_URL between tests.
|
|
vi.resetModules();
|
|
if (originalWebappUrl === undefined) {
|
|
delete process.env.NEXT_PUBLIC_WEBAPP_URL;
|
|
} else {
|
|
process.env.NEXT_PUBLIC_WEBAPP_URL = originalWebappUrl;
|
|
}
|
|
});
|
|
|
|
it("sets SameSite=None and Secure when WEBAPP_URL is https", async () => {
|
|
process.env.NEXT_PUBLIC_WEBAPP_URL = "https://example.com";
|
|
vi.resetModules();
|
|
const { reserveSlotHandler } = await dynamicImportHandler();
|
|
const { prismaStub, reqStub, resStub, getCookieHeader } = buildContext();
|
|
await reserveSlotHandler({
|
|
ctx: { prisma: prismaStub, req: reqStub, res: resStub },
|
|
input: {
|
|
slotUtcStartDate: new Date().toISOString(),
|
|
slotUtcEndDate: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
|
eventTypeId: 1,
|
|
bookingUid: undefined,
|
|
_isDryRun: false,
|
|
},
|
|
});
|
|
const cookie = getCookieHeader();
|
|
expect(cookie).toMatch(/SameSite=None/);
|
|
expect(cookie).toMatch(/Secure/);
|
|
});
|
|
|
|
it("falls back to SameSite=Lax and no Secure for http WEBAPP_URL", async () => {
|
|
process.env.NEXT_PUBLIC_WEBAPP_URL = "http://localhost:3000";
|
|
vi.resetModules();
|
|
const { reserveSlotHandler } = await dynamicImportHandler();
|
|
const { prismaStub, reqStub, resStub, getCookieHeader } = buildContext();
|
|
await reserveSlotHandler({
|
|
ctx: { prisma: prismaStub, req: reqStub, res: resStub },
|
|
input: {
|
|
slotUtcStartDate: new Date().toISOString(),
|
|
slotUtcEndDate: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
|
|
eventTypeId: 1,
|
|
bookingUid: undefined,
|
|
_isDryRun: false,
|
|
},
|
|
});
|
|
const cookie = getCookieHeader();
|
|
expect(cookie).toMatch(/SameSite=Lax/);
|
|
expect(cookie).not.toMatch(/Secure/);
|
|
});
|
|
});
|