chore: enable booking redesign for e2e (#25642)
* enable bookings-v3 feature flag for e2e tests WIP * fix e2e * update comments
This commit is contained in:
1 parent
c2d275551a
commit
c361b9bbc5
3 files changed
+118
-34
No files matched your search
@@ -555,17 +555,23 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
await page.waitForSelector('[data-testid="bookings"]');
|
||||
|
||||
await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click();
|
||||
await page.waitForTimeout(2000);
|
||||
const href = await page.locator('[data-testid="reschedule"]').getAttribute("href");
|
||||
|
||||
// Wait for the reschedule link to be visible and have an href attribute
|
||||
const rescheduleLink = page.locator('[data-testid="reschedule"]');
|
||||
await expect(rescheduleLink).toBeVisible();
|
||||
await expect(rescheduleLink).toHaveAttribute("href", /.+/);
|
||||
|
||||
const href = await rescheduleLink.getAttribute("href");
|
||||
const url = new URL(href!, page.url());
|
||||
const seatReferenceUid = url.searchParams.get('seatReferenceUid');
|
||||
if(!seatReferenceUid) {
|
||||
const seatReferenceUid = url.searchParams.get("seatReferenceUid");
|
||||
if (!seatReferenceUid) {
|
||||
await page.reload();
|
||||
await page.waitForSelector('[data-testid="bookings"]');
|
||||
await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await expect(rescheduleLink).toBeVisible();
|
||||
await expect(rescheduleLink).toHaveAttribute("href", /.+/);
|
||||
}
|
||||
await page.locator('[data-testid="reschedule"]').click();
|
||||
await rescheduleLink.click();
|
||||
await expect(page.getByText("Seats available").first()).toBeVisible();
|
||||
|
||||
await page.waitForURL((url) => {
|
||||
|
||||
@@ -58,16 +58,14 @@ test.describe("Bookings", () => {
|
||||
const firstUpcomingBooking = upcomingBookings.locator('[data-testid="booking-item"]').nth(0);
|
||||
const secondUpcomingBooking = upcomingBookings.locator('[data-testid="booking-item"]').nth(1);
|
||||
await expect(
|
||||
|
||||
firstUpcomingBooking.locator(`text=${bookingWhereFirstUserIsAttendee!.title}`)
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
|
||||
secondUpcomingBooking.locator(`text=${bookingWhereFirstUserIsOrganizer!.title}`)
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("Cannot choose date range presets", async ({ page, users, bookings, webhooks }) => {
|
||||
test("Cannot choose date range presets", async ({ page, users }) => {
|
||||
const firstUser = await users.create();
|
||||
await firstUser.apiLogin();
|
||||
const bookingsGetResponse = page.waitForResponse((response) =>
|
||||
@@ -91,7 +89,7 @@ test.describe("Bookings", () => {
|
||||
test.describe("Past bookings", () => {
|
||||
test("Mark first guest as no-show", async ({ page, users, bookings, webhooks }) => {
|
||||
const firstUser = await users.create();
|
||||
const secondUser = await users.create();
|
||||
await users.create();
|
||||
|
||||
const bookingWhereFirstUserIsOrganizerFixture = await createBooking({
|
||||
title: "Booking as organizer",
|
||||
@@ -112,7 +110,6 @@ test.describe("Bookings", () => {
|
||||
await page.goto(`/bookings/past`);
|
||||
const pastBookings = page.locator('[data-testid="past-bookings"]');
|
||||
const firstPastBooking = pastBookings.locator('[data-testid="booking-item"]').nth(0);
|
||||
const titleAndAttendees = firstPastBooking.locator('[data-testid="title-and-attendees"]');
|
||||
const firstGuest = firstPastBooking.locator('[data-testid="guest"]').nth(0);
|
||||
await firstGuest.click();
|
||||
await expect(page.locator('[data-testid="unmark-no-show"]')).toBeHidden();
|
||||
@@ -142,7 +139,7 @@ test.describe("Bookings", () => {
|
||||
});
|
||||
test("Mark 3rd attendee as no-show", async ({ page, users, bookings }) => {
|
||||
const firstUser = await users.create();
|
||||
const secondUser = await users.create();
|
||||
await users.create();
|
||||
|
||||
const bookingWhereFirstUserIsOrganizerFixture = await createBooking({
|
||||
title: "Booking as organizer",
|
||||
@@ -158,23 +155,22 @@ test.describe("Bookings", () => {
|
||||
{ name: "Fourth", email: "fourth@cal.com", timeZone: "Europe/Berlin" },
|
||||
],
|
||||
});
|
||||
const bookingWhereFirstUserIsOrganizer = await bookingWhereFirstUserIsOrganizerFixture.self();
|
||||
await bookingWhereFirstUserIsOrganizerFixture.self();
|
||||
|
||||
await firstUser.apiLogin();
|
||||
await page.goto(`/bookings/past`);
|
||||
const pastBookings = page.locator('[data-testid="past-bookings"]');
|
||||
const firstPastBooking = pastBookings.locator('[data-testid="booking-item"]').nth(0);
|
||||
const titleAndAttendees = firstPastBooking.locator('[data-testid="title-and-attendees"]');
|
||||
const moreGuests = firstPastBooking.locator('[data-testid="more-guests"]');
|
||||
await moreGuests.click();
|
||||
const firstGuestInMore = page.getByRole("menuitemcheckbox").nth(0);
|
||||
await expect(firstGuestInMore).toBeChecked({ checked: false });
|
||||
await expect(firstGuestInMore).toHaveAttribute("data-state", "unchecked");
|
||||
await firstGuestInMore.click();
|
||||
await expect(firstGuestInMore).toBeChecked({ checked: true });
|
||||
await expect(firstGuestInMore).toHaveAttribute("data-state", "checked");
|
||||
const updateNoShow = firstPastBooking.locator('[data-testid="update-no-show"]');
|
||||
await updateNoShow.click();
|
||||
await moreGuests.click();
|
||||
await expect(firstGuestInMore).toBeChecked({ checked: true });
|
||||
await expect(firstGuestInMore).toHaveAttribute("data-state", "checked");
|
||||
});
|
||||
test("Team admin/owner can mark first attendee as no-show", async ({
|
||||
page,
|
||||
@@ -199,11 +195,10 @@ test.describe("Bookings", () => {
|
||||
});
|
||||
const booking = await bookingFixture.self();
|
||||
await adminUser.apiLogin();
|
||||
const { webhookReceiver, teamId } = await webhooks.createTeamReceiver();
|
||||
const { webhookReceiver } = await webhooks.createTeamReceiver();
|
||||
await page.goto(`/bookings/past`);
|
||||
const pastBookings = page.locator('[data-testid="past-bookings"]');
|
||||
const firstPastBooking = pastBookings.locator('[data-testid="booking-item"]').nth(0);
|
||||
const titleAndAttendees = firstPastBooking.locator('[data-testid="title-and-attendees"]');
|
||||
const firstGuest = firstPastBooking.locator('[data-testid="guest"]').nth(0);
|
||||
await firstGuest.click();
|
||||
await expect(page.locator('[data-testid="mark-no-show"]')).toBeVisible();
|
||||
@@ -232,7 +227,7 @@ test.describe("Bookings", () => {
|
||||
webhookReceiver.close();
|
||||
});
|
||||
|
||||
test("Can choose date range presets", async ({ page, users, bookings, webhooks }) => {
|
||||
test("Can choose date range presets", async ({ page, users }) => {
|
||||
const firstUser = await users.create();
|
||||
await firstUser.apiLogin();
|
||||
const bookingsGetResponse = page.waitForResponse((response) =>
|
||||
@@ -374,22 +369,15 @@ test.describe("Bookings", () => {
|
||||
|
||||
//verify with the booking titles
|
||||
const firstUpcomingBooking = bookingListItems.nth(0);
|
||||
await expect(
|
||||
|
||||
firstUpcomingBooking.locator(`text=${thirdUserOrganizerBooking!.title}`)
|
||||
).toBeVisible();
|
||||
await expect(firstUpcomingBooking.locator(`text=${thirdUserOrganizerBooking!.title}`)).toBeVisible();
|
||||
|
||||
const secondUpcomingBooking = bookingListItems.nth(1);
|
||||
await expect(
|
||||
|
||||
secondUpcomingBooking.locator(`text=${thirdUserAttendeeIndividualBooking!.title}`)
|
||||
).toBeVisible();
|
||||
|
||||
const thirdUpcomingBooking = bookingListItems.nth(2);
|
||||
await expect(
|
||||
|
||||
thirdUpcomingBooking.locator(`text=${thirdUserAttendeeTeamEvent!.title}`)
|
||||
).toBeVisible();
|
||||
await expect(thirdUpcomingBooking.locator(`text=${thirdUserAttendeeTeamEvent!.title}`)).toBeVisible();
|
||||
});
|
||||
|
||||
test("Does not show booking from another user from collective event type when a member is filtered", async ({
|
||||
@@ -414,7 +402,7 @@ test.describe("Bookings", () => {
|
||||
|
||||
const { team } = await owner.getFirstTeamMembership();
|
||||
const eventType = await owner.getFirstTeamEvent(team.id);
|
||||
const { id: eventTypeId, title: teamEventTitle, slug: teamEventSlug } = eventType;
|
||||
const { id: eventTypeId } = eventType;
|
||||
|
||||
// remove myself from host of this event type
|
||||
await prisma.host.delete({
|
||||
|
||||
@@ -6,6 +6,7 @@ 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 type { AppFlags } from "@calcom/features/flags/config";
|
||||
import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository";
|
||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
@@ -27,6 +28,18 @@ export function hashPassword(password: string) {
|
||||
return hashedPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default feature flags enabled for all teams and organizations created in E2E tests.
|
||||
* These flags represent the most common production features that should be tested by default.
|
||||
*/
|
||||
const DEFAULT_TEAM_FEATURE_FLAGS: Array<keyof AppFlags> = [];
|
||||
|
||||
/**
|
||||
* Default feature flags enabled for individual users created in E2E tests.
|
||||
* Empty by default - users don't typically have feature flags unless explicitly needed.
|
||||
*/
|
||||
const DEFAULT_USER_FEATURE_FLAGS: Array<keyof AppFlags> = ["bookings-v3"];
|
||||
|
||||
type UserFixture = ReturnType<typeof createUserFixture>;
|
||||
|
||||
export type CreateUsersFixture = ReturnType<typeof createUsersFixture>;
|
||||
@@ -155,6 +168,7 @@ const createTeamAndAddUser = async (
|
||||
schedulingType,
|
||||
assignAllTeamMembersForSubTeamEvents,
|
||||
teamSlug,
|
||||
teamFeatureFlags,
|
||||
}: {
|
||||
user: { id: number; email: string; username: string | null; role?: MembershipRole };
|
||||
isUnpublished?: boolean;
|
||||
@@ -168,6 +182,7 @@ const createTeamAndAddUser = async (
|
||||
schedulingType?: SchedulingType;
|
||||
assignAllTeamMembersForSubTeamEvents?: boolean;
|
||||
teamSlug?: string;
|
||||
teamFeatureFlags?: Array<keyof AppFlags>;
|
||||
},
|
||||
workerInfo: WorkerInfo
|
||||
) => {
|
||||
@@ -196,13 +211,14 @@ const createTeamAndAddUser = async (
|
||||
|
||||
data.slug = !isUnpublished ? slug : undefined;
|
||||
if (isOrg && hasSubteam) {
|
||||
const team = await createTeamAndAddUser({ user }, workerInfo);
|
||||
await createTeamEventType(user, team, {
|
||||
const subteam = await createTeamAndAddUser({ user, teamFeatureFlags }, workerInfo);
|
||||
|
||||
await createTeamEventType(user, subteam, {
|
||||
schedulingType: schedulingType,
|
||||
assignAllTeamMembers: assignAllTeamMembersForSubTeamEvents,
|
||||
});
|
||||
await createTeamWorkflow(user, team);
|
||||
data.children = { connect: [{ id: team.id }] };
|
||||
await createTeamWorkflow(user, subteam);
|
||||
data.children = { connect: [{ id: subteam.id }] };
|
||||
}
|
||||
data.orgProfiles = isOrg
|
||||
? {
|
||||
@@ -235,6 +251,18 @@ const createTeamAndAddUser = async (
|
||||
},
|
||||
});
|
||||
|
||||
// Enable feature flags for the team if specified
|
||||
if (teamFeatureFlags && teamFeatureFlags.length > 0) {
|
||||
await prisma.teamFeatures.createMany({
|
||||
data: teamFeatureFlags.map((featureFlag) => ({
|
||||
teamId: team.id,
|
||||
featureId: featureFlag,
|
||||
assignedBy: "e2e-fixture",
|
||||
assignedAt: new Date(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
return team;
|
||||
};
|
||||
|
||||
@@ -270,6 +298,23 @@ export const createUsersFixture = (
|
||||
| (CustomUserOpts & {
|
||||
organizationId?: number | null;
|
||||
overrideDefaultEventTypes?: boolean;
|
||||
/**
|
||||
* Feature flags to enable for this individual user.
|
||||
* Defaults to DEFAULT_USER_FEATURE_FLAGS.
|
||||
* Pass specific flags to enable user-level features.
|
||||
* @default DEFAULT_USER_FEATURE_FLAGS
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Default feature flags
|
||||
* const user = await users.create();
|
||||
*
|
||||
* // Specific feature flags
|
||||
* const user = await users.create({
|
||||
* userFeatureFlags: ["bookings-v3"]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
userFeatureFlags?: Array<keyof AppFlags>;
|
||||
})
|
||||
| null,
|
||||
scenario: {
|
||||
@@ -295,6 +340,31 @@ export const createUsersFixture = (
|
||||
orgRequestedSlug?: string;
|
||||
assignAllTeamMembers?: boolean;
|
||||
assignAllTeamMembersForSubTeamEvents?: boolean;
|
||||
/**
|
||||
* Feature flags to enable for the created team(s) and organization(s).
|
||||
* Defaults to DEFAULT_TEAM_FEATURE_FLAGS when hasTeam is true.
|
||||
* Pass an empty array to disable default flags, or pass specific flags to override.
|
||||
* Applies to both regular teams and organizations (when isOrg: true).
|
||||
* @default DEFAULT_TEAM_FEATURE_FLAGS
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Default feature flags
|
||||
* const user = await users.create({}, { hasTeam: true });
|
||||
*
|
||||
* // Specific feature flags
|
||||
* const user = await users.create({}, {
|
||||
* hasTeam: true,
|
||||
* teamFeatureFlags: ["pbac"]
|
||||
* });
|
||||
*
|
||||
* // Organizations also get the flags by default
|
||||
* const user = await users.create({}, {
|
||||
* hasTeam: true,
|
||||
* isOrg: true
|
||||
* }); // Org gets DEFAULT_TEAM_FEATURE_FLAGS
|
||||
* ```
|
||||
*/
|
||||
teamFeatureFlags?: Array<keyof AppFlags>;
|
||||
} = {}
|
||||
) => {
|
||||
const _user = await prisma.user.create({
|
||||
@@ -347,9 +417,27 @@ export const createUsersFixture = (
|
||||
where: { id: _user.id },
|
||||
include: userIncludes,
|
||||
});
|
||||
|
||||
// Enable feature flags for the user if specified
|
||||
// Default to DEFAULT_USER_FEATURE_FLAGS if not specified
|
||||
const userFeatureFlags = opts?.userFeatureFlags ?? DEFAULT_USER_FEATURE_FLAGS;
|
||||
if (userFeatureFlags.length > 0) {
|
||||
await prisma.userFeatures.createMany({
|
||||
data: userFeatureFlags.map((featureFlag) => ({
|
||||
userId: user.id,
|
||||
featureId: featureFlag,
|
||||
assignedBy: "e2e-fixture",
|
||||
assignedAt: new Date(),
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
if (scenario.hasTeam) {
|
||||
const numberOfTeams = scenario.numberOfTeams || 1;
|
||||
for (let i = 0; i < numberOfTeams; i++) {
|
||||
// Determine feature flags to use
|
||||
const featureFlags = scenario.teamFeatureFlags ?? DEFAULT_TEAM_FEATURE_FLAGS;
|
||||
|
||||
const team = await createTeamAndAddUser(
|
||||
{
|
||||
user: {
|
||||
@@ -368,10 +456,12 @@ export const createUsersFixture = (
|
||||
schedulingType: scenario.schedulingType,
|
||||
assignAllTeamMembersForSubTeamEvents: scenario.assignAllTeamMembersForSubTeamEvents,
|
||||
teamSlug: scenario?.teamSlug,
|
||||
teamFeatureFlags: featureFlags,
|
||||
},
|
||||
workerInfo
|
||||
);
|
||||
store.teams.push(team);
|
||||
|
||||
const teamEvent = await createTeamEventType(user, team, scenario);
|
||||
if (scenario.teammates) {
|
||||
// Create Teammate users
|
||||
|
||||
Reference in new issue
Block a user