refactor: allow managed event tests parallel runs (#16113)
Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Replexica <support@replexica.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: Udit Takkar <udit222001@gmail.com> Co-authored-by: Peer Richelsen <peer@cal.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: unknown <adhabal2002@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com> Co-authored-by: zomars <zomars@me.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
co-authored by
CarinaWolli
Joe Au-Yeung
Replexica
Morgan
Amit Sharma
Peer Richelsen
Udit Takkar
Udit Takkar
Peer Richelsen
Carina Wollendorfer
unknown
Anik Dhabal Babu
Syed Ali Shahbaz
Keith Williams
sean-brydon
parent
34ca3bd22d
commit
9fc9876b3f
@@ -7,6 +7,7 @@ import { hashSync as hash } from "bcryptjs";
|
||||
import { uuid } from "short-uuid";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
import updateChildrenEventTypes from "@calcom/features/ee/managed-event-types/lib/handleChildrenEventTypes";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
@@ -92,6 +93,7 @@ const createTeamEventType = async (
|
||||
teamEventSlug?: string;
|
||||
teamEventLength?: number;
|
||||
seatsPerTimeSlot?: number;
|
||||
managedEventUnlockedFields?: Record<string, boolean>;
|
||||
}
|
||||
) => {
|
||||
return await prisma.eventType.create({
|
||||
@@ -122,6 +124,20 @@ const createTeamEventType = async (
|
||||
slug: scenario?.teamEventSlug ?? `${teamEventSlug}-team-id-${team.id}`,
|
||||
length: scenario?.teamEventLength ?? 30,
|
||||
seatsPerTimeSlot: scenario?.seatsPerTimeSlot,
|
||||
locations: [{ type: "integrations:daily" }],
|
||||
metadata:
|
||||
scenario?.schedulingType === SchedulingType.MANAGED
|
||||
? {
|
||||
managedEventConfig: {
|
||||
unlockedFields: {
|
||||
locations: true,
|
||||
scheduleId: true,
|
||||
destinationCalendar: true,
|
||||
...scenario?.managedEventUnlockedFields,
|
||||
},
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -259,6 +275,8 @@ export const createUsersFixture = (
|
||||
hasSubteam?: true;
|
||||
isUnpublished?: true;
|
||||
seatsPerTimeSlot?: number;
|
||||
addManagedEventToTeamMates?: boolean;
|
||||
managedEventUnlockedFields?: Record<string, boolean>;
|
||||
orgRequestedSlug?: string;
|
||||
} = {}
|
||||
) => {
|
||||
@@ -521,6 +539,31 @@ export const createUsersFixture = (
|
||||
teamMates.push(teamUser);
|
||||
store.users.push(teammateFixture);
|
||||
}
|
||||
// If the teamEvent is a managed one, we add the team mates to it.
|
||||
if (scenario.schedulingType === SchedulingType.MANAGED && scenario.addManagedEventToTeamMates) {
|
||||
await updateChildrenEventTypes({
|
||||
eventTypeId: teamEvent.id,
|
||||
currentUserId: user.id,
|
||||
hashedLink: "",
|
||||
connectedLink: null,
|
||||
oldEventType: {
|
||||
team: null,
|
||||
},
|
||||
updatedEventType: teamEvent,
|
||||
children: teamMates.map((tm) => ({
|
||||
hidden: false,
|
||||
owner: {
|
||||
id: tm.id,
|
||||
name: tm.name || tm.username || "Nameless",
|
||||
email: tm.email,
|
||||
eventTypeSlugs: [],
|
||||
},
|
||||
})),
|
||||
profileId: null,
|
||||
prisma,
|
||||
updatedValues: {},
|
||||
});
|
||||
}
|
||||
// Add Teammates to OrgUsers
|
||||
if (scenario.isOrg) {
|
||||
const orgProfilesCreate = teamMates
|
||||
@@ -730,10 +773,11 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => {
|
||||
userId: user.id,
|
||||
},
|
||||
}),
|
||||
getFirstTeamEvent: async (teamId: number) => {
|
||||
getFirstTeamEvent: async (teamId: number, schedulingType?: SchedulingType) => {
|
||||
return prisma.eventType.findFirstOrThrow({
|
||||
where: {
|
||||
teamId,
|
||||
schedulingType,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,212 +1,247 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import type { Locator, Page } from "@playwright/test";
|
||||
import { expect } from "@playwright/test";
|
||||
import { apiLogin } from "playwright/fixtures/users";
|
||||
|
||||
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
import { test } from "./lib/fixtures";
|
||||
import {
|
||||
bookTimeSlot,
|
||||
fillStripeTestCheckout,
|
||||
localize,
|
||||
selectFirstAvailableTimeSlotNextMonth,
|
||||
} from "./lib/testUtils";
|
||||
import { test, type Fixtures } from "./lib/fixtures";
|
||||
import { bookTimeSlot, localize, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
|
||||
|
||||
test.afterEach(({ users }) => users.deleteAll());
|
||||
test.afterEach(async ({ users }) => {
|
||||
await users.deleteAll();
|
||||
});
|
||||
|
||||
/** So we can test different areas in parallel and avoiding the creation flow each time */
|
||||
async function setupManagedEvent({
|
||||
users,
|
||||
unlockedFields,
|
||||
}: {
|
||||
users: Fixtures["users"];
|
||||
unlockedFields?: Record<string, boolean>;
|
||||
}) {
|
||||
const teamMateName = "teammate-1";
|
||||
const teamEventTitle = "Managed";
|
||||
const adminUser = await users.create(null, {
|
||||
hasTeam: true,
|
||||
teammates: [{ name: teamMateName }],
|
||||
teamEventTitle,
|
||||
teamEventSlug: "managed",
|
||||
schedulingType: "MANAGED",
|
||||
addManagedEventToTeamMates: true,
|
||||
managedEventUnlockedFields: unlockedFields,
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const memberUser = users.get().find((u) => u.name === teamMateName)!;
|
||||
const { team } = await adminUser.getFirstTeamMembership();
|
||||
const managedEvent = await adminUser.getFirstTeamEvent(team.id, SchedulingType.MANAGED);
|
||||
return { adminUser, memberUser, managedEvent, teamMateName, teamEventTitle };
|
||||
}
|
||||
|
||||
/** Short hand to get elements by translation key */
|
||||
const getByKey = async (page: Page, key: string) => page.getByText((await localize("en"))(key));
|
||||
|
||||
test.describe("Managed Event Types", () => {
|
||||
/** We don't use setupManagedEvent here to test the actual creation flow */
|
||||
test("Can create managed event type", async ({ page, users }) => {
|
||||
// Creating the owner user of the team
|
||||
const adminUser = await users.create();
|
||||
const adminUser = await users.create(null, {
|
||||
hasTeam: true,
|
||||
teammates: [{ name: "teammate-1" }],
|
||||
});
|
||||
// Creating the member user of the team
|
||||
const memberUser = await users.create();
|
||||
// First we work with owner user, logging in
|
||||
await adminUser.apiLogin();
|
||||
|
||||
// Let's create a team
|
||||
await page.goto("/settings/teams/new");
|
||||
// Going to create an event type
|
||||
await page.goto("/event-types");
|
||||
await page.getByTestId("new-event-type").click();
|
||||
await page.getByTestId("option-team-1").click();
|
||||
// Expecting we can add a managed event type as team owner
|
||||
await expect(page.locator('button[value="MANAGED"]')).toBeVisible();
|
||||
|
||||
await test.step("Managed event option exists for team admin", async () => {
|
||||
// Filling team creation form wizard
|
||||
await page.locator('input[name="name"]').fill(`${adminUser.username}'s Team`);
|
||||
await page.click("[type=submit]");
|
||||
// TODO: Figure out a way to make this more reliable
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
if (IS_TEAM_BILLING_ENABLED) await fillStripeTestCheckout(page);
|
||||
await page.waitForURL(/\/settings\/teams\/(\d+)\/onboard-members.*$/i);
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('[placeholder="email\\@example\\.com"]').fill(`${memberUser.username}@example.com`);
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
// wait for the second member to be added to the pending-member-list.
|
||||
await page.getByTestId("pending-member-list").locator("li:nth-child(2)").waitFor();
|
||||
await page.locator("[data-testid=publish-button]").click();
|
||||
await expect(page).toHaveURL(/\/settings\/teams\/(\d+)\/event-type$/i);
|
||||
// create a round-robin event type and finish
|
||||
await expect(page.locator('button[value="ROUND_ROBIN"]')).toBeVisible();
|
||||
await page.click('button[value="ROUND_ROBIN"]');
|
||||
await page.fill("[name=title]", "roundRobin");
|
||||
await page.getByTestId("finish-button").click();
|
||||
await page.waitForURL(/\/settings\/teams\/(\d+)\/profile$/i);
|
||||
// Going to create an managed event type
|
||||
await page.goto("/event-types");
|
||||
await page.getByTestId("new-event-type").click();
|
||||
await page.getByTestId("option-team-1").click();
|
||||
// Expecting we can add a managed event type as team owner
|
||||
await expect(page.locator('button[value="MANAGED"]')).toBeVisible();
|
||||
// Actually creating a managed event type to test things further
|
||||
await page.click('button[value="MANAGED"]');
|
||||
await page.fill("[name=title]", "managed");
|
||||
await page.click("[type=submit]");
|
||||
|
||||
// Actually creating a managed event type to test things further
|
||||
await page.click('button[value="MANAGED"]');
|
||||
await page.fill("[name=title]", "managed");
|
||||
await page.click("[type=submit]");
|
||||
await page.waitForURL("event-types/**");
|
||||
expect(page.url()).toContain("?tabName=team");
|
||||
});
|
||||
|
||||
await page.waitForURL("event-types/**");
|
||||
/** From here we use setupManagedEvent to avoid repeating the previous flow */
|
||||
test("Has unlocked fields for admin", async ({ page, users }) => {
|
||||
const { adminUser, managedEvent } = await setupManagedEvent({ users });
|
||||
await adminUser.apiLogin();
|
||||
await page.goto(`/event-types/${managedEvent.id}?tabName=setup`);
|
||||
await page.getByTestId("update-eventtype").waitFor();
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).toBeEditable();
|
||||
});
|
||||
|
||||
test("Exists for added member", async ({ page, users }) => {
|
||||
const { memberUser, teamEventTitle } = await setupManagedEvent({
|
||||
users,
|
||||
});
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await expect(
|
||||
page.getByTestId("event-types").locator("div").filter({ hasText: teamEventTitle }).nth(1)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step("Managed event type has unlocked fields for admin", async () => {
|
||||
await page.getByTestId("vertical-tab-event_setup_tab_title").click();
|
||||
await page.getByTestId("update-eventtype").waitFor();
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).toBeEditable();
|
||||
test("Can use Organizer's default app as location", async ({ page, users }) => {
|
||||
const { adminUser, managedEvent } = await setupManagedEvent({ users });
|
||||
await adminUser.apiLogin();
|
||||
await page.goto(`/event-types/${managedEvent.id}?tabName=setup`);
|
||||
await page.locator("#location-select").click();
|
||||
const optionText = await getByKey(page, "organizer_default_conferencing_app");
|
||||
await expect(optionText).toBeVisible();
|
||||
await optionText.click();
|
||||
await submitAndWaitForResponse(page);
|
||||
|
||||
await page.getByTestId("vertical-tab-assignment").click();
|
||||
await gotoBookingPage(page);
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
await bookTimeSlot(page);
|
||||
|
||||
await expect(page.getByTestId("success-page")).toBeVisible();
|
||||
});
|
||||
|
||||
test("Has locked fields for added member", async ({ page, users }) => {
|
||||
const { memberUser } = await setupManagedEvent({
|
||||
users,
|
||||
});
|
||||
await memberUser.apiLogin();
|
||||
const managedEvent = await memberUser.getFirstEventAsOwner();
|
||||
await page.goto(`/event-types/${managedEvent.id}?tabName=setup`);
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).not.toBeEditable();
|
||||
});
|
||||
|
||||
test("Provides discrete field lock/unlock state for admin", async ({ page, users }) => {
|
||||
const { adminUser, teamEventTitle } = await setupManagedEvent({ users });
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
// Locked by default
|
||||
const titleLockIndicator = page.getByTestId("locked-indicator-title");
|
||||
await expect(titleLockIndicator).toBeVisible();
|
||||
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(1);
|
||||
|
||||
// Proceed to unlock and check that it got unlocked
|
||||
titleLockIndicator.click();
|
||||
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(0);
|
||||
await expect(titleLockIndicator.locator("[data-state='unchecked']")).toHaveCount(1);
|
||||
|
||||
// Save changes
|
||||
await page.locator('[type="submit"]').click();
|
||||
await expect(titleLockIndicator.locator("[data-state='unchecked']")).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("Shows discretionally unlocked field to member", async ({ page, users }) => {
|
||||
const { memberUser, teamEventTitle } = await setupManagedEvent({
|
||||
users,
|
||||
unlockedFields: {
|
||||
title: true,
|
||||
},
|
||||
});
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
});
|
||||
|
||||
test("Should only update the unlocked fields modified by Admin", async ({
|
||||
page: memberPage,
|
||||
users,
|
||||
browser,
|
||||
}) => {
|
||||
const { adminUser, memberUser, teamEventTitle } = await setupManagedEvent({
|
||||
users,
|
||||
unlockedFields: {
|
||||
title: true,
|
||||
},
|
||||
});
|
||||
await memberUser.apiLogin();
|
||||
await memberPage.goto("/event-types");
|
||||
await memberPage.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click();
|
||||
await memberPage.waitForURL("event-types/**");
|
||||
await expect(memberPage.locator('input[name="title"]')).toBeEditable();
|
||||
await memberPage.locator('input[name="title"]').fill(`Managed Event Title`);
|
||||
await submitAndWaitForResponse(memberPage);
|
||||
|
||||
// We edit the managed event as original owner
|
||||
const adminContext = await browser.newContext();
|
||||
const adminPage = await adminContext.newPage();
|
||||
const adminUserSnapshot = await adminUser.self();
|
||||
await apiLogin({ ...adminUserSnapshot, password: adminUserSnapshot.username }, adminPage);
|
||||
await adminPage.goto("/event-types");
|
||||
await adminPage.getByTestId("event-types").locator(`a[title="${teamEventTitle}"]`).click();
|
||||
await adminPage.waitForURL("event-types/**");
|
||||
await adminPage.locator('input[name="length"]').fill(`45`);
|
||||
await submitAndWaitForResponse(adminPage);
|
||||
await adminContext.close();
|
||||
|
||||
await memberPage.goto("/event-types");
|
||||
await memberPage.getByTestId("event-types").locator('a[title="Managed Event Title"]').click();
|
||||
await memberPage.waitForURL("event-types/**");
|
||||
//match length
|
||||
expect(await memberPage.locator("[data-testid=duration]").getAttribute("value")).toBe("45");
|
||||
//ensure description didn't update
|
||||
expect(await memberPage.locator(`input[name="title"]`).getAttribute("value")).toBe(`Managed Event Title`);
|
||||
await memberPage.locator('input[name="title"]').fill(`managed`);
|
||||
// Save changes
|
||||
await submitAndWaitForResponse(memberPage);
|
||||
});
|
||||
|
||||
const MANAGED_EVENT_TABS: { slug: string; locator: (page: Page) => Locator | Promise<Locator> }[] = [
|
||||
{ slug: "setup", locator: (page) => getByKey(page, "title") },
|
||||
{
|
||||
slug: "team",
|
||||
locator: (page) => getByKey(page, "automatically_add_all_team_members"),
|
||||
},
|
||||
{
|
||||
slug: "availability",
|
||||
locator: (page) => getByKey(page, "members_default_schedule_description"),
|
||||
},
|
||||
{
|
||||
slug: "limits",
|
||||
locator: (page) => getByKey(page, "before_event"),
|
||||
},
|
||||
{
|
||||
slug: "advanced",
|
||||
locator: (page) => getByKey(page, "event_name_in_calendar"),
|
||||
},
|
||||
{
|
||||
slug: "apps",
|
||||
locator: (page) => page.getByRole("heading", { name: "No apps installed" }),
|
||||
},
|
||||
{
|
||||
slug: "workflows",
|
||||
locator: (page) => page.getByTestId("empty-screen").getByRole("heading", { name: "Workflows" }),
|
||||
},
|
||||
{
|
||||
slug: "ai",
|
||||
locator: (page) => page.getByTestId("empty-screen").getByRole("heading", { name: "Cal.ai" }),
|
||||
},
|
||||
];
|
||||
|
||||
MANAGED_EVENT_TABS.forEach((tab) => {
|
||||
test(`Can render "${tab.slug}" tab`, async ({ page, users }) => {
|
||||
const { adminUser, managedEvent } = await setupManagedEvent({ users });
|
||||
// First we work with owner user, logging in
|
||||
await adminUser.apiLogin();
|
||||
});
|
||||
|
||||
await test.step("Managed event type exists for added member", async () => {
|
||||
// Now we need to accept the invitation as member and come back in as admin to
|
||||
// assign the member in the managed event type
|
||||
await memberUser.apiLogin();
|
||||
|
||||
await page.goto("/teams");
|
||||
await page.locator('button[data-testid^="accept-invitation"]').click();
|
||||
await page.getByText("Member").waitFor();
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
|
||||
// Coming back as team owner to assign member user to managed event
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.getByTestId("vertical-tab-assignment").click();
|
||||
await page.getByTestId("assignment-dropdown").click();
|
||||
|
||||
await page.getByTestId(`select-option-${memberUser.id}`).click();
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
});
|
||||
|
||||
await test.step("Managed event type can use Organizer's default app as location", async () => {
|
||||
await page.getByTestId("vertical-tab-event_setup_tab_title").click();
|
||||
|
||||
await page.locator("#location-select").click();
|
||||
const optionText = (await localize("en"))("organizer_default_conferencing_app");
|
||||
await page.locator(`text=${optionText}`).click();
|
||||
await page.locator("[data-testid=update-eventtype]").click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByTestId("vertical-tab-assignment").click();
|
||||
await gotoBookingPage(page);
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
await bookTimeSlot(page);
|
||||
|
||||
await expect(page.getByTestId("success-page")).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step("Managed event type has locked fields for added member", async () => {
|
||||
await adminUser.logout();
|
||||
// Coming back as member user to see if there is a managed event present after assignment
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).not.toBeEditable();
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
});
|
||||
|
||||
await test.step("Managed event type provides discrete field lock/unlock state for admin", async () => {
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
// Locked by default
|
||||
const titleLockIndicator = page.getByTestId("locked-indicator-title");
|
||||
await expect(titleLockIndicator).toBeVisible();
|
||||
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(1);
|
||||
|
||||
// Proceed to unlock and check that it got unlocked
|
||||
titleLockIndicator.click();
|
||||
await expect(titleLockIndicator.locator("[data-state='checked']")).toHaveCount(0);
|
||||
await expect(titleLockIndicator.locator("[data-state='unchecked']")).toHaveCount(1);
|
||||
|
||||
// Save changes
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
});
|
||||
|
||||
await test.step("Managed event type shows discretionally unlocked field to member", async () => {
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
});
|
||||
|
||||
await test.step("Managed event type should only update the unlocked fields modified by Admin", async () => {
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
await page.locator('input[name="title"]').fill(`Managed Event Title`);
|
||||
// Save changes
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await page.locator('input[name="length"]').fill(`45`);
|
||||
// Save changes
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.goto("/auth/logout");
|
||||
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="Managed Event Title"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
//match length
|
||||
expect(await page.locator("[data-testid=duration]").getAttribute("value")).toBe("45");
|
||||
//ensure description didn't update
|
||||
expect(await page.locator(`input[name="title"]`).getAttribute("value")).toBe(`Managed Event Title`);
|
||||
await page.locator('input[name="title"]').fill(`managed`);
|
||||
// Save changes
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
await page.goto(`/event-types/${managedEvent.id}?tabName=${tab.slug}`);
|
||||
await expect(await tab.locator(page)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -216,3 +251,10 @@ async function gotoBookingPage(page: Page) {
|
||||
|
||||
await page.goto(previewLink ?? "");
|
||||
}
|
||||
|
||||
async function submitAndWaitForResponse(page: Page) {
|
||||
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/update?batch=1");
|
||||
await page.locator('[type="submit"]').click();
|
||||
const response = await submitPromise;
|
||||
expect(response.status()).toBe(200);
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import { test } from "../lib/fixtures";
|
||||
|
||||
test.beforeEach(async ({ page, users, bookingPage }) => {
|
||||
const teamEventTitle = "Test Managed Event Type";
|
||||
const userFixture = await users.create(
|
||||
{ name: "testuser" },
|
||||
{ hasTeam: true, schedulingType: "MANAGED", teamEventTitle }
|
||||
);
|
||||
await userFixture.apiLogin();
|
||||
|
||||
await page.goto("/event-types");
|
||||
await bookingPage.goToEventType(teamEventTitle);
|
||||
await page.getByTestId("location-select").click();
|
||||
await page.locator(`text="Cal Video (Global)"`).click();
|
||||
await bookingPage.goToTab("event_advanced_tab_title");
|
||||
});
|
||||
|
||||
test.describe("Check advanced options in a managed team event type", () => {
|
||||
test("Check advanced options in a managed team event type without offer seats", async ({ bookingPage }) => {
|
||||
await bookingPage.checkRequiresConfirmation();
|
||||
await bookingPage.checkRequiresBookerEmailVerification();
|
||||
await bookingPage.checkHideNotes();
|
||||
await bookingPage.checkRedirectOnBooking();
|
||||
await bookingPage.checkLockTimezone();
|
||||
await bookingPage.updateEventType();
|
||||
await bookingPage.goToEventTypesPage();
|
||||
|
||||
await bookingPage.checkEventType();
|
||||
});
|
||||
|
||||
test("Check advanced options in a managed team event type with offer seats", async ({ bookingPage }) => {
|
||||
await bookingPage.checkRequiresConfirmation();
|
||||
await bookingPage.checkRequiresBookerEmailVerification();
|
||||
await bookingPage.checkHideNotes();
|
||||
await bookingPage.checkRedirectOnBooking();
|
||||
await bookingPage.toggleOfferSeats();
|
||||
await bookingPage.checkLockTimezone();
|
||||
await bookingPage.updateEventType();
|
||||
await bookingPage.goToEventTypesPage();
|
||||
|
||||
await bookingPage.checkEventType();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user