cleanup(team-org): drop playwright helpers and fixtures (#28954)

This commit is contained in:
Romit
2026-04-22 16:05:05 +05:30
committed by GitHub
parent 04fcd9f3ab
commit 42f4192bd1
4 changed files with 43 additions and 285 deletions
@@ -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<string, string[]>; // 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;
}
@@ -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;
}
+43 -21
View File
@@ -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<typeof createEmailsFixture>;
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<typeof createEmailsFixture>;
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: {
-38
View File
@@ -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<typeof createEmailsFixture>,
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<typeof createEmailsFixture>,
userEmail: string,
subject?: string | null
) {
return expectInvitationEmailToBeReceived(page, emails, userEmail, subject, "teams?token");
}