diff --git a/apps/web/components/booking/BookingListItem.tsx b/apps/web/components/booking/BookingListItem.tsx index 518a0c21d8..4cba1243c5 100644 --- a/apps/web/components/booking/BookingListItem.tsx +++ b/apps/web/components/booking/BookingListItem.tsx @@ -336,7 +336,7 @@ function BookingListItem(booking: BookingItemProps) { - + diff --git a/apps/web/pages/bookings/[status].tsx b/apps/web/pages/bookings/[status].tsx index bcb05e2cfd..712a627a8e 100644 --- a/apps/web/pages/bookings/[status].tsx +++ b/apps/web/pages/bookings/[status].tsx @@ -179,7 +179,7 @@ export default function Bookings() { )}
- +
{query.data.pages.map((page, index) => ( diff --git a/apps/web/playwright/bookings-list.e2e.ts b/apps/web/playwright/bookings-list.e2e.ts new file mode 100644 index 0000000000..de5ccb55a3 --- /dev/null +++ b/apps/web/playwright/bookings-list.e2e.ts @@ -0,0 +1,113 @@ +import { expect } from "@playwright/test"; + +import { BookingStatus } from "@calcom/prisma/client"; + +import type { Fixtures } from "./lib/fixtures"; +import { test } from "./lib/fixtures"; + +test.afterEach(({ users }) => users.deleteAll()); + +test.describe("Bookings", () => { + test.describe("Upcoming bookings", () => { + test("show attendee bookings and organizer bookings in asc order by startDate", async ({ + page, + users, + bookings, + }) => { + const firstUser = await users.create(); + const secondUser = await users.create(); + + const bookingWhereFirstUserIsOrganizerFixture = await createBooking({ + title: "Booking as organizer", + bookingsFixture: bookings, + // Create a booking 3 days from today + relativeDate: 3, + organizer: firstUser, + organizerEventType: firstUser.eventTypes[0], + attendees: [ + { name: "First", email: "first@cal.com", timeZone: "Europe/Berlin" }, + { name: "Second", email: "second@cal.com", timeZone: "Europe/Berlin" }, + { name: "Third", email: "third@cal.com", timeZone: "Europe/Berlin" }, + ], + }); + const bookingWhereFirstUserIsOrganizer = await bookingWhereFirstUserIsOrganizerFixture.self(); + + const bookingWhereFirstUserIsAttendeeFixture = await createBooking({ + title: "Booking as attendee", + bookingsFixture: bookings, + organizer: secondUser, + // Booking created 2 days from today + relativeDate: 2, + organizerEventType: secondUser.eventTypes[0], + attendees: [ + { name: "OrganizerAsBooker", email: firstUser.email, timeZone: "Europe/Berlin" }, + { name: "Second", email: "second@cal.com", timeZone: "Europe/Berlin" }, + { name: "Third", email: "third@cal.com", timeZone: "Europe/Berlin" }, + ], + }); + const bookingWhereFirstUserIsAttendee = await bookingWhereFirstUserIsAttendeeFixture.self(); + + await firstUser.apiLogin(); + await page.goto(`/bookings/upcoming`); + const upcomingBookings = page.locator('[data-testid="upcoming-bookings"]'); + const firstUpcomingBooking = upcomingBookings.locator('[data-testid="booking-item"]').nth(0); + const secondUpcomingBooking = upcomingBookings.locator('[data-testid="booking-item"]').nth(1); + await expect( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + firstUpcomingBooking.locator(`text=${bookingWhereFirstUserIsAttendee!.title}`) + ).toBeVisible(); + await expect( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + secondUpcomingBooking.locator(`text=${bookingWhereFirstUserIsOrganizer!.title}`) + ).toBeVisible(); + }); + }); +}); + +async function createBooking({ + bookingsFixture, + organizer, + organizerEventType, + attendees, + /** + * Relative date from today + * 0 means today + * 1 means tomorrow + */ + relativeDate = 0, + durationMins = 30, + title, +}: { + bookingsFixture: Fixtures["bookings"]; + organizer: { + id: number; + username: string | null; + }; + organizerEventType: { + id: number; + }; + attendees: { + name: string; + email: string; + timeZone: string; + }[]; + relativeDate?: number; + durationMins?: number; + title: string; +}) { + const DAY_MS = 24 * 60 * 60 * 1000; + const bookingDurationMs = durationMins * 60 * 1000; + const startTime = new Date(Date.now() + relativeDate * DAY_MS); + const endTime = new Date(Date.now() + relativeDate * DAY_MS + bookingDurationMs); + return await bookingsFixture.create(organizer.id, organizer.username, organizerEventType.id, { + title, + status: BookingStatus.ACCEPTED, + startTime, + endTime, + attendees: { + createMany: { + data: [...attendees], + }, + }, + }); +} diff --git a/apps/web/playwright/fixtures/bookings.ts b/apps/web/playwright/fixtures/bookings.ts index 0cc9f18260..dc3ebea4d3 100644 --- a/apps/web/playwright/fixtures/bookings.ts +++ b/apps/web/playwright/fixtures/bookings.ts @@ -19,9 +19,12 @@ export const createBookingsFixture = (page: Page) => { username: string | null, eventTypeId = -1, { + title = "", rescheduled = false, paid = false, status = "ACCEPTED", + startTime, + endTime, attendees = { create: { email: "attendee@example.com", @@ -39,9 +42,9 @@ export const createBookingsFixture = (page: Page) => { const booking = await prisma.booking.create({ data: { uid: uid, - title: "30min", - startTime: startDate, - endTime: endDateParam || dayjs().add(1, "day").add(30, "minutes").toDate(), + title: title || "30min", + startTime: startTime || startDate, + endTime: endTime || endDateParam || dayjs().add(1, "day").add(30, "minutes").toDate(), user: { connect: { id: userId,