Files
calendar/packages/trpc/server/routers/viewer/slots/reserveSlot.handler.test.ts
Alex van AndelGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Somay Chauhan
fde1d671fb refactor: rename SelectedSlotsRepository to PrismaSelectedSlotRepository (#22705)
* refactor: rename SelectedSlotsRepository to PrismaSelectedSlotRepository

- Rename class from SelectedSlotsRepository to PrismaSelectedSlotRepository for consistency
- Update all imports and type references throughout the codebase
- Update DI module bindings and variable names
- Maintain type safety without breaking changes

Co-Authored-By: [email protected] <[email protected]>

* refactor: complete PrismaSelectedSlotRepository rename

- Update DI module binding property name from selectedSlotsRepo to selectedSlotRepo
- Update test mock to use PrismaSelectedSlotRepository class name
- Ensure all references are consistently updated

Co-Authored-By: [email protected] <[email protected]>

* fix: rename file to prismaSelectedSlotRepository.ts and fix plural variable references

- Rename apps/api/v2/src/lib/repositories/prisma-selected-slots.repository.ts to prismaSelectedSlotRepository.ts
- Update class name from PrismaSelectedSlotsRepository to PrismaSelectedSlotRepository
- Fix plural variable reference selectedSlotsRepository to selectedSlotRepository in service
- Update all import paths to reference the new file name
- Maintain consistency with camelCase naming convention

Co-Authored-By: [email protected] <[email protected]>

* fix: rename SelectedSlotsRepositoryFixture to SelectedSlotRepositoryFixture for consistency

- Rename test fixture class from SelectedSlotsRepositoryFixture to SelectedSlotRepositoryFixture (singular)
- Update all import statements in test files to use the renamed class
- Resolves naming mismatch between fixture class and variable declarations
- Fixes TypeScript compilation errors in CI tests

Co-Authored-By: [email protected] <[email protected]>

* feat: add SelectedSlotRepositoryInterface and update DI to use interface

Co-Authored-By: [email protected] <[email protected]>

* refactor: rename selectedSlots.ts to selectedSlot.ts and update all imports

Co-Authored-By: [email protected] <[email protected]>

* fix: update test mock import path after file rename

Co-Authored-By: [email protected] <[email protected]>

* Update apps/api/v2/src/lib/modules/available-slots.module.ts

* Update apps/api/v2/src/lib/modules/available-slots.module.ts

* Implement DTO

* dont declare dependencies locally, duplicating

* Small DTO/token fix

* chore: bump @calcom/platform-libraries from 0.0.266 to 0.0.267

* oops.

* Update fixture names also

* Omg these vscode actions preventing saves

* Final fix, hopefully

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Somay Chauhan <[email protected]>
2025-07-25 16:59:32 -07:00

104 lines
3.8 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/lib/server/repository/PrismaSelectedSlotRepository", () => ({
PrismaSelectedSlotRepository: vi.fn().mockImplementation(() => ({
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/);
});
});