Files
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
f5d345b133 refactor: remove @calcom/web imports from @calcom/features and add @calcom/testing package (#26480)
* fix: remove @calcom/web imports from packages/features to eliminate circular dependency

- Migrate UserTableUser and MemberPermissions types to packages/features/users/types/user-table.ts
- Migrate useGeo hook to packages/features/geo/GeoContext.tsx
- Migrate buildLegacyRequest to packages/lib/buildLegacyCtx.ts
- Migrate Calendar component to packages/features/calendars/weeklyview/components/
- Move test utilities (bookingScenario, fixtures) to packages/features/test/
- Update all imports in packages/features to use new locations
- Add re-exports in apps/web for backward compatibility

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

* fix: delete original implementation files and fix type issues

- Delete original calendar component files in apps/web (keep only re-export stubs)
- Migrate OutOfOfficeInSlots to packages/features/bookings/components
- Convert apps/web OutOfOfficeInSlots to re-export stub
- Fix className vs class issue in Calendar.tsx
- Fix @calcom/trpc import violation in user-table.ts by using structural type

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

* fix: add missing isGroup and contains fields to UserTableUser attributes type

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

* fix: update customRole type to match actual Prisma Role model

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

* fix build

* fix

* fix

* cleanup weeklyview

* fix

* refactor to mv MemberPermissions to types package

* add types dependency to features

* fix

* fix

* fix

* fix

* fix

* fix

* rename

* rename

* migrate

* migrate

* migrate

* fix

* fix

* fix

* refactor: move test utilities from packages/features/test to tests/libs

- Move bookingScenario utilities to tests/libs/bookingScenario
- Move fixtures to tests/libs/fixtures
- Update all imports in packages/features test files to use new location
- Update all imports in apps/web test files to use new location
- Eliminates duplication of test utilities between packages/features and apps/web

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

* fix: correct relative import paths for tests/libs in test files

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

* refactor: replace test utility implementations with re-exports to tests/libs

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

* fix: fix test import paths and move signup handler tests to apps/web

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

* fix: move buildLegacyCtx to packages/lib and restore handlers to packages/features

- Move buildLegacyCtx from apps/web/lib to packages/lib to break circular dependency
- Update apps/web/lib/buildLegacyCtx.ts to re-export from @calcom/lib
- Restore signup handlers and tests to packages/features/auth/signup/handlers
- Update handler imports to use @calcom/lib/buildLegacyCtx instead of @calcom/web/lib/buildLegacyCtx

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

* fix: update recurring-event.test.ts imports to use tests/libs path

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

* refactor: delete test re-export files and update imports to use tests/libs directly

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

* fix: update remaining test imports to use tests/libs directly

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

* fix: update handleRecurringEventBooking calls to match function signature (1 arg)

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

* remove

* migrate tests

* migrate tests

* refactor: update test mock imports by removing  and using async  for mock creators.

* fix type errors

* fix: add type assertion for MockUser in p2002.test-suite.ts

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

* fix: restore locale import in compareReminderBodyToTemplate.test.ts using relative path

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

* feat: create @calcom/testing package and migrate tests from /tests directory

- Created new @calcom/testing package in /packages/testing
- Moved all files from /tests to /packages/testing
- Updated all imports across the codebase to use @calcom/testing alias
- Removed /tests directory at root level

This allows other packages like @calcom/features and @calcom/web to import
testing utilities using the @calcom/testing alias instead of relative paths.

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

* fix

* fix

* fix: add missing useBookings export to @calcom/atoms package

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

* fix: add missing useCalendarsBusyTimes and useConnectedCalendars exports to @calcom/atoms

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

* chore: add @calcom/testing as explicit devDependency to packages that use it

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

* refactor: move setupVitest.ts into @calcom/testing package

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

* fix

* chore: add biome rules to restrict @calcom/testing imports

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

* fix

* rename libs to lib

* rename libs to lib

* add rule

* add rule

* refactor: remove @calcom/features imports from @calcom/testing

- Move mockPaymentSuccessWebhookFromStripe to fresh-booking.test.ts
- Replace ProfileRepository.generateProfileUid() with uuidv4()
- Clone Tracking type into @calcom/testing/src/lib/types.ts
- Update imports in expects.ts and getMockRequestDataForBooking.ts
- Move source files into src/ folder
- Move CalendarManager mock to @calcom/features

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

* fix: add explicit exports for nested paths in @calcom/testing

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

* improve

* improve

* fix

* fix

* fix type checks

* fix type checks

* fix type checks

* fix tests

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-08 16:59:11 +09:00

138 lines
4.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, beforeEach } from "vitest";
import { SIGNUP_ERROR_CODES } from "../../constants";
import type { MockResponse } from "./mocks/next.mocks";
import {
prismaMock,
createP2002Error,
createP2002ErrorWithoutTarget,
createGenericPrismaError,
} from "./mocks/prisma.mocks";
import { createSignupBody, createMockUser } from "./mocks/signup.factories";
import type { SignupBody } from "./mocks/signup.factories";
type CallHandler = (body: SignupBody) => Promise<MockResponse>;
// biome-ignore lint/complexity/noExcessiveLinesPerFunction: test suite contains multiple test cases
export function runP2002TestSuite(
handlerName: string,
callHandler: CallHandler,
setupMocks: () => void
): void {
describe(`${handlerName} – signup P2002 contract`, () => {
describe("P2002 Error Handling (non-token flow)", () => {
beforeEach(setupMocks);
it("returns 409 when target includes 'email'", async () => {
prismaMock.user.create.mockRejectedValue(createP2002Error(["email"]));
const response = await callHandler(createSignupBody());
expect(response.status).toBe(409);
expect(await response.json()).toEqual({
message: SIGNUP_ERROR_CODES.USER_ALREADY_EXISTS,
});
});
it("returns 409 when target includes 'email' among other fields", async () => {
prismaMock.user.create.mockRejectedValue(createP2002Error(["id", "email", "username"]));
const response = await callHandler(createSignupBody());
expect(response.status).toBe(409);
expect(await response.json()).toEqual({
message: SIGNUP_ERROR_CODES.USER_ALREADY_EXISTS,
});
});
it("returns 409 when target is 'username' only", async () => {
prismaMock.user.create.mockRejectedValue(createP2002Error(["username"]));
const response = await callHandler(createSignupBody());
expect(response.status).toBe(409);
expect(await response.json()).toEqual({
message: SIGNUP_ERROR_CODES.USER_ALREADY_EXISTS,
});
});
it("re-throws when target is empty", async () => {
const error = createP2002ErrorWithoutTarget();
prismaMock.user.create.mockRejectedValue(error);
await expect(callHandler(createSignupBody())).rejects.toThrow(error);
});
it("re-throws when target is undefined", async () => {
const error = createP2002Error([]);
error.meta = undefined;
prismaMock.user.create.mockRejectedValue(error);
await expect(callHandler(createSignupBody())).rejects.toThrow(error);
});
it("re-throws non-P2002 Prisma errors", async () => {
const error = createGenericPrismaError();
prismaMock.user.create.mockRejectedValue(error);
await expect(callHandler(createSignupBody())).rejects.toThrow(error);
});
it("re-throws generic errors", async () => {
const error = new Error("Database connection failed");
prismaMock.user.create.mockRejectedValue(error);
await expect(callHandler(createSignupBody())).rejects.toThrow(error);
});
});
describe("Successful Creation", () => {
beforeEach(setupMocks);
it("returns 201 when user is created (non-token flow)", async () => {
prismaMock.user.create.mockResolvedValue(createMockUser() as never);
const response = await callHandler(createSignupBody());
expect(response.status).toBe(201);
});
it("returns 201 when user is created via invite (token flow)", async () => {
prismaMock.user.findUnique.mockResolvedValue(null as never);
prismaMock.user.findFirst.mockResolvedValue(null as never);
prismaMock.user.upsert.mockResolvedValue(createMockUser() as never);
const response = await callHandler(createSignupBody({ token: "valid-token" }));
expect(response.status).toBe(201);
});
});
describe("Invite flow - existing user validation", () => {
beforeEach(setupMocks);
it("returns 409 when user exists but was not invited to this team", async () => {
prismaMock.user.findUnique.mockResolvedValue({ id: 99, invitedTo: 999 } as never);
const response = await callHandler(createSignupBody({ token: "valid-token" }));
expect(response.status).toBe(409);
expect(await response.json()).toEqual({
message: SIGNUP_ERROR_CODES.USER_ALREADY_EXISTS,
});
});
it("returns 201 when user exists and was invited to this team", async () => {
prismaMock.user.findUnique.mockResolvedValue({ id: 99, invitedTo: 1 } as never);
prismaMock.user.findFirst.mockResolvedValue(null as never);
prismaMock.user.upsert.mockResolvedValue(createMockUser() as never);
const response = await callHandler(createSignupBody({ token: "valid-token" }));
expect(response.status).toBe(201);
});
});
});
}