From 42f4192bd16bf33582f79ea2fb5e40749b50e02b Mon Sep 17 00:00:00 2001 From: Romit <85230081+romitg2@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:05:05 +0530 Subject: [PATCH] cleanup(team-org): drop playwright helpers and fixtures (#28954) --- .../lib/test-helpers/organizationHelpers.ts | 177 ------------------ .../lib/test-helpers/teamHelpers.ts | 49 ----- apps/web/playwright/profile.e2e.ts | 64 ++++--- apps/web/playwright/team/expects.ts | 38 ---- 4 files changed, 43 insertions(+), 285 deletions(-) delete mode 100644 apps/web/playwright/lib/test-helpers/organizationHelpers.ts delete mode 100644 apps/web/playwright/lib/test-helpers/teamHelpers.ts delete mode 100644 apps/web/playwright/team/expects.ts diff --git a/apps/web/playwright/lib/test-helpers/organizationHelpers.ts b/apps/web/playwright/lib/test-helpers/organizationHelpers.ts deleted file mode 100644 index 19b60ef474..0000000000 --- a/apps/web/playwright/lib/test-helpers/organizationHelpers.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { prisma } from "@calcom/prisma"; - -/** - * Example usage: - * - * // Basic usage with default assignments - * await createAttributes({ - * orgId: 1, - * attributes: [ - * { - * name: "Department", - * type: "SINGLE_SELECT", - * options: ["Engineering", "Sales", "Marketing"] - * } - * ], - * assignments: [ - * { - * memberIndex: 0, - * attributeValues: { - * "Department": ["Engineering"] - * } - * } - * ] - * }); - * - * // Create attributes without assignments - * await createAttributes({ - * orgId: 1, - * attributes: [ - * { name: "Bio", type: "TEXT" }, - * { name: "Years of Experience", type: "NUMBER" } - * ] - * }); - */ - -interface AttributeConfig { - name: string; - type: "SINGLE_SELECT" | "MULTI_SELECT" | "TEXT" | "NUMBER"; - options?: string[]; -} - -interface MemberAssignment { - memberIndex: number; - attributeValues: Record; // attribute name -> selected values -} - -interface SeedAttributesConfig { - orgId: number; - attributes: AttributeConfig[]; - assignments?: MemberAssignment[]; -} - -/** - * Seeds attributes for an organization with configurable types, values, and assignments - * @param config - Configuration object containing orgId, attributes, and optional assignments - * @returns Array of created attributes with their options - */ -export async function createAttributes(config: SeedAttributesConfig) { - const { orgId, attributes: attributeConfigs, assignments = [] } = config; - - console.log(`🎯 Seeding attributes for org ${orgId}`); - - // Check if attributes already exist - const existingAttributes = await prisma.attribute.findMany({ - where: { - teamId: orgId, - name: { - in: attributeConfigs.map((attr) => attr.name), - }, - }, - }); - - if (existingAttributes.length > 0) { - console.log(`Skipping attributes seed, attributes already exist`); - return; - } - - const memberships = await prisma.membership.findMany({ - where: { - teamId: orgId, - }, - select: { - id: true, - userId: true, - }, - }); - - console.log(`🎯 Creating attributes for org ${orgId}`); - - const attributes: { id: string; name: string; options: { id: string; value: string }[] }[] = []; - - for (const attr of attributeConfigs) { - const attribute = await prisma.attribute.create({ - data: { - name: attr.name, - slug: `org:${orgId}-${attr.name.toLowerCase().replace(/ /g, "-")}`, - type: attr.type as "TEXT" | "NUMBER" | "SINGLE_SELECT" | "MULTI_SELECT", - teamId: orgId, - enabled: true, - options: attr.options - ? { - create: attr.options.map((opt) => ({ - value: opt, - slug: opt.toLowerCase().replace(/ /g, "-"), - })), - } - : undefined, - }, - include: { - options: true, - }, - }); - - attributes.push({ - id: attribute.id, - name: attribute.name, - options: attribute.options.map((opt) => ({ - id: opt.id, - value: opt.value, - })), - }); - - console.log(`\t📝 Created attribute: ${attr.name}`); - - // Process assignments for this attribute - for (const assignment of assignments) { - const { memberIndex, attributeValues } = assignment; - - // Check if this assignment has values for the current attribute - const valuesForAttribute = attributeValues[attr.name]; - if (!valuesForAttribute || valuesForAttribute.length === 0) { - console.log( - `\t\t⏭️ Skipped ${attr.name} assignment for member ${memberIndex + 1} - no values specified` - ); - continue; - } - - // Get the member at the specified index - const member = memberships[memberIndex]; - if (!member) { - console.log(`\t\t⚠️ Skipped ${attr.name} assignment - member at index ${memberIndex} not found`); - continue; - } - - // Find the options for the specified values - const selectedOptions = attribute.options.filter((opt) => valuesForAttribute.includes(opt.value)); - - if (selectedOptions.length === 0) { - console.log( - `\t\t⚠️ Skipped ${attr.name} assignment for user ${ - member.userId - } - no matching options found for values: ${valuesForAttribute.join(", ")}` - ); - continue; - } - - // Create assignments for each selected option - for (const option of selectedOptions) { - await prisma.attributeToUser.create({ - data: { - memberId: member.id, - attributeOptionId: option.id, - }, - }); - } - - const assignedValues = selectedOptions.map((opt) => opt.value); - console.log( - `\t\t✅ Assigned ${attr.name} [${assignedValues.map((v) => `"${v}"`).join(", ")}] to user ${ - member.userId - } (member ${memberIndex + 1})` - ); - } - } - - return attributes; -} diff --git a/apps/web/playwright/lib/test-helpers/teamHelpers.ts b/apps/web/playwright/lib/test-helpers/teamHelpers.ts deleted file mode 100644 index 9c6613f63a..0000000000 --- a/apps/web/playwright/lib/test-helpers/teamHelpers.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { prisma } from "@calcom/prisma"; -import type { Prisma } from "@calcom/prisma/client"; - -/** - * Creates a team event type and assigns all team members as hosts - * @param teamId - The team ID - * @param eventType - Event type data to create - * @returns The created event type - */ -export async function createRoundRobinTeamEventType({ - teamId, - eventType, -}: { - teamId: number; - eventType: Prisma.EventTypeCreateInput; -}) { - const createdEventType = await prisma.eventType.create({ - data: { - ...eventType, - team: { - connect: { - id: teamId, - }, - }, - }, - include: { - team: true, - }, - }); - - const teamMemberships = await prisma.membership.findMany({ - where: { - teamId, - }, - }); - - // Add all team members as hosts (excluding the current user who's already added) - for (const membership of teamMemberships) { - await prisma.host.create({ - data: { - userId: membership.userId, - eventTypeId: createdEventType.id, - isFixed: false, // ROUND_ROBIN scheduling type - }, - }); - } - - return createdEventType; -} diff --git a/apps/web/playwright/profile.e2e.ts b/apps/web/playwright/profile.e2e.ts index 72408fb3a2..dcf884ffb4 100644 --- a/apps/web/playwright/profile.e2e.ts +++ b/apps/web/playwright/profile.e2e.ts @@ -1,14 +1,40 @@ -import { expect } from "@playwright/test"; -import type { Page } from "@playwright/test"; -import type { createUsersFixture } from "./fixtures/users"; - import { WEBAPP_URL } from "@calcom/lib/constants"; import type { PrismaClient } from "@calcom/prisma"; - +import type { Page } from "@playwright/test"; +import { expect } from "@playwright/test"; +import { JSDOM } from "jsdom"; +import type { Messages } from "mailhog"; import type { createEmailsFixture } from "./fixtures/emails"; +import type { createUsersFixture } from "./fixtures/users"; import { test } from "./lib/fixtures"; import { getEmailsReceivedByUser, submitAndWaitForResponse } from "./lib/testUtils"; -import { expectInvitationEmailToBeReceived } from "./team/expects"; + +const expectInvitationEmailToBeReceived = async ({ + emails, + userEmail, + subject, + returnLink, +}: { + emails: ReturnType; + userEmail: string; + subject?: string | null; + returnLink?: string; +}) => { + if (!emails) return null; + + const receivedEmails = await getEmailsReceivedByUser({ emails, userEmail }); + expect(receivedEmails?.total).toBe(1); + + const [firstReceivedEmail] = (receivedEmails as Messages).items; + if (subject) { + expect(firstReceivedEmail.subject).toBe(subject); + } + if (!returnLink) return null; + + const dom = new JSDOM(firstReceivedEmail.html); + const anchor = dom.window.document.querySelector(`a[href*="${returnLink}"]`); + return anchor?.getAttribute("href") ?? null; +}; test.describe.configure({ mode: "parallel" }); @@ -170,12 +196,10 @@ test.describe("Update Profile", () => { }); const testEmailVerificationLink = async ({ - page, prisma, emails, secondaryEmail, }: { - page: Page; prisma: PrismaClient; emails: ReturnType; secondaryEmail: string; @@ -186,13 +210,12 @@ test.describe("Update Profile", () => { identifier: secondaryEmail, }, }); - const inviteLink = await expectInvitationEmailToBeReceived( - page, + const inviteLink = await expectInvitationEmailToBeReceived({ emails, - secondaryEmail, - "Verify your email address", - "verify-email" - ); + userEmail: secondaryEmail, + subject: "Verify your email address", + returnLink: "verify-email", + }); expect(inviteLink).toEqual(`${WEBAPP_URL}/api/auth/verify-email?token=${verificationToken?.token}`); }); }; @@ -236,13 +259,12 @@ test.describe("Update Profile", () => { identifier: secondaryEmail, }, }); - const inviteLink = await expectInvitationEmailToBeReceived( - page, + const inviteLink = await expectInvitationEmailToBeReceived({ emails, - secondaryEmail, - "Verify your email address", - "verify-email" - ); + userEmail: secondaryEmail, + subject: "Verify your email address", + returnLink: "verify-email", + }); expect(inviteLink?.endsWith(`/api/auth/verify-email?token=${verificationToken?.token}`)).toEqual(true); }); @@ -385,7 +407,7 @@ test.describe("Update Profile", () => { await expect(page.locator("button[data-testid=resend-verify-email-button]")).toBeEnabled(); await page.getByTestId("resend-verify-email-button").click(); - await testEmailVerificationLink({ page, prisma, emails, secondaryEmail }); + await testEmailVerificationLink({ prisma, emails, secondaryEmail }); const verificationToken = await prisma.verificationToken.findFirst({ where: { diff --git a/apps/web/playwright/team/expects.ts b/apps/web/playwright/team/expects.ts deleted file mode 100644 index 09ce139971..0000000000 --- a/apps/web/playwright/team/expects.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { Page } from "@playwright/test"; -import { expect } from "@playwright/test"; -import { JSDOM } from "jsdom"; -import type { Messages } from "mailhog"; -import type { createEmailsFixture } from "playwright/fixtures/emails"; - -import { getEmailsReceivedByUser } from "../lib/testUtils"; - -export async function expectInvitationEmailToBeReceived( - page: Page, - emails: ReturnType, - userEmail: string, - subject?: string | null, - returnLink?: string -) { - if (!emails) return null; - - const receivedEmails = await getEmailsReceivedByUser({ emails, userEmail }); - expect(receivedEmails?.total).toBe(1); - - const [firstReceivedEmail] = (receivedEmails as Messages).items; - if (subject) { - expect(firstReceivedEmail.subject).toBe(subject); - } - if (!returnLink) return; - const dom = new JSDOM(firstReceivedEmail.html); - const anchor = dom.window.document.querySelector(`a[href*="${returnLink}"]`); - return anchor?.getAttribute("href"); -} - -export async function expectExistingUserToBeInvitedToOrganization( - page: Page, - emails: ReturnType, - userEmail: string, - subject?: string | null -) { - return expectInvitationEmailToBeReceived(page, emails, userEmail, subject, "teams?token"); -}