From f3eefc1ffa795eb887468315a649ca5f9fd9f209 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:43:32 +0530 Subject: [PATCH 01/10] cleanup(test): remove team-seeded event type integration coverage (#29010) --- ...getEventTypesFromGroup.integration-test.ts | 126 ------------------ 1 file changed, 126 deletions(-) diff --git a/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.integration-test.ts b/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.integration-test.ts index 148d4d3b6718f3..1f63c94dc2e088 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.integration-test.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.integration-test.ts @@ -1,7 +1,6 @@ import { describe, it, expect } from "vitest"; import prisma from "@calcom/prisma"; -import { SchedulingType } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; import { getEventTypesFromGroup } from "./getEventTypesFromGroup.handler"; @@ -10,13 +9,6 @@ describe("getEventTypesFromGroup", async () => { const proUser = await prisma.user.findFirstOrThrow({ where: { email: "pro@example.com" } }); const proUserEventTypes = await prisma.eventType.findMany({ where: { userId: proUser.id } }); - const teamProUser = await prisma.user.findFirstOrThrow({ where: { email: "teampro@example.com" } }); - const teamProMembership = await prisma.membership.findFirstOrThrow({ - where: { userId: teamProUser.id, accepted: true }, - }); - - const teamId = teamProMembership.teamId; - const proUserCtx = { user: { id: proUser.id, @@ -33,63 +25,6 @@ describe("getEventTypesFromGroup", async () => { prisma, }; - const teamProUserCtx = { - user: { - id: teamProUser.id, - name: teamProUser.name, - profile: { - name: teamProUser.name, - organizationId: null, - organization: null, - username: teamProUser.username, - id: null, - upId: "usr-9", - }, - } as NonNullable, - prisma, - }; - - const createManagedEventTypes = async () => { - const childEventType = await prisma.eventType.create({ - data: { - title: "Child Event Type", - slug: "managed-event-type", - schedulingType: null, - length: 30, - userId: teamProUser.id, - }, - }); - - const parentEventType = await prisma.eventType.create({ - data: { - title: "Managed Event Type", - slug: "managed-event-type", - schedulingType: SchedulingType.MANAGED, - length: 30, - teamId, - }, - }); - - // Connect child event type to parent event type - await prisma.eventType.update({ - where: { - id: childEventType.id, - }, - data: { - parent: { - connect: { - id: parentEventType.id, - }, - }, - }, - }); - - return { - parentEventType, - childEventType, - }; - }; - it("should return personal event types for a user", async () => { const ctx = proUserCtx; @@ -113,65 +48,4 @@ describe("getEventTypesFromGroup", async () => { expect(resEventTypeIds).toEqual(expect.arrayContaining(proUserEventTypeIds)); expect(resEventTypeIds.length).toBe(proUserEventTypeIds.length); }); - - it("should return team event types for a user", async () => { - const response = await getEventTypesFromGroup({ - ctx: teamProUserCtx, - input: { - group: { - teamId, - parentId: null, - }, - limit: 10, - cursor: null, - }, - }); - - const resEventTypeIds = response.eventTypes.map((et) => et.id); - - const seededTeamEventTypes = await prisma.eventType.findMany({ where: { teamId } }); - const teamProUserEventTypeIds = seededTeamEventTypes.map((et) => et.id); - - expect(response.eventTypes).toBeDefined(); - expect(response.eventTypes.length).toBeGreaterThan(0); - expect(resEventTypeIds).toEqual(expect.arrayContaining(teamProUserEventTypeIds)); - expect(resEventTypeIds.length).toBe(teamProUserEventTypeIds.length); - }); - - it("should return managed event types event types", async () => { - const { parentEventType, childEventType } = await createManagedEventTypes(); - - const res = await getEventTypesFromGroup({ - ctx: teamProUserCtx, - input: { - group: { - teamId: null, - parentId: null, - }, - limit: 10, - cursor: null, - }, - }); - - const resEventTypeIds = res.eventTypes.map((et) => et.id); - - const managedEventType = await prisma.eventType.findFirstOrThrow({ - where: { - parentId: { - not: null, - }, - schedulingType: null, - userId: teamProUser.id, - }, - }); - - expect(res.eventTypes).toBeDefined(); - expect(resEventTypeIds).toContain(managedEventType.id); - - await deleteEventTypes({ ids: [parentEventType.id, childEventType.id] }); - }); }); - -const deleteEventTypes = async ({ ids }: { ids: number[] }) => { - await prisma.eventType.deleteMany({ where: { id: { in: ids } } }); -}; From 1660adeb537a3524290c6885c6b9feca63cf675b Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:44:05 +0530 Subject: [PATCH 02/10] cleanup(seed): remove platform team seeding from scripts/seed.ts (#29007) * refactor(seed): drop platform team fixtures * refactor(seed): drop platform team helpers * fix(seed): restore team fixture users --- scripts/seed.ts | 273 +++++------------------------------------------- 1 file changed, 26 insertions(+), 247 deletions(-) diff --git a/scripts/seed.ts b/scripts/seed.ts index 32374e80b48125..b100c4c0e5261e 100644 --- a/scripts/seed.ts +++ b/scripts/seed.ts @@ -23,191 +23,6 @@ function hashAPIKey(apiKey: string): string { return createHash("sha256").update(apiKey).digest("hex"); } -type PlatformUser = { - email: string; - password: string; - username: string; - name: string; - completedOnboarding?: boolean; - timeZone?: string; - role?: UserPermissionRole; - theme?: "dark" | "light"; - avatarUrl?: string | null; -}; - -type AssociateUserAndOrgProps = { - teamId: number; - userId: number; - role: MembershipRole; - username: string; -}; - -const checkUnpublishedTeam = async (slug: string) => { - return await prisma.team.findFirst({ - where: { - metadata: { - path: ["requestedSlug"], - equals: slug, - }, - }, - }); -}; - -const setupPlatformUser = async (user: PlatformUser) => { - const { password: _password, ...restOfUser } = user; - const userData = { - ...restOfUser, - emailVerified: new Date(), - completedOnboarding: user.completedOnboarding ?? true, - locale: "en", - schedules: - (user.completedOnboarding ?? true) - ? { - create: { - name: "Working Hours", - availability: { - createMany: { - data: getAvailabilityFromSchedule(DEFAULT_SCHEDULE), - }, - }, - }, - } - : undefined, - }; - - const platformUser = await prisma.user.upsert({ - where: { email_username: { email: user.email, username: user.username } }, - update: userData, - create: userData, - }); - - await prisma.userPassword.upsert({ - where: { userId: platformUser.id }, - update: { - hash: await hashPassword(user.password), - }, - create: { - hash: await hashPassword(user.password), - user: { - connect: { - id: platformUser.id, - }, - }, - }, - }); - - return platformUser; -}; - -const createTeam = async (team: Prisma.TeamCreateInput) => { - try { - const requestedSlug = (team.metadata as z.infer)?.requestedSlug; - if (requestedSlug) { - const unpublishedTeam = await checkUnpublishedTeam(requestedSlug); - if (unpublishedTeam) { - throw Error("Unique constraint failed on the fields"); - } - } - return await prisma.team.create({ - data: { - ...team, - }, - }); - } catch (_err) { - if (_err instanceof Error && _err.message.indexOf("Unique constraint failed on the fields") !== -1) { - console.log(`Team '${team.name}' already exists, skipping.`); - return; - } - throw _err; - } -}; - -const associateUserAndOrg = async ({ teamId, userId, role, username }: AssociateUserAndOrgProps) => { - await prisma.membership.create({ - data: { - createdAt: new Date(), - teamId, - userId, - role: role as MembershipRole, - accepted: true, - }, - }); - - const profile = await prisma.profile.create({ - data: { - uid: uuid(), - username, - organizationId: teamId, - userId, - }, - }); - - await prisma.user.update({ - data: { - movedToProfileId: profile.id, - }, - where: { - id: userId, - }, - }); -}; - -async function createPlatformAndSetupUser({ - teamInput, - user, -}: { - teamInput: Prisma.TeamCreateInput; - user: PlatformUser; -}) { - const team = await createTeam(teamInput); - - const platformUser = await setupPlatformUser(user); - - console.log( - `šŸ‘¤ Upserted '${user.username}' with email "${user.email}" & password "${user.password}". Booking page šŸ‘‰ ${process.env.NEXT_PUBLIC_WEBAPP_URL}/${user.username}` - ); - - const { username } = platformUser; - - const membershipRole = MembershipRole.OWNER; - - if (team) { - await associateUserAndOrg({ - teamId: team.id, - userId: platformUser.id, - role: membershipRole, - username: user.username, - }); - - await prisma.platformBilling.create({ - data: { - id: team?.id, - plan: "SCALE", - customerId: "cus_123", - subscriptionId: "sub_123", - }, - }); - - const clientId = process.env.SEED_PLATFORM_OAUTH_CLIENT_ID; - const secret = process.env.SEED_PLATFORM_OAUTH_CLIENT_SECRET; - - if (clientId && secret) { - await prisma.platformOAuthClient.create({ - data: { - name: "Acme", - redirectUris: ["http://localhost:4321"], - permissions: 1023, - areEmailsEnabled: true, - organizationId: team.id, - id: clientId, - secret, - }, - }); - } - console.log(`\tšŸ‘¤ Added '${teamInput.name}' membership for '${username}' with role '${membershipRole}'`); - } -} - async function createTeamAndAddUsers( teamInput: Prisma.TeamCreateInput, users: { id: number; username: string; role?: MembershipRole }[] = [] @@ -1159,68 +974,6 @@ async function main() { }, }); - const admin = await createUserAndEventType({ - user: { - email: "admin@example.com", - /** To comply with admin password requirements */ - password: "ADMINadmin2022!", - username: "admin", - name: "Admin Example", - role: "ADMIN", - }, - }); - - const clientId = process.env.SEED_OAUTH2_CLIENT_ID; - const clientSecret = process.env.SEED_OAUTH2_CLIENT_SECRET_HASHED; - - if (clientId && clientSecret) { - await createOAuthClientForUser(admin.id, { - clientId, - clientSecret, - name: "atoms examples app oauth 2 client", - purpose: "test atoms examples app with oauth 2", - redirectUri: "http://localhost:4321", - websiteUrl: "http://localhost:4321", - enablePkce: false, - }); - } - - await createPlatformAndSetupUser({ - teamInput: { - name: "Platform Team", - slug: "platform-admin-team", - isPlatform: true, - isOrganization: true, - eventTypes: { - createMany: { - data: [ - { - title: "Collective Seeded Team Event", - slug: "collective-seeded-team-event", - length: 15, - schedulingType: "COLLECTIVE", - }, - { - title: "Round Robin Seeded Team Event", - slug: "round-robin-seeded-team-event", - length: 15, - schedulingType: "ROUND_ROBIN", - }, - ], - }, - }, - createdAt: new Date(), - }, - user: { - email: "platform@example.com", - /** To comply with admin password requirements */ - password: "PLATFORMadmin2024!", - username: "platform", - name: "Platform Admin", - role: "USER", - }, - }); - const pro2UserTeam = await createUserAndEventType({ user: { email: "teampro2@example.com", @@ -1248,6 +1001,32 @@ async function main() { }, }); + const admin = await createUserAndEventType({ + user: { + email: "admin@example.com", + /** To comply with admin password requirements */ + password: "ADMINadmin2022!", + username: "admin", + name: "Admin Example", + role: "ADMIN", + }, + }); + + const clientId = process.env.SEED_OAUTH2_CLIENT_ID; + const clientSecret = process.env.SEED_OAUTH2_CLIENT_SECRET_HASHED; + + if (clientId && clientSecret) { + await createOAuthClientForUser(admin.id, { + clientId, + clientSecret, + name: "atoms examples app oauth 2 client", + purpose: "test atoms examples app with oauth 2", + redirectUri: "http://localhost:4321", + websiteUrl: "http://localhost:4321", + enablePkce: false, + }); + } + if (process.env.E2E_TEST_CALCOM_QA_EMAIL && process.env.E2E_TEST_CALCOM_QA_PASSWORD) { await createUserAndEventType({ user: { From 8b0c3070d1f454797804cf3f7b386bbe821cc17d Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:44:50 +0530 Subject: [PATCH 03/10] cleanup(test): remove team host availability integration coverage (#29011) --- ...etHostsForAvailability.integration-test.ts | 264 ------------------ 1 file changed, 264 deletions(-) delete mode 100644 packages/trpc/server/routers/viewer/eventTypes/getHostsForAvailability.integration-test.ts diff --git a/packages/trpc/server/routers/viewer/eventTypes/getHostsForAvailability.integration-test.ts b/packages/trpc/server/routers/viewer/eventTypes/getHostsForAvailability.integration-test.ts deleted file mode 100644 index 0dc8b4248a3104..00000000000000 --- a/packages/trpc/server/routers/viewer/eventTypes/getHostsForAvailability.integration-test.ts +++ /dev/null @@ -1,264 +0,0 @@ -import prisma from "@calcom/prisma"; -import type { EventType, Team, User } from "@calcom/prisma/client"; -import { MembershipRole, SchedulingType } from "@calcom/prisma/enums"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; - -import { getHostsForAvailabilityHandler } from "./getHostsForAvailability.handler"; -import { getHostsForAssignmentHandler } from "./getHostsForAssignment.handler"; - -let user1: User; -let user2: User; -let user3: User; -let team: Team; -let eventType: EventType; - -describe("getHostsForAvailability and getHostsForAssignment", () => { - beforeAll(async () => { - const timestamp = Date.now(); - - user1 = await prisma.user.create({ - data: { - username: `host-test-1-${timestamp}`, - email: `host-test-1-${timestamp}@example.com`, - name: "Host User 1", - }, - }); - user2 = await prisma.user.create({ - data: { - username: `host-test-2-${timestamp}`, - email: `host-test-2-${timestamp}@example.com`, - name: "Host User 2", - }, - }); - user3 = await prisma.user.create({ - data: { - username: `host-test-3-${timestamp}`, - email: `host-test-3-${timestamp}@example.com`, - name: "Host User 3", - }, - }); - - team = await prisma.team.create({ - data: { - name: `Host Test Team ${timestamp}`, - slug: `host-test-team-${timestamp}`, - members: { - createMany: { - data: [ - { userId: user1.id, role: MembershipRole.ADMIN, accepted: true }, - { userId: user2.id, role: MembershipRole.MEMBER, accepted: true }, - { userId: user3.id, role: MembershipRole.MEMBER, accepted: true }, - ], - }, - }, - }, - }); - - eventType = await prisma.eventType.create({ - data: { - title: "Host Test Event", - slug: `host-test-event-${timestamp}`, - length: 30, - teamId: team.id, - schedulingType: SchedulingType.ROUND_ROBIN, - hosts: { - createMany: { - data: [ - { userId: user1.id, isFixed: true, priority: 1, weight: 100 }, - { userId: user2.id, isFixed: false, priority: 2, weight: 200 }, - { userId: user3.id, isFixed: false, priority: 3, weight: 50 }, - ], - }, - }, - }, - }); - }); - - afterAll(async () => { - try { - if (eventType?.id) { - await prisma.host.deleteMany({ where: { eventTypeId: eventType.id } }); - await prisma.eventType.delete({ where: { id: eventType.id } }); - } - if (team?.id) { - await prisma.team.delete({ where: { id: team.id } }); - } - const userIds = [user1?.id, user2?.id, user3?.id].filter(Boolean); - if (userIds.length > 0) { - await prisma.user.deleteMany({ where: { id: { in: userIds } } }); - } - } catch (error) { - console.warn("Test cleanup failed:", error); - } - }); - - describe("getHostsForAvailability", () => { - it("should return all hosts for an event type", async () => { - const result = await getHostsForAvailabilityHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10 }, - }); - - expect(result.hosts).toHaveLength(3); - expect(result.hasMore).toBe(false); - expect(result.nextCursor).toBeUndefined(); - - const userIds = result.hosts.map((h) => h.userId); - expect(userIds).toContain(user1.id); - expect(userIds).toContain(user2.id); - expect(userIds).toContain(user3.id); - }); - - it("should paginate hosts correctly", async () => { - const page1 = await getHostsForAvailabilityHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 2 }, - }); - - expect(page1.hosts).toHaveLength(2); - expect(page1.hasMore).toBe(true); - expect(page1.nextCursor).toBeDefined(); - - const page2 = await getHostsForAvailabilityHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: page1.nextCursor ?? null, limit: 2 }, - }); - - expect(page2.hosts).toHaveLength(1); - expect(page2.hasMore).toBe(false); - expect(page2.nextCursor).toBeUndefined(); - - // No duplicate hosts across pages - const allUserIds = [...page1.hosts.map((h) => h.userId), ...page2.hosts.map((h) => h.userId)]; - expect(new Set(allUserIds).size).toBe(3); - }); - - it("should return host data with user fields", async () => { - const result = await getHostsForAvailabilityHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10 }, - }); - - const host1 = result.hosts.find((h) => h.userId === user1.id); - expect(host1).toBeDefined(); - expect(host1?.isFixed).toBe(true); - expect(host1?.priority).toBe(1); - expect(host1?.weight).toBe(100); - expect(host1?.name).toBe("Host User 1"); - }); - - it("should filter hosts by search term", async () => { - const result = await getHostsForAvailabilityHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10, search: "Host User 1" }, - }); - - expect(result.hosts).toHaveLength(1); - expect(result.hosts[0].userId).toBe(user1.id); - }); - }); - - describe("getHostsForAssignment", () => { - it("should return all hosts for an event type", async () => { - const result = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10 }, - }); - - expect(result.hosts).toHaveLength(3); - expect(result.hasMore).toBe(false); - - const userIds = result.hosts.map((h) => h.userId); - expect(userIds).toContain(user1.id); - expect(userIds).toContain(user2.id); - expect(userIds).toContain(user3.id); - }); - - it("should paginate hosts correctly", async () => { - const page1 = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 1 }, - }); - - expect(page1.hosts).toHaveLength(1); - expect(page1.hasMore).toBe(true); - expect(page1.nextCursor).toBeDefined(); - - // hasFixedHosts should be present on first page - expect(page1.hasFixedHosts).toBe(true); - - const page2 = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: page1.nextCursor ?? null, limit: 1 }, - }); - - expect(page2.hosts).toHaveLength(1); - expect(page2.hasMore).toBe(true); - - // hasFixedHosts should NOT be present on subsequent pages - expect(page2.hasFixedHosts).toBeUndefined(); - - const page3 = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: page2.nextCursor ?? null, limit: 1 }, - }); - - expect(page3.hosts).toHaveLength(1); - expect(page3.hasMore).toBe(false); - }); - - it("should include email in assignment host data", async () => { - const result = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10 }, - }); - - const host1 = result.hosts.find((h) => h.userId === user1.id); - expect(host1).toBeDefined(); - expect(host1?.email).toContain("host-test-1"); - expect(host1?.name).toBe("Host User 1"); - }); - - it("should filter by memberUserIds when provided", async () => { - const result = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { - eventTypeId: eventType.id, - cursor: null, - limit: 10, - memberUserIds: [user1.id, user2.id], - }, - }); - - expect(result.hosts).toHaveLength(2); - const userIds = result.hosts.map((h) => h.userId); - expect(userIds).toContain(user1.id); - expect(userIds).toContain(user2.id); - expect(userIds).not.toContain(user3.id); - }); - - it("should return zero results for empty memberUserIds array", async () => { - const result = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { - eventTypeId: eventType.id, - cursor: null, - limit: 10, - memberUserIds: [], - }, - }); - - expect(result.hosts).toHaveLength(0); - }); - - it("should filter hosts by search term", async () => { - const result = await getHostsForAssignmentHandler({ - ctx: { user: { id: user1.id } as never, prisma }, - input: { eventTypeId: eventType.id, cursor: null, limit: 10, search: "Host User 2" }, - }); - - expect(result.hosts).toHaveLength(1); - expect(result.hosts[0].userId).toBe(user2.id); - }); - }); -}); From ec1ff7eb6858467be090e72c7fa5562a033cc03a Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:45:21 +0530 Subject: [PATCH 04/10] cleanup(test): remove team duration limit integration coverage (#29015) --- .../durationLimits.integration-test.ts | 213 ------------------ 1 file changed, 213 deletions(-) delete mode 100644 apps/web/test/lib/getSchedule/durationLimits.integration-test.ts diff --git a/apps/web/test/lib/getSchedule/durationLimits.integration-test.ts b/apps/web/test/lib/getSchedule/durationLimits.integration-test.ts deleted file mode 100644 index 18db56fb6cadf3..00000000000000 --- a/apps/web/test/lib/getSchedule/durationLimits.integration-test.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { afterAll, beforeAll, describe, test, vi } from "vitest"; - -import { getAvailableSlotsService } from "@calcom/features/di/containers/AvailableSlots"; -import { prisma } from "@calcom/prisma"; -import type { EventType, Schedule, Team, User } from "@calcom/prisma/client"; -import { BookingStatus, MembershipRole, SchedulingType } from "@calcom/prisma/enums"; - -import { expect } from "./expects"; - -describe("getSchedule duration limits (integration)", () => { - let user1: User; - let user2: User; - let team: Team; - let schedule1: Schedule; - let schedule2: Schedule; - let eventType: EventType; - const createdBookingIds: number[] = []; - - beforeAll(async () => { - const timestamp = Date.now(); - - vi.stubEnv("UPSTASH_REDIS_REST_URL", undefined); - vi.stubEnv("UPSTASH_REDIS_REST_TOKEN", undefined); - - [user1, user2] = await Promise.all([ - prisma.user.create({ - data: { - username: `dur-limit-user-1-${timestamp}`, - name: "Duration Limit User 1", - email: `dur-limit-user-1-${timestamp}@example.com`, - }, - }), - prisma.user.create({ - data: { - username: `dur-limit-user-2-${timestamp}`, - name: "Duration Limit User 2", - email: `dur-limit-user-2-${timestamp}@example.com`, - }, - }), - ]); - - [schedule1, schedule2] = await Promise.all([ - prisma.schedule.create({ - data: { - name: `Schedule 1 ${timestamp}`, - userId: user1.id, - timeZone: "UTC", - }, - }), - prisma.schedule.create({ - data: { - name: `Schedule 2 ${timestamp}`, - userId: user2.id, - timeZone: "UTC", - }, - }), - ]); - - await prisma.availability.createMany({ - data: [ - { - scheduleId: schedule1.id, - days: [0, 1, 2, 3, 4, 5, 6], - startTime: new Date("1970-01-01T09:00:00.000Z"), - endTime: new Date("1970-01-01T17:00:00.000Z"), - }, - { - scheduleId: schedule2.id, - days: [0, 1, 2, 3, 4, 5, 6], - startTime: new Date("1970-01-01T09:00:00.000Z"), - endTime: new Date("1970-01-01T17:00:00.000Z"), - }, - ], - }); - - await Promise.all([ - prisma.user.update({ - where: { id: user1.id }, - data: { defaultScheduleId: schedule1.id }, - }), - prisma.user.update({ - where: { id: user2.id }, - data: { defaultScheduleId: schedule2.id }, - }), - ]); - - team = await prisma.team.create({ - data: { - name: `Duration Limit Team ${timestamp}`, - slug: `duration-limit-team-${timestamp}`, - }, - }); - - await prisma.membership.createMany({ - data: [ - { - userId: user1.id, - teamId: team.id, - role: MembershipRole.ADMIN, - accepted: true, - }, - { - userId: user2.id, - teamId: team.id, - role: MembershipRole.MEMBER, - accepted: true, - }, - ], - }); - - eventType = await prisma.eventType.create({ - data: { - title: "Duration Limit Event", - slug: `duration-limit-event-${timestamp}`, - length: 30, - slotInterval: 30, - teamId: team.id, - userId: user1.id, - schedulingType: SchedulingType.ROUND_ROBIN, - durationLimits: { PER_YEAR: 480 }, - users: { - connect: [{ id: user1.id }, { id: user2.id }], - }, - hosts: { - createMany: { - data: [ - { userId: user1.id, isFixed: false }, - { userId: user2.id, isFixed: false }, - ], - }, - }, - }, - }); - - const [booking1, booking2] = await Promise.all([ - prisma.booking.create({ - data: { - uid: `dur-limit-booking-1-${timestamp}`, - title: "Duration Limit Booking 1", - status: BookingStatus.ACCEPTED, - userId: user1.id, - eventTypeId: eventType.id, - startTime: new Date("2026-01-10T00:00:00.000Z"), - endTime: new Date("2026-01-10T06:40:00.000Z"), // 400 minutes - }, - }), - prisma.booking.create({ - data: { - uid: `dur-limit-booking-2-${timestamp}`, - title: "Duration Limit Booking 2", - status: BookingStatus.ACCEPTED, - userId: user2.id, - eventTypeId: eventType.id, - startTime: new Date("2026-01-11T00:00:00.000Z"), - endTime: new Date("2026-01-11T06:40:00.000Z"), // 400 minutes - }, - }), - ]); - - createdBookingIds.push(booking1.id, booking2.id); - }); - - afterAll(async () => { - vi.useRealTimers(); - if (createdBookingIds.length > 0) { - await prisma.booking.deleteMany({ - where: { id: { in: createdBookingIds } }, - }); - } - if (eventType?.id) { - await prisma.eventType.delete({ - where: { id: eventType.id }, - }); - } - await prisma.availability.deleteMany({ - where: { scheduleId: { in: [schedule1?.id, schedule2?.id].filter(Boolean) } }, - }); - await prisma.schedule.deleteMany({ - where: { id: { in: [schedule1?.id, schedule2?.id].filter(Boolean) } }, - }); - await prisma.membership.deleteMany({ - where: { teamId: team?.id }, - }); - if (team?.id) { - await prisma.team.delete({ - where: { id: team.id }, - }); - } - await prisma.user.deleteMany({ - where: { id: { in: [user1?.id, user2?.id].filter(Boolean) } }, - }); - }); - - test("yearly duration limit is enforced event-type-wide", async () => { - vi.setSystemTime("2026-02-01T00:00:00Z"); - const dateString = "2026-02-10"; - - const availableSlotsService = getAvailableSlotsService(); - const scheduleForEvent = await availableSlotsService.getAvailableSlots({ - input: { - eventTypeId: eventType.id, - eventTypeSlug: "", - startTime: `${dateString}T00:00:00.000Z`, - endTime: `${dateString}T23:59:59.999Z`, - timeZone: "UTC", - isTeamEvent: true, - orgSlug: null, - }, - }); - - expect(scheduleForEvent).toHaveDateDisabled({ dateString }); - }); -}); From 84815a9d2f0b3050cda5d841836595eee6923b1d Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:45:43 +0530 Subject: [PATCH 05/10] cleanup(test): remove round robin booking repository integration coverage (#29021) --- .../BookingRepository.integration-test.ts | 345 ------------------ 1 file changed, 345 deletions(-) delete mode 100644 packages/features/bookings/repositories/BookingRepository.integration-test.ts diff --git a/packages/features/bookings/repositories/BookingRepository.integration-test.ts b/packages/features/bookings/repositories/BookingRepository.integration-test.ts deleted file mode 100644 index b1ce9d4f736732..00000000000000 --- a/packages/features/bookings/repositories/BookingRepository.integration-test.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { describe, it, expect, beforeAll, beforeEach, afterAll, afterEach, vi } from "vitest"; -import { prisma } from "@calcom/prisma"; - -import { BookingStatus, RRTimestampBasis } from "@calcom/prisma/enums"; -import { BookingRepository } from "./BookingRepository"; - -// ------------ -// Test Helpers -// ------------ - -// Track resources to clean up -const createdBookingIds: number[] = []; -let testUserId: number; -let testEventTypeId: number | null = null; - -async function clearTestBookings() { - if (createdBookingIds.length > 0) { - await prisma.attendee.deleteMany({ - where: { bookingId: { in: createdBookingIds } }, - }); - await prisma.booking.deleteMany({ - where: { id: { in: createdBookingIds } }, - }); - createdBookingIds.length = 0; - } -} - -async function createAttendeeNoShowTestBookings() { - // Booking 1: 00:00-01:00 - const booking1 = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "uid-1", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - attendees: { - create: { - email: "test1@example.com", - noShow: false, - name: "Test 1", - timeZone: "America/Toronto", - }, - }, - startTime: new Date("2025-05-01T00:00:00.000Z"), - endTime: new Date("2025-05-01T01:00:00.000Z"), - title: "Test Event", - }, - }); - createdBookingIds.push(booking1.id); - - // Booking 2: 01:00-02:00 (different time to avoid idempotencyKey collision) - const booking2 = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "uid-2", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - attendees: { - create: { - email: "test1@example.com", - noShow: true, - name: "Test 1", - timeZone: "America/Toronto", - }, - }, - startTime: new Date("2025-05-01T01:00:00.000Z"), - endTime: new Date("2025-05-01T02:00:00.000Z"), - title: "Test Event", - }, - }); - createdBookingIds.push(booking2.id); -} - -async function createHostNoShowTestBookings() { - // Booking 1: 02:00-03:00 (different time to avoid idempotencyKey collision) - const booking1 = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "uid-3", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - noShowHost: false, - attendees: { - create: { - email: "att1@example.com", - noShow: false, - name: "Att 1", - timeZone: "America/Toronto", - }, - }, - startTime: new Date("2025-05-01T02:00:00.000Z"), - endTime: new Date("2025-05-01T03:00:00.000Z"), - title: "Test Event", - }, - }); - createdBookingIds.push(booking1.id); - - // Booking 2: 03:00-04:00 (different time to avoid idempotencyKey collision) - const booking2 = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "uid-4", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - noShowHost: true, - attendees: { - create: { - email: "att2@example.com", - noShow: false, - name: "Att 2", - timeZone: "America/Toronto", - }, - }, - startTime: new Date("2025-05-01T03:00:00.000Z"), - endTime: new Date("2025-05-01T04:00:00.000Z"), - title: "Test Event", - }, - }); - createdBookingIds.push(booking2.id); -} - -// ----------------- -// Actual Test Suite -// ----------------- - -describe("BookingRepository (Integration Tests)", () => { - beforeAll(async () => { - // Use existing seed user - const testUser = await prisma.user.findFirstOrThrow({ - where: { email: "member0-acme@example.com" }, - }); - testUserId = testUser.id; - - // Find or create a test event type for this user - let eventType = await prisma.eventType.findFirst({ - where: { userId: testUserId }, - }); - - if (!eventType) { - eventType = await prisma.eventType.create({ - data: { - title: "Test Event Type", - slug: `test-event-type-${Date.now()}`, - length: 30, - userId: testUserId, - }, - }); - testEventTypeId = eventType.id; // Track for cleanup - } else { - testEventTypeId = eventType.id; // Use existing, don't clean up - } - }); - - afterAll(async () => { - // Only delete event type if we created it - if (testEventTypeId) { - const eventType = await prisma.eventType.findUnique({ - where: { id: testEventTypeId }, - select: { slug: true }, - }); - if (eventType?.slug.startsWith("test-event-type-")) { - await prisma.eventType.delete({ - where: { id: testEventTypeId }, - }); - } - } - }); - - beforeEach(async () => { - vi.setSystemTime(new Date("2025-05-01T00:00:00.000Z")); - }); - - afterEach(async () => { - await clearTestBookings(); - vi.useRealTimers(); - }); - - describe("getAllBookingsForRoundRobin", () => { - describe("includeNoShowInRRCalculation", () => { - it("should not include bookings where attendee is a no-show", async () => { - await createAttendeeNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: false, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(1); - }); - - it("should include attendee no-shows when enabled", async () => { - await createAttendeeNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: true, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(2); - }); - - it("should not include bookings where host is a no-show", async () => { - await createHostNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: false, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(1); - }); - - it("should include host no-shows when enabled", async () => { - await createHostNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: true, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(2); - }); - - it("should not include ANY host/attendee no-shows when disabled", async () => { - await createHostNoShowTestBookings(); - await createAttendeeNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: false, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(2); - }); - - it("should include ALL host/attendee no-shows when enabled", async () => { - await createHostNoShowTestBookings(); - await createAttendeeNoShowTestBookings(); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "organizer1@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-05-01T00:00:00.000Z"), - endDate: new Date("2025-05-01T23:59:59.999Z"), - includeNoShowInRRCalculation: true, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(4); - }); - }); - - it("should filter by startTime when rrTimestampBasis=START_TIME", async () => { - const mayBooking = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "booking_may", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - attendees: { - create: { - email: "test@example.com", - noShow: false, - name: "Test", - timeZone: "UTC", - }, - }, - startTime: new Date("2025-05-26T00:00:00.000Z"), - endTime: new Date("2025-05-26T01:00:00.000Z"), - createdAt: new Date("2025-05-03T00:00:00.000Z"), - title: "Test May", - }, - }); - createdBookingIds.push(mayBooking.id); - - const juneBooking = await prisma.booking.create({ - data: { - userId: testUserId, - uid: "booking_june", - eventTypeId: testEventTypeId, - status: BookingStatus.ACCEPTED, - attendees: { - create: { - email: "test@example.com", - noShow: true, - name: "Test", - timeZone: "UTC", - }, - }, - startTime: new Date("2025-06-26T00:00:00.000Z"), - endTime: new Date("2025-06-26T01:00:00.000Z"), - createdAt: new Date("2025-05-03T00:00:00.000Z"), - title: "Test June", - }, - }); - createdBookingIds.push(juneBooking.id); - - const bookingRepo = new BookingRepository(prisma); - const bookings = await bookingRepo.getAllBookingsForRoundRobin({ - users: [{ id: testUserId, email: "org@example.com" }], - eventTypeId: testEventTypeId, - startDate: new Date("2025-06-01T00:00:00.000Z"), - endDate: new Date("2025-06-30T23:59:59.999Z"), - includeNoShowInRRCalculation: true, - virtualQueuesData: null, - rrTimestampBasis: RRTimestampBasis.START_TIME, - }); - - expect(bookings).toHaveLength(1); - expect(bookings[0].startTime.toISOString()).toBe("2025-06-26T00:00:00.000Z"); - }); - }); -}); From 9d481454bf22bd39676d3622c57d77310235d9a0 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:46:20 +0530 Subject: [PATCH 06/10] cleanup(test): remove team bookings handler integration coverage (#29017) --- .../bookings/get.handler.integration-test.ts | 85 ++----------------- 1 file changed, 5 insertions(+), 80 deletions(-) diff --git a/packages/trpc/server/routers/viewer/bookings/get.handler.integration-test.ts b/packages/trpc/server/routers/viewer/bookings/get.handler.integration-test.ts index 89abd7b376a9dd..da727524b662bc 100644 --- a/packages/trpc/server/routers/viewer/bookings/get.handler.integration-test.ts +++ b/packages/trpc/server/routers/viewer/bookings/get.handler.integration-test.ts @@ -1,19 +1,16 @@ import prisma from "@calcom/prisma"; import kysely from "@calcom/kysely"; -import type { Booking, EventType, Team, User } from "@calcom/prisma/client"; -import { BookingStatus, MembershipRole } from "@calcom/prisma/enums"; +import type { Booking, EventType, User } from "@calcom/prisma/client"; +import { BookingStatus } from "@calcom/prisma/enums"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { getBookings } from "./get.handler"; let user1: User; let user2: User; -let team1: Team; let eventType1: EventType; let booking1: Booking; let booking2: Booking; let booking3: Booking; -let booking4: Booking; -let teamEventType: EventType; const timestamp = Date.now(); @@ -35,29 +32,6 @@ describe("getBookings - integration", () => { }, }); - team1 = await prisma.team.create({ - data: { - name: `GetBookings Team ${timestamp}`, - slug: `getbookings-team-${timestamp}`, - members: { - create: { - userId: user1.id, - role: MembershipRole.ADMIN, - accepted: true, - }, - }, - }, - }); - - await prisma.membership.create({ - data: { - userId: user2.id, - teamId: team1.id, - role: MembershipRole.MEMBER, - accepted: true, - }, - }); - eventType1 = await prisma.eventType.create({ data: { title: `GetBookings Event ${timestamp}`, @@ -127,52 +101,19 @@ describe("getBookings - integration", () => { }, }, }); - - teamEventType = await prisma.eventType.create({ - data: { - title: `GetBookings Team Event ${timestamp}`, - slug: `getbookings-team-event-${timestamp}`, - length: 30, - teamId: team1.id, - }, - }); - - const futureDate4 = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000); - booking4 = await prisma.booking.create({ - data: { - uid: `getbookings-booking4-${timestamp}`, - title: "Team Booking - multi branch", - startTime: futureDate4, - endTime: new Date(futureDate4.getTime() + 30 * 60 * 1000), - userId: user1.id, - eventTypeId: teamEventType.id, - status: BookingStatus.ACCEPTED, - attendees: { - create: { - email: user1.email, - name: user1.name ?? "User 1", - timeZone: "UTC", - }, - }, - }, - }); }); afterAll(async () => { try { - const bookingIds = [booking1?.id, booking2?.id, booking3?.id, booking4?.id].filter(Boolean); + const bookingIds = [booking1?.id, booking2?.id, booking3?.id].filter(Boolean); if (bookingIds.length > 0) { await prisma.attendee.deleteMany({ where: { bookingId: { in: bookingIds } } }); await prisma.booking.deleteMany({ where: { id: { in: bookingIds } } }); } - const eventTypeIds = [eventType1?.id, teamEventType?.id].filter(Boolean); + const eventTypeIds = [eventType1?.id].filter(Boolean); if (eventTypeIds.length > 0) { await prisma.eventType.deleteMany({ where: { id: { in: eventTypeIds } } }); } - const teamIds = [team1?.id].filter(Boolean); - if (teamIds.length > 0) { - await prisma.team.deleteMany({ where: { id: { in: teamIds } } }); - } const userIds = [user1?.id, user2?.id].filter(Boolean); if (userIds.length > 0) { await prisma.user.deleteMany({ where: { id: { in: userIds } } }); @@ -242,7 +183,7 @@ describe("getBookings - integration", () => { skip: 0, }); - const expectedBookingIds = [booking1.id, booking2.id, booking3.id, booking4.id]; + const expectedBookingIds = [booking1.id, booking2.id, booking3.id]; const returnedIds = resultUser1.bookings.map((b) => b.id); for (const id of expectedBookingIds) { expect(returnedIds).toContain(id); @@ -250,22 +191,6 @@ describe("getBookings - integration", () => { expect(resultUser1.totalCount).toBe(resultUser1.bookings.length); }); - it("should count booking4 exactly once in totalCount even though it matches multiple union branches", async () => { - const result = await getBookings({ - user: { id: user1.id, email: user1.email, orgId: null }, - prisma, - kysely, - bookingListingByStatus: ["upcoming"], - filters: {}, - take: 50, - skip: 0, - }); - - const booking4Occurrences = result.bookings.filter((b) => b.id === booking4.id); - expect(booking4Occurrences).toHaveLength(1); - expect(result.totalCount).toBe(result.bookings.length); - }); - it("should respect pagination with correct ordering", async () => { const page1 = await getBookings({ user: { id: user1.id, email: user1.email, orgId: null }, From 03fc126d796bd3d42a433a21bf2f3316081518a8 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:46:45 +0530 Subject: [PATCH 07/10] cleanup(test): remove signup membership integration coverage (#29014) --- ...ateOrUpdateMemberships.integration-test.ts | 472 ------------------ 1 file changed, 472 deletions(-) delete mode 100644 packages/features/auth/signup/utils/createOrUpdateMemberships.integration-test.ts diff --git a/packages/features/auth/signup/utils/createOrUpdateMemberships.integration-test.ts b/packages/features/auth/signup/utils/createOrUpdateMemberships.integration-test.ts deleted file mode 100644 index 9c8e9fcb1215da..00000000000000 --- a/packages/features/auth/signup/utils/createOrUpdateMemberships.integration-test.ts +++ /dev/null @@ -1,472 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; - -import { prisma } from "@calcom/prisma"; -import type { Team, User, OrganizationSettings } from "@calcom/prisma/client"; -import { MembershipRole } from "@calcom/prisma/enums"; - -import { createOrUpdateMemberships } from "./createOrUpdateMemberships"; - -function generateUniqueId() { - return `${Date.now()}-${Math.random().toString(36).substring(7)}`; -} - -async function createTestUser(data: { - email: string; - username: string; - organizationId?: number | null; -}): Promise { - const uniqueId = generateUniqueId(); - const uniqueEmail = data.email.includes("@") - ? data.email.replace("@", `-${uniqueId}@`) - : `${data.email}-${uniqueId}@example.com`; - const uniqueUsername = `${data.username}-${uniqueId}`; - - return await prisma.user.create({ - data: { - email: uniqueEmail, - username: uniqueUsername, - organizationId: data.organizationId ?? undefined, - }, - }); -} - -async function createTestOrganization(data: { - name: string; - slug: string; - orgAutoAcceptEmail?: string; -}): Promise { - const uniqueId = generateUniqueId(); - const uniqueSlug = `${data.slug}-${uniqueId}`; - - const team = await prisma.team.create({ - data: { - name: `${data.name} ${uniqueId}`, - slug: uniqueSlug, - isOrganization: true, - }, - }); - - let organizationSettings: OrganizationSettings | null = null; - if (data.orgAutoAcceptEmail) { - organizationSettings = await prisma.organizationSettings.create({ - data: { - organizationId: team.id, - orgAutoAcceptEmail: data.orgAutoAcceptEmail, - isOrganizationVerified: true, - }, - }); - } - - return { ...team, organizationSettings }; -} - -async function createTestSubteam(data: { name: string; slug: string; parentId: number }): Promise { - const uniqueId = generateUniqueId(); - const uniqueSlug = `${data.slug}-${uniqueId}`; - - return await prisma.team.create({ - data: { - name: `${data.name} ${uniqueId}`, - slug: uniqueSlug, - isOrganization: false, - parentId: data.parentId, - }, - }); -} - -describe("createOrUpdateMemberships Integration Tests", () => { - let testUsers: User[] = []; - let testTeams: Team[] = []; - - beforeEach(() => { - testUsers = []; - testTeams = []; - }); - - afterEach(async () => { - const userIds = testUsers.map((u) => u.id); - const teamIds = testTeams.map((t) => t.id); - - if (userIds.length > 0 || teamIds.length > 0) { - // Clean up in reverse dependency order - await prisma.profile.deleteMany({ - where: { - OR: [{ userId: { in: userIds } }, { organizationId: { in: teamIds } }], - }, - }); - await prisma.membership.deleteMany({ - where: { - OR: [{ userId: { in: userIds } }, { teamId: { in: teamIds } }], - }, - }); - await prisma.organizationSettings.deleteMany({ - where: { organizationId: { in: teamIds } }, - }); - await prisma.team.deleteMany({ - where: { id: { in: teamIds } }, - }); - await prisma.user.deleteMany({ - where: { id: { in: userIds } }, - }); - } - }); - - function trackUser(user: User): User { - testUsers.push(user); - return user; - } - - function trackTeam(team: Team): Team { - testTeams.push(team); - return team; - } - - describe("Organization Direct Membership", () => { - it("should create membership and profile when joining an organization directly", async () => { - // Setup - const org = trackTeam( - await createTestOrganization({ - name: "Test Org", - slug: "test-org", - orgAutoAcceptEmail: "example.com", - }) - ); - - const user = trackUser( - await createTestUser({ - email: "user@example.com", - username: "testuser", - organizationId: org.id, - }) - ); - - // Act - await createOrUpdateMemberships({ - user: { id: user.id }, - team: { - id: org.id, - parentId: org.parentId, - isOrganization: org.isOrganization ?? false, - organizationSettings: { orgAutoAcceptEmail: "example.com" }, - }, - }); - - // Assert - membership created with accepted: true - const membership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: org.id } }, - }); - expect(membership).toBeTruthy(); - expect(membership?.accepted).toBe(true); - expect(membership?.role).toBe(MembershipRole.MEMBER); - - // Assert - profile created - const profile = await prisma.profile.findUnique({ - where: { - userId_organizationId: { userId: user.id, organizationId: org.id }, - }, - }); - expect(profile).toBeTruthy(); - expect(profile?.organizationId).toBe(org.id); - }); - }); - - describe("Sub-Team Membership (within organization)", () => { - it("should create memberships for both team and parent org when joining a sub-team", async () => { - // Setup - const org = trackTeam( - await createTestOrganization({ - name: "Test Org", - slug: "test-org", - orgAutoAcceptEmail: "example.com", - }) - ); - - const subteam = trackTeam( - await createTestSubteam({ - name: "Sub Team", - slug: "sub-team", - parentId: org.id, - }) - ); - - const user = trackUser( - await createTestUser({ - email: "user@example.com", - username: "testuser", - organizationId: org.id, // User already has organizationId set (as done in calcomSignupHandler) - }) - ); - - // Act - await createOrUpdateMemberships({ - user: { id: user.id }, - team: { - id: subteam.id, - parentId: subteam.parentId, - isOrganization: subteam.isOrganization ?? false, - organizationSettings: null, - }, - }); - - // Assert - team membership created - const teamMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: subteam.id } }, - }); - expect(teamMembership).toBeTruthy(); - expect(teamMembership?.accepted).toBe(true); - - // Assert - org membership created - const orgMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: org.id } }, - }); - expect(orgMembership).toBeTruthy(); - expect(orgMembership?.accepted).toBe(true); - }); - - it("should create profile for parent org when joining a sub-team", async () => { - // Setup - const org = trackTeam( - await createTestOrganization({ - name: "Test Org", - slug: "test-org", - orgAutoAcceptEmail: "example.com", - }) - ); - - const subteam = trackTeam( - await createTestSubteam({ - name: "Sub Team", - slug: "sub-team", - parentId: org.id, - }) - ); - - const user = trackUser( - await createTestUser({ - email: "user@example.com", - username: "testuser", - organizationId: org.id, // User already has organizationId set - }) - ); - - // Act - NOTE: We need to pass parent data for profile creation - await createOrUpdateMemberships({ - user: { id: user.id }, - team: { - id: subteam.id, - parentId: subteam.parentId, - isOrganization: subteam.isOrganization ?? false, - organizationSettings: null, - parent: { - id: org.id, - organizationSettings: { orgAutoAcceptEmail: "example.com" }, - }, - }, - }); - - // Assert - profile should be created for the parent organization - const profile = await prisma.profile.findUnique({ - where: { - userId_organizationId: { userId: user.id, organizationId: org.id }, - }, - }); - - // BUG: This assertion will FAIL because profile is not created for sub-team signup - expect(profile).toBeTruthy(); - expect(profile?.organizationId).toBe(org.id); - }); - - it("should handle user invited to sub-team via invite link (new user flow)", async () => { - // This simulates the API v2 invite link flow: - // 1. Token created with identifier: "invite-link-for-teamId-${teamId}" - // 2. User fills in their email and signs up - // 3. User should be added to both team and org with proper profile - - // Setup - const org = trackTeam( - await createTestOrganization({ - name: "Acme Corp", - slug: "acme", - orgAutoAcceptEmail: "acme.com", - }) - ); - - const salesTeam = trackTeam( - await createTestSubteam({ - name: "Sales Team", - slug: "sales", - parentId: org.id, - }) - ); - - // User is created during signup with organizationId already set - // (this happens in calcomSignupHandler.ts:200-232) - const newUser = trackUser( - await createTestUser({ - email: "newuser@acme.com", - username: "newuser", - organizationId: org.id, - }) - ); - - // Act - simulate createOrUpdateMemberships call from calcomSignupHandler - await createOrUpdateMemberships({ - user: { id: newUser.id }, - team: { - id: salesTeam.id, - parentId: salesTeam.parentId, - isOrganization: salesTeam.isOrganization ?? false, - organizationSettings: null, - parent: { - id: org.id, - organizationSettings: { orgAutoAcceptEmail: "acme.com" }, - }, - }, - }); - - // Assert - team membership exists - const teamMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: newUser.id, teamId: salesTeam.id } }, - }); - expect(teamMembership).toBeTruthy(); - expect(teamMembership?.accepted).toBe(true); - - // Assert - org membership exists - const orgMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: newUser.id, teamId: org.id } }, - }); - expect(orgMembership).toBeTruthy(); - expect(orgMembership?.accepted).toBe(true); - - // Assert - profile exists for the organization - // BUG: This will FAIL - the profile is not created for sub-team invites - const profile = await prisma.profile.findUnique({ - where: { - userId_organizationId: { userId: newUser.id, organizationId: org.id }, - }, - }); - expect(profile).toBeTruthy(); - expect(profile?.organizationId).toBe(org.id); - expect(profile?.username).toBe(newUser.username); - }); - - it("should upsert existing memberships when user was previously invited", async () => { - // Setup - user was invited via email (membership created with accepted: false) - const org = trackTeam( - await createTestOrganization({ - name: "Test Org", - slug: "test-org", - orgAutoAcceptEmail: "example.com", - }) - ); - - const subteam = trackTeam( - await createTestSubteam({ - name: "Sub Team", - slug: "sub-team", - parentId: org.id, - }) - ); - - const user = trackUser( - await createTestUser({ - email: "invited@other.com", - username: "inviteduser", - organizationId: org.id, - }) - ); - - // Pre-create memberships as they would be created during invite - await prisma.membership.create({ - data: { - userId: user.id, - teamId: subteam.id, - role: MembershipRole.MEMBER, - accepted: false, - }, - }); - await prisma.membership.create({ - data: { - userId: user.id, - teamId: org.id, - role: MembershipRole.MEMBER, - accepted: false, - }, - }); - - // Act - user completes signup - await createOrUpdateMemberships({ - user: { id: user.id }, - team: { - id: subteam.id, - parentId: subteam.parentId, - isOrganization: subteam.isOrganization ?? false, - organizationSettings: null, - parent: { - id: org.id, - organizationSettings: null, - }, - }, - }); - - // Assert - memberships are now accepted - const teamMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: subteam.id } }, - }); - expect(teamMembership?.accepted).toBe(true); - - const orgMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: org.id } }, - }); - expect(orgMembership?.accepted).toBe(true); - }); - }); - - describe("Regular Team Membership (not in organization)", () => { - it("should create only team membership for regular teams", async () => { - // Setup - regular team without parent org - const uniqueId = generateUniqueId(); - const regularTeam = trackTeam( - await prisma.team.create({ - data: { - name: `Regular Team ${uniqueId}`, - slug: `regular-team-${uniqueId}`, - isOrganization: false, - parentId: null, - }, - }) - ); - - const user = trackUser( - await createTestUser({ - email: "user@example.com", - username: "testuser", - }) - ); - - // Act - await createOrUpdateMemberships({ - user: { id: user.id }, - team: { - id: regularTeam.id, - parentId: regularTeam.parentId, - isOrganization: regularTeam.isOrganization ?? false, - organizationSettings: null, - }, - }); - - // Assert - team membership created - const teamMembership = await prisma.membership.findUnique({ - where: { userId_teamId: { userId: user.id, teamId: regularTeam.id } }, - }); - expect(teamMembership).toBeTruthy(); - expect(teamMembership?.accepted).toBe(true); - - // Assert - no profile should be created for regular teams - const profiles = await prisma.profile.findMany({ - where: { userId: user.id }, - }); - expect(profiles.length).toBe(0); - }); - }); -}); From ca1d86a5a92bcf2ff593f4f0e9fba1c5d08b39e3 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:47:02 +0530 Subject: [PATCH 08/10] cleanup(test): remove membership repository integration coverage (#29013) --- .../MembershipRepository.integration-test.ts | 164 ------------------ 1 file changed, 164 deletions(-) delete mode 100644 packages/features/membership/repositories/MembershipRepository.integration-test.ts diff --git a/packages/features/membership/repositories/MembershipRepository.integration-test.ts b/packages/features/membership/repositories/MembershipRepository.integration-test.ts deleted file mode 100644 index 79a7889d4e0e9d..00000000000000 --- a/packages/features/membership/repositories/MembershipRepository.integration-test.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { describe, it, expect, beforeAll, afterAll, afterEach } from "vitest"; - -import { prisma } from "@calcom/prisma"; -import { MembershipRole } from "@calcom/prisma/enums"; - -import { MembershipRepository } from "./MembershipRepository"; - -const createdMembershipIds: number[] = []; -let testTeamId: number; -let createdTeamId: number | null = null; - -async function clearTestMemberships() { - if (createdMembershipIds.length > 0) { - await prisma.membership.deleteMany({ - where: { id: { in: createdMembershipIds } }, - }); - createdMembershipIds.length = 0; - } -} - -describe("MembershipRepository (Integration Tests)", () => { - beforeAll(async () => { - let testTeam = await prisma.team.findFirst({ - where: { slug: { not: null } }, - }); - - if (!testTeam) { - testTeam = await prisma.team.create({ - data: { - name: "Test Team for MembershipRepository", - slug: `test-team-membership-repo-${Date.now()}`, - }, - }); - createdTeamId = testTeam.id; - } - testTeamId = testTeam.id; - }); - - afterAll(async () => { - if (createdTeamId) { - await prisma.team.delete({ where: { id: createdTeamId } }); - } - }); - - afterEach(async () => { - await clearTestMemberships(); - }); - - describe("hasPendingInviteByUserId", () => { - it("should return true when user has a pending invite (accepted: false)", async () => { - const newUser = await prisma.user.create({ - data: { - email: `test-pending-invite-${Date.now()}@example.com`, - username: `test-pending-${Date.now()}`, - }, - }); - - const membership = await prisma.membership.create({ - data: { - userId: newUser.id, - teamId: testTeamId, - role: MembershipRole.MEMBER, - accepted: false, - }, - }); - createdMembershipIds.push(membership.id); - - const result = await MembershipRepository.hasPendingInviteByUserId({ userId: newUser.id }); - - expect(result).toBe(true); - - await prisma.membership.delete({ where: { id: membership.id } }); - createdMembershipIds.length = 0; - await prisma.user.delete({ where: { id: newUser.id } }); - }); - - it("should return false when user has no pending invites (all accepted)", async () => { - const newUser = await prisma.user.create({ - data: { - email: `test-accepted-invite-${Date.now()}@example.com`, - username: `test-accepted-${Date.now()}`, - }, - }); - - const membership = await prisma.membership.create({ - data: { - userId: newUser.id, - teamId: testTeamId, - role: MembershipRole.MEMBER, - accepted: true, - }, - }); - createdMembershipIds.push(membership.id); - - const result = await MembershipRepository.hasPendingInviteByUserId({ userId: newUser.id }); - - expect(result).toBe(false); - - await prisma.membership.delete({ where: { id: membership.id } }); - createdMembershipIds.length = 0; - await prisma.user.delete({ where: { id: newUser.id } }); - }); - - it("should return false when user has no memberships at all", async () => { - const newUser = await prisma.user.create({ - data: { - email: `test-no-membership-${Date.now()}@example.com`, - username: `test-no-membership-${Date.now()}`, - }, - }); - - const result = await MembershipRepository.hasPendingInviteByUserId({ userId: newUser.id }); - - expect(result).toBe(false); - - await prisma.user.delete({ where: { id: newUser.id } }); - }); - - it("should return true when user has both accepted and pending invites", async () => { - const newUser = await prisma.user.create({ - data: { - email: `test-mixed-invites-${Date.now()}@example.com`, - username: `test-mixed-${Date.now()}`, - }, - }); - - const team2 = await prisma.team.findFirst({ - where: { - slug: { not: null }, - id: { not: testTeamId }, - }, - }); - - const acceptedMembership = await prisma.membership.create({ - data: { - userId: newUser.id, - teamId: testTeamId, - role: MembershipRole.MEMBER, - accepted: true, - }, - }); - createdMembershipIds.push(acceptedMembership.id); - - if (team2) { - const pendingMembership = await prisma.membership.create({ - data: { - userId: newUser.id, - teamId: team2.id, - role: MembershipRole.MEMBER, - accepted: false, - }, - }); - createdMembershipIds.push(pendingMembership.id); - } - - const result = await MembershipRepository.hasPendingInviteByUserId({ userId: newUser.id }); - - expect(result).toBe(team2 ? true : false); - - await clearTestMemberships(); - await prisma.user.delete({ where: { id: newUser.id } }); - }); - }); -}); From 6a2b84ab02d8a5155744752e0445fd400da19402 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:47:57 +0530 Subject: [PATCH 09/10] cleanup(test): remove round robin lucky user integration coverage (#29020) --- .../lib/getLuckyUser.integration-test.ts | 792 ------------------ 1 file changed, 792 deletions(-) delete mode 100644 packages/features/bookings/lib/getLuckyUser.integration-test.ts diff --git a/packages/features/bookings/lib/getLuckyUser.integration-test.ts b/packages/features/bookings/lib/getLuckyUser.integration-test.ts deleted file mode 100644 index 3571d0be00b622..00000000000000 --- a/packages/features/bookings/lib/getLuckyUser.integration-test.ts +++ /dev/null @@ -1,792 +0,0 @@ -import { getLuckyUserService } from "@calcom/features/di/containers/LuckyUser"; -import prisma from "@calcom/prisma"; -import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - -const luckyUserService = getLuckyUserService(); -let commonEventTypeId: number; -const userIds: number[] = []; - -async function deleteUsers() { - await prisma.user.deleteMany({ - where: { - id: { - in: userIds, - }, - }, - }); - userIds.splice(0, userIds.length); -} - -beforeAll(async () => { - const event = await prisma.eventType.create({ - data: { - title: "Test Event", - slug: "test-event", - length: 15, - }, - select: { - id: true, - }, - }); - commonEventTypeId = event.id; -}); - -beforeEach(() => { - // tell vitest we use mocked time - vi.useFakeTimers(); -}); - -afterEach(async () => { - await deleteUsers(); - vi.useRealTimers(); -}); - -afterAll(async () => { - await prisma.eventType.delete({ - where: { - id: commonEventTypeId, - }, - }); -}); - -type BookingPropsRelatedToLuckyUserAlgorithm = { - eventTypeId: number; - createdAt: Date; - noShowHost?: boolean | null; -}; - -type OptionalBookingProps = { - uid?: string; - title?: string; - startTime?: Date; - endTime?: Date; - attendees?: { - create: { - name: string; - email: string; - timeZone: string; - noShow?: boolean | null; - }[]; - }; -}; - -type UserProps = { - email: string; - createdDate?: Date; -}; - -const commonBookingData = { - startTime: new Date(), - endTime: new Date(), -}; - -const commonAttendeesData = [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, -]; - -const createUserWithBookings = async ({ - user: { email, createdDate }, - bookings, -}: { - user: UserProps; - bookings: (BookingPropsRelatedToLuckyUserAlgorithm & OptionalBookingProps)[]; -}) => { - const user = await prisma.user.create({ - data: { - email, - createdDate, - bookings: { - create: bookings.map(({ eventTypeId, ...booking }, index) => ({ - ...commonBookingData, - attendees: { - create: commonAttendeesData, - }, - uid: `uuid-${email}-booking${index + 1}`, - title: `${email} Booking ${index + 1}`, - eventTypeId, - ...booking, - })), - }, - }, - include: { - bookings: true, - credentials: true, - }, - }); - userIds.push(user.id); - return user; -}; - -const createHostWithBookings = async ({ - user: userData, - bookings, - priority = 2, - weight = null, - createdAt, -}: { - user: UserProps; - bookings: (BookingPropsRelatedToLuckyUserAlgorithm & OptionalBookingProps)[]; - weight?: number | null; - priority?: number; - createdAt?: Date; -}) => { - const user = await createUserWithBookings({ - user: { - createdDate: userData.createdDate || new Date(), - email: userData.email, - }, - bookings, - }); - - const host = await prisma.host.create({ - data: { - user: { connect: { id: user.id } }, - eventType: { connect: { id: commonEventTypeId } }, - weight, - priority, - createdAt: createdAt ?? new Date(), - }, - include: { - user: { - include: { - bookings: true, - credentials: true, - }, - }, - }, - }); - return { - ...host, - user: { - ...host.user, - priority, - weight, - }, - }; -}; - -function expectLuckyUsers(luckyUsers: { email: string }[], expectedLuckyUsers: { email: string }[]) { - expect(luckyUsers.map((user) => user.email)).toEqual(expectedLuckyUsers.map((user) => user.email)); -} - -describe("getLuckyUser Integration tests", () => { - describe("should not consider no show bookings for round robin: ", () => { - it("When a host is no show, that is chosen when competing with another host that showed up for the booking", async () => { - const createOrganizerThatShowedUp = async (email: string) => { - return createHostWithBookings({ - user: { email }, - bookings: [{ eventTypeId: commonEventTypeId, createdAt: new Date("2022-01-25T05:30:00.000Z") }], - }); - }; - - const createOrganizerThatDidntShowUp = async (email: string) => { - return createHostWithBookings({ - user: { email }, - bookings: [ - { - eventTypeId: commonEventTypeId, - createdAt: new Date("2022-01-25T06:30:00.000Z"), - noShowHost: true, - }, - ], - }); - }; - - const organizerHostThatShowedUp = await createOrganizerThatShowedUp("test-user1@example.com"); - const organizerHostThatDidntShowUp = await createOrganizerThatDidntShowUp("test-user2@example.com"); - const organizerThatShowedUp = organizerHostThatShowedUp.user; - const organizerThatDidntShowUp = organizerHostThatDidntShowUp.user; - - const luckyUser = await luckyUserService.getLuckyUser({ - availableUsers: [organizerThatShowedUp, organizerThatDidntShowUp], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - }); - - expect(luckyUser.email).toBe(organizerThatDidntShowUp.email); - }); - - it("When a attendee is a noShow for organizers booking, that organizer is competing with another host whose attendee showed up for the booking", async () => { - const organizerHostWhoseAttendeeShowedUp = await createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [ - { - eventTypeId: commonEventTypeId, - createdAt: new Date("2022-01-25T05:30:00.000Z"), - title: "Test User 1 Booking", - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - ], - }); - - const organizerWhoseAttendeeShowedUp = organizerHostWhoseAttendeeShowedUp.user; - - const organizerHostWhoseAttendeeDidntShowUp = await createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [ - { - eventTypeId: commonEventTypeId, - createdAt: new Date("2022-01-25T06:30:00.000Z"), - attendees: { - create: [ - { - noShow: true, - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - ], - }); - - const organizerWhoseAttendeeDidntShowUp = organizerHostWhoseAttendeeDidntShowUp.user; - - expect( - luckyUserService.getLuckyUser({ - availableUsers: [organizerWhoseAttendeeShowedUp, organizerWhoseAttendeeDidntShowUp], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - }) - ).resolves.toStrictEqual(organizerWhoseAttendeeDidntShowUp); - }); - - it("When a organizer is attendee (event types with fixed hosts) and no show, that organizer is competing other hosts", async () => { - const organizerHostWhoseAttendeeShowedUp = await createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [ - { - eventTypeId: commonEventTypeId, - createdAt: new Date("2022-01-25T05:30:00.000Z"), - title: "Test User 1 Booking", - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - ], - }); - const organizerWhoseAttendeeShowedUp = organizerHostWhoseAttendeeShowedUp.user; - - const fixedHostOrganizerHostWhoseAttendeeDidNotShowUp = await createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [ - { - eventTypeId: commonEventTypeId, - createdAt: new Date("2022-01-25T06:30:00.000Z"), - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - // User2 is fixed user, User 3 was selected as round robin host but did not show up so this booking should be counted for User 3 - { - uid: "uuid-test-user2-booking2", - title: `Test User 2 Booking 2`, - createdAt: new Date("2022-01-25T07:30:00.000Z"), - eventTypeId: commonEventTypeId, - attendees: { - create: [ - { - name: "test-attendee", - email: "test-user3@example.com", - timeZone: "Asia/Calcutta", - noShow: true, - }, - ], - }, - }, - ], - }); - const fixedHostOrganizerWhoseAttendeeDidNotShowUp = - fixedHostOrganizerHostWhoseAttendeeDidNotShowUp.user; - - const organizerHostWhoWasAttendeeAndDidntShowUp = await createHostWithBookings({ - user: { email: `test-user3@example.com` }, - bookings: [ - { - uid: "uuid-test-user3-booking1", - title: `Test User 3 Booking`, - createdAt: new Date("2022-01-25T04:30:00.000Z"), - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - eventTypeId: commonEventTypeId, - }, - ], - }); - - const organizerWhoWasAttendeeAndDidntShowUp = organizerHostWhoWasAttendeeAndDidntShowUp.user; - - expect( - luckyUserService.getLuckyUser({ - availableUsers: [ - organizerWhoseAttendeeShowedUp, - fixedHostOrganizerWhoseAttendeeDidNotShowUp, - organizerWhoWasAttendeeAndDidntShowUp, - ], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - }) - ).resolves.toStrictEqual(organizerWhoWasAttendeeAndDidntShowUp); - }); - - it("should consider booking when noShowHost is null", async () => { - const hostWithBookingThatHappenedLater = await createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [ - { - uid: "uuid-test-user1-booking1", - createdAt: new Date("2022-01-25T07:30:00.000Z"), - title: "Test user 1 Booking", - noShowHost: null, - eventTypeId: commonEventTypeId, - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - ], - }); - - const userWithBookingThatHappenedLater = hostWithBookingThatHappenedLater.user; - - const hostWithBookingThatHappenedEarlier = await createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [ - { - uid: "uuid-test-user2-booking1", - title: "Test User 2 Booking", - createdAt: new Date("2022-01-25T06:30:00.000Z"), - noShowHost: null, - eventTypeId: commonEventTypeId, - attendees: { - create: [ - { - name: "test-attendee", - email: "test-attendee@example.com", - timeZone: "Asia/Calcutta", - }, - ], - }, - }, - ], - }); - - const userWithBookingThatHappenedEarlier = hostWithBookingThatHappenedEarlier.user; - - expect( - luckyUserService.getLuckyUser({ - availableUsers: [userWithBookingThatHappenedLater, userWithBookingThatHappenedEarlier], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - }) - ).resolves.toStrictEqual(userWithBookingThatHappenedEarlier); - }); - }); -}); - -describe("getOrderedListOfLuckyUsers Integration tests", () => { - beforeEach(() => { - vi.setSystemTime("2024-11-14T00:00:13Z"); - }); - - it("should sort by user id if no other criteria like weight/priority/calibration", async () => { - const [host1, host2, host3] = await Promise.all([ - createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [], - createdAt: new Date(), - }), - createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [], - createdAt: new Date(), - }), - createHostWithBookings({ - user: { email: "test-user3@example.com" }, - bookings: [], - createdAt: new Date(), - }), - ]); - - const user1 = host1.user; - const user2 = host2.user; - const user3 = host3.user; - - const { users: luckyUsers } = await luckyUserService.getOrderedListOfLuckyUsers({ - availableUsers: [user2, user1, user3], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - routingFormResponse: null, - }); - - const expectedOrder = [user1, user2, user3].sort((a, b) => a.id - b.id) - - expectLuckyUsers(luckyUsers, expectedOrder); - - const { users: luckyUsers2 } = await luckyUserService.getOrderedListOfLuckyUsers({ - availableUsers: [user3, user1, user2], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled: false, - team: {}, - }, - allRRHosts: [], - routingFormResponse: null, - }); - expectLuckyUsers(luckyUsers2, expectedOrder); - }); - - describe("should sort as per weights", () => { - const isRRWeightsEnabled = true; - it("even if there are no bookings", async () => { - const [host1WithWeight100, host2WithWeight200, host3WithWeight100] = await Promise.all([ - createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [], - createdAt: new Date(), - weight: 100, - }), - createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [], - createdAt: new Date(), - weight: 200, - }), - createHostWithBookings({ - user: { email: "test-user3@example.com" }, - bookings: [], - createdAt: new Date(), - weight: 100, - }), - ]); - - const user1WithWeight100 = host1WithWeight100.user; - const userWithHighestWeight = host2WithWeight200.user; - const user2WithWeight100 = host3WithWeight100.user; - - const allRRHosts = [host1WithWeight100, host2WithWeight200, host3WithWeight100]; - const { users: luckyUsers } = await luckyUserService.getOrderedListOfLuckyUsers({ - availableUsers: [userWithHighestWeight, user1WithWeight100, user2WithWeight100], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled, - team: {}, - }, - allRRHosts, - }); - - expectLuckyUsers(luckyUsers, [ - // It has the highest weight - userWithHighestWeight, - // It has the same weight as the next one but comes earlier in availableUsers array - user1WithWeight100, - // It is the last choice - user2WithWeight100, - ]); - - const { users: luckyUsers2 } = await luckyUserService.getOrderedListOfLuckyUsers({ - availableUsers: [user2WithWeight100, userWithHighestWeight, user1WithWeight100], - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled, - team: {}, - }, - allRRHosts, - }); - expectLuckyUsers(luckyUsers2, [ - // It has the highest weight and zero bookings. - userWithHighestWeight, - // It has the same weight as the next one but comes earlier in availableUsers array - user2WithWeight100, - // It is the last choice - user1WithWeight100, - ]); - }); - - it("consider booking count for the current month", async () => { - const [ - hostWithOneBookingAndWeight200, - hostWithTwoBookingsAndWeight100, - hostWithThreeBookingsAndWeight100, - ] = await Promise.all([ - createHostWithBookings({ - user: { email: "test-user1@example.com" }, - bookings: [{ eventTypeId: commonEventTypeId, createdAt: new Date() }], - createdAt: new Date(), - weight: 200, - }), - createHostWithBookings({ - user: { email: "test-user2@example.com" }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date() }, - { eventTypeId: commonEventTypeId, createdAt: new Date() }, - ], - createdAt: new Date(), - weight: 100, - }), - createHostWithBookings({ - user: { email: "test-user3@example.com" }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date() }, - { eventTypeId: commonEventTypeId, createdAt: new Date() }, - { eventTypeId: commonEventTypeId, createdAt: new Date() }, - ], - createdAt: new Date(), - weight: 100, - }), - ]); - - const userWithOneBookingAndWeight200 = hostWithOneBookingAndWeight200.user; - const userWithTwoBookingsAndWeight100 = hostWithTwoBookingsAndWeight100.user; - const userWithThreeBookingsAndWeight100 = hostWithThreeBookingsAndWeight100.user; - - const availableUsers = [ - userWithThreeBookingsAndWeight100, - userWithTwoBookingsAndWeight100, - userWithOneBookingAndWeight200, - ]; - - const getLuckUserParams = { - availableUsers, - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled, - team: null, - }, - allRRHosts: [ - hostWithOneBookingAndWeight200, - hostWithTwoBookingsAndWeight100, - hostWithThreeBookingsAndWeight100, - ], - }; - - const { users: luckyUsers, perUserData } = await luckyUserService.getOrderedListOfLuckyUsers({ - ...getLuckUserParams, - availableUsers: [getLuckUserParams.availableUsers[0], ...getLuckUserParams.availableUsers.slice(1)], - }); - - expectLuckyUsers(luckyUsers, [ - // User with 1 booking is chosen first because it has higher weight and lesser bookings - userWithOneBookingAndWeight200, - // User with 2 bookings is chosen next because it has lesser bookings - userWithTwoBookingsAndWeight100, - // User with 3 bookings is chosen last because it has the most bookings - userWithThreeBookingsAndWeight100, - ]); - - if (!perUserData?.bookingShortfalls) { - throw new Error("bookingShortfalls is not defined"); - } - expect(perUserData.bookingShortfalls[userWithThreeBookingsAndWeight100.id]).toBe(-1.5); - expect(perUserData.bookingShortfalls[userWithTwoBookingsAndWeight100.id]).toBe(-0.5); - expect(perUserData.bookingShortfalls[userWithOneBookingAndWeight200.id]).toBe(2); - }); - - it("not considering bookings that were created in previous months", async () => { - const [ - hostWithOneBookingInPreviousMonthAndWeight200, - hostWithTwoBookingsInPreviousMonthAndWeight100, - hostWithThreeBookingsInPreviousMonthAndWeight100, - ] = await Promise.all([ - createHostWithBookings({ - user: { email: "test-user1@example.com", createdDate: new Date() }, - bookings: [{ eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }], - weight: 200, - createdAt: new Date(), - }), - createHostWithBookings({ - user: { email: "test-user2@example.com", createdDate: new Date() }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }, - { eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }, - ], - weight: 100, - createdAt: new Date(), - }), - createHostWithBookings({ - user: { email: "test-user3@example.com", createdDate: new Date() }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }, - { eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }, - { eventTypeId: commonEventTypeId, createdAt: new Date("2024-10-01T00:00:00.000Z") }, - ], - weight: 100, - createdAt: new Date(), - }), - ]); - - const userWithOneBookingInPreviousMonthAndWeight200 = - hostWithOneBookingInPreviousMonthAndWeight200.user; - const userWithTwoBookingsInPreviousMonthAndWeight100 = - hostWithTwoBookingsInPreviousMonthAndWeight100.user; - const userWithThreeBookingsInPreviousMonthAndWeight100 = - hostWithThreeBookingsInPreviousMonthAndWeight100.user; - - const availableUsers = [ - userWithThreeBookingsInPreviousMonthAndWeight100, - userWithTwoBookingsInPreviousMonthAndWeight100, - userWithOneBookingInPreviousMonthAndWeight200, - ]; - - const getLuckUserParams = { - availableUsers, - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled, - team: null, - }, - allRRHosts: [ - hostWithOneBookingInPreviousMonthAndWeight200, - hostWithTwoBookingsInPreviousMonthAndWeight100, - hostWithThreeBookingsInPreviousMonthAndWeight100, - ], - }; - - const { users: luckyUsers, perUserData } = await luckyUserService.getOrderedListOfLuckyUsers({ - ...getLuckUserParams, - availableUsers: [getLuckUserParams.availableUsers[0], ...getLuckUserParams.availableUsers.slice(1)], - }); - - expectLuckyUsers(luckyUsers, [ - // User with 1 booking is chosen first because it has higher weight and lesser bookings - userWithOneBookingInPreviousMonthAndWeight200, - // User with 3 bookings is chosen next because it comes earlier in availableUsers array - userWithThreeBookingsInPreviousMonthAndWeight100, - // User with 2 bookings is chosen last because it comes later in availableUsers array - userWithTwoBookingsInPreviousMonthAndWeight100, - ]); - - if (!perUserData?.bookingShortfalls) { - throw new Error("bookingShortfalls is not defined"); - } - - // Because no one has any bookings in the current month, the booking shortfall should be 0 for all users - expect(perUserData.bookingShortfalls[userWithThreeBookingsInPreviousMonthAndWeight100.id]).toBe(0); - expect(perUserData.bookingShortfalls[userWithTwoBookingsInPreviousMonthAndWeight100.id]).toBe(0); - expect(perUserData.bookingShortfalls[userWithOneBookingInPreviousMonthAndWeight200.id]).toBe(0); - }); - }); - describe("should sort as per host creation data calibration", () => { - const isRRWeightsEnabled = true; - - it("not considering bookings that were created in previous months", async () => { - const today = new Date(); - const tenthOfTheMonth = new Date(today.getFullYear(), today.getMonth(), 10); - const secondsInDay = 24 * 60 * 60 * 1000; - const ninthOfTheMonth = new Date(tenthOfTheMonth.getTime() - secondsInDay); - const eighthOfTheMonth = new Date(tenthOfTheMonth.getTime() - 2 * secondsInDay); - const [host1, host2, host3] = await Promise.all([ - createHostWithBookings({ - user: { email: "test-user1@example.com", createdDate: tenthOfTheMonth }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date(tenthOfTheMonth.getTime() + 1000) }, - ], - weight: 200, - createdAt: tenthOfTheMonth, - }), - createHostWithBookings({ - user: { email: "test-user2@example.com", createdDate: ninthOfTheMonth }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date(ninthOfTheMonth.getTime() + 1000) }, - { eventTypeId: commonEventTypeId, createdAt: new Date(ninthOfTheMonth.getTime() + 2000) }, - ], - weight: 100, - createdAt: ninthOfTheMonth, - }), - createHostWithBookings({ - user: { email: "test-user3@example.com", createdDate: eighthOfTheMonth }, - bookings: [ - { eventTypeId: commonEventTypeId, createdAt: new Date(eighthOfTheMonth.getTime() + 1000) }, - { eventTypeId: commonEventTypeId, createdAt: new Date(eighthOfTheMonth.getTime() + 2000) }, - { eventTypeId: commonEventTypeId, createdAt: new Date(eighthOfTheMonth.getTime() + 3000) }, - ], - weight: 100, - createdAt: eighthOfTheMonth, - }), - ]); - - const availableUsers = [host3.user, host2.user, host1.user]; - - const getLuckyUserParams = { - availableUsers, - eventType: { - id: commonEventTypeId, - isRRWeightsEnabled, - team: null, - }, - allRRHosts: [host1, host2, host3], - }; - - const { users: luckyUsers, perUserData } = await luckyUserService.getOrderedListOfLuckyUsers({ - ...getLuckyUserParams, - availableUsers: [getLuckyUserParams.availableUsers[0], ...getLuckyUserParams.availableUsers.slice(1)], - }); - - if (!perUserData?.bookingShortfalls || !perUserData?.calibrations) { - throw new Error("bookingShortfalls or calibrations is not defined"); - } - - expect(perUserData.calibrations[host1.user.id]).toBe(2.5); - expect(perUserData.calibrations[host2.user.id]).toBe(3); - expect(perUserData.calibrations[host3.user.id]).toBe(0); - - expectLuckyUsers(luckyUsers, [host1.user, host3.user, host2.user]); - }); - }); -}); From 987fe910021852bc6c05f4972802d0edd16e0b75 Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:49:24 +0530 Subject: [PATCH 10/10] cleanup(test): remove team event type list integration coverage (#29012) --- .../listWithTeam.handler.integration-test.ts | 340 ------------------ 1 file changed, 340 deletions(-) delete mode 100644 packages/trpc/server/routers/viewer/eventTypes/listWithTeam.handler.integration-test.ts diff --git a/packages/trpc/server/routers/viewer/eventTypes/listWithTeam.handler.integration-test.ts b/packages/trpc/server/routers/viewer/eventTypes/listWithTeam.handler.integration-test.ts deleted file mode 100644 index c665a8e8538e09..00000000000000 --- a/packages/trpc/server/routers/viewer/eventTypes/listWithTeam.handler.integration-test.ts +++ /dev/null @@ -1,340 +0,0 @@ -import prisma from "@calcom/prisma"; -import type { EventType, Team, User } from "@calcom/prisma/client"; -import { MembershipRole, SchedulingType } from "@calcom/prisma/enums"; -import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { listWithTeamHandler } from "./listWithTeam.handler"; - -let user1: User; -let user2: User; -let user3: User; -let team1: Team; -let team2: Team; -let team3: Team; -let eventType1: EventType; -let eventType2: EventType; -let eventType3: EventType; -let eventType4: EventType; -let managedParent: EventType; -let managedChild: EventType; -let teamEventNoUserId: EventType; - -describe("listWithTeamHandler", () => { - beforeAll(async () => { - const timestamp = Date.now(); - user1 = await prisma.user.create({ - data: { - username: `testuser-lwt-1-${timestamp}`, - email: `testuser-lwt-1-${timestamp}@example.com`, - name: "Test User 1", - }, - }); - user2 = await prisma.user.create({ - data: { - username: `testuser-lwt-2-${timestamp}`, - email: `testuser-lwt-2-${timestamp}@example.com`, - name: "Test User 2", - }, - }); - user3 = await prisma.user.create({ - data: { - username: `testuser-lwt-3-${timestamp}`, - email: `testuser-lwt-3-${timestamp}@example.com`, - name: "Test User 3", - }, - }); - - team1 = await prisma.team.create({ - data: { - name: "Team 1 lwt", - slug: `team-1-lwt-${timestamp}`, - members: { - create: { - userId: user1.id, - role: MembershipRole.MEMBER, - accepted: true, - }, - }, - }, - }); - - team2 = await prisma.team.create({ - data: { - name: "Team 2 lwt", - slug: `team-2-lwt-${timestamp}`, - }, - }); - - team3 = await prisma.team.create({ - data: { - name: "Team 3 lwt", - slug: `team-3-lwt-${timestamp}`, - members: { - create: { - userId: user1.id, - role: MembershipRole.ADMIN, - accepted: true, - }, - }, - }, - }); - - eventType1 = await prisma.eventType.create({ - data: { - title: "User 1 Individual Event", - slug: `user1-event-lwt-${timestamp}`, - length: 30, - userId: user1.id, - }, - }); - - eventType2 = await prisma.eventType.create({ - data: { - title: "Team 1 Event (user1 owner + member)", - slug: `team1-event-lwt-${timestamp}`, - length: 30, - teamId: team1.id, - userId: user1.id, - }, - }); - - eventType3 = await prisma.eventType.create({ - data: { - title: "User 2 Individual Event", - slug: `user2-event-lwt-${timestamp}`, - length: 30, - userId: user2.id, - }, - }); - - eventType4 = await prisma.eventType.create({ - data: { - title: "Team 2 Event (user2 owner, NOT member)", - slug: `team2-event-lwt-${timestamp}`, - length: 30, - teamId: team2.id, - userId: user2.id, - }, - }); - - managedParent = await prisma.eventType.create({ - data: { - title: "Managed Parent Event", - slug: `managed-parent-lwt-${timestamp}`, - length: 45, - teamId: team3.id, - schedulingType: SchedulingType.MANAGED, - }, - }); - - managedChild = await prisma.eventType.create({ - data: { - title: "Managed Child Event", - slug: `managed-child-lwt-${timestamp}`, - length: 45, - userId: user1.id, - parentId: managedParent.id, - }, - }); - - teamEventNoUserId = await prisma.eventType.create({ - data: { - title: "Team 3 Event (no userId)", - slug: `team3-nouserid-lwt-${timestamp}`, - length: 60, - teamId: team3.id, - }, - }); - }); - - afterAll(async () => { - try { - const eventTypeIds = [ - eventType1?.id, - eventType2?.id, - eventType3?.id, - eventType4?.id, - managedChild?.id, - managedParent?.id, - teamEventNoUserId?.id, - ].filter(Boolean); - if (eventTypeIds.length > 0) { - await prisma.eventType.deleteMany({ - where: { id: { in: eventTypeIds } }, - }); - } - const teamIds = [team1?.id, team2?.id, team3?.id].filter(Boolean); - if (teamIds.length > 0) { - await prisma.team.deleteMany({ - where: { id: { in: teamIds } }, - }); - } - const userIds = [user1?.id, user2?.id, user3?.id].filter(Boolean); - if (userIds.length > 0) { - await prisma.user.deleteMany({ - where: { id: { in: userIds } }, - }); - } - } catch (error) { - console.warn("Test cleanup failed:", error); - } - }); - - it("should return user's own event types and team event types they are a member of", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).toContain(eventType1.id); - expect(resultIds).toContain(eventType2.id); - - const individualResult = result.find((e) => e.id === eventType1.id); - expect(individualResult).toBeDefined(); - expect(individualResult?.title).toBe(eventType1.title); - expect(individualResult?.slug).toBe(eventType1.slug); - expect(individualResult?.team).toBeNull(); - - const teamResult = result.find((e) => e.id === eventType2.id); - expect(teamResult).toBeDefined(); - expect(teamResult?.title).toBe(eventType2.title); - expect(teamResult?.slug).toBe(eventType2.slug); - expect(teamResult?.team).toBeDefined(); - expect(teamResult?.team?.id).toBe(team1.id); - expect(teamResult?.team?.name).toBe(team1.name); - }); - - it("should not return event types belonging to other users", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).not.toContain(eventType3.id); - expect(resultIds).not.toContain(eventType4.id); - }); - - it("should return team event types where userId is set but user has no membership", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user2.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).toContain(eventType3.id); - expect(resultIds).toContain(eventType4.id); - - const teamEventResult = result.find((e) => e.id === eventType4.id); - expect(teamEventResult).toBeDefined(); - expect(teamEventResult?.team?.id).toBe(team2.id); - expect(teamEventResult?.team?.name).toBe(team2.name); - }); - - it("should not duplicate events when user is both owner and team member", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const eventType2Occurrences = result.filter((e) => e.id === eventType2.id); - expect(eventType2Occurrences).toHaveLength(1); - }); - - it("should return managed event type children with userId set", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).toContain(managedChild.id); - - const managedChildResult = result.find((e) => e.id === managedChild.id); - expect(managedChildResult).toBeDefined(); - expect(managedChildResult?.title).toBe(managedChild.title); - expect(managedChildResult?.team).toBeNull(); - }); - - it("should return team event types without userId via membership", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).toContain(teamEventNoUserId.id); - - const noUserIdResult = result.find((e) => e.id === teamEventNoUserId.id); - expect(noUserIdResult).toBeDefined(); - expect(noUserIdResult?.team?.id).toBe(team3.id); - expect(noUserIdResult?.team?.name).toBe(team3.name); - }); - - it("should populate username for individual event types and null for team event types", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user1.id } }, - }); - - const individualResult = result.find((e) => e.id === eventType1.id); - expect(individualResult?.username).toBe(user1.username); - - const teamResult = result.find((e) => e.id === eventType2.id); - expect(teamResult?.username).toBeNull(); - - const noUserIdTeamResult = result.find((e) => e.id === teamEventNoUserId.id); - expect(noUserIdTeamResult?.username).toBeNull(); - }); - - it("should return username for user2 individual events", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user2.id } }, - }); - - const individualResult = result.find((e) => e.id === eventType3.id); - expect(individualResult?.username).toBe(user2.username); - - const teamEventResult = result.find((e) => e.id === eventType4.id); - expect(teamEventResult?.username).toBeNull(); - }); - - it("should return empty array for user with no event types", async () => { - const result = await listWithTeamHandler({ - ctx: { user: { id: user3.id } }, - }); - - expect(result).toHaveLength(0); - }); - - it("should not return team events for users with unaccepted membership", async () => { - const timestamp = Date.now(); - const pendingTeam = await prisma.team.create({ - data: { - name: "Pending Team lwt", - slug: `pending-team-lwt-${timestamp}`, - members: { - create: { - userId: user3.id, - role: MembershipRole.MEMBER, - accepted: false, - }, - }, - }, - }); - - const pendingTeamEvent = await prisma.eventType.create({ - data: { - title: "Pending Team Event", - slug: `pending-team-event-lwt-${timestamp}`, - length: 30, - teamId: pendingTeam.id, - }, - }); - - try { - const result = await listWithTeamHandler({ - ctx: { user: { id: user3.id } }, - }); - - const resultIds = result.map((e) => e.id); - expect(resultIds).not.toContain(pendingTeamEvent.id); - } finally { - await prisma.eventType.delete({ where: { id: pendingTeamEvent.id } }); - await prisma.team.delete({ where: { id: pendingTeam.id } }); - } - }); -});