test: add test for invalid cal video (#13103)

* test: add test for invalid cal video

* chore: add confirm

* chore: fix type error

* chore: update code

* test: add unit test

* chore: type error

* chore

* chore: type

* chore: fix test

* chore

---------

Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
This commit is contained in:
Udit Takkar
2024-01-15 15:07:58 -05:00
committed by GitHub
co-authored by Carina Wollendorfer
parent 13a765e50a
commit 7ec3d04acc
6 changed files with 112 additions and 7 deletions
@@ -147,6 +147,7 @@ function BookingListItem(booking: BookingItemProps) {
? [
{
id: "confirm",
bookingId: booking.id,
label: (isTabRecurring || isTabUnconfirmed) && isRecurring ? t("confirm_all") : t("confirm"),
onClick: () => {
bookingConfirm(true);
+5 -6
View File
@@ -8,6 +8,7 @@ import { useState, useEffect, useRef } from "react";
import dayjs from "@calcom/dayjs";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { getCalVideoReference } from "@calcom/features/get-cal-video-reference";
import classNames from "@calcom/lib/classNames";
import { APP_NAME, SEO_IMG_OGIMG_VIDEO, WEBSITE_URL } from "@calcom/lib/constants";
import { formatToLocalizedDate, formatToLocalizedTime } from "@calcom/lib/date-fns";
@@ -332,15 +333,13 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
bookRef.meetingPassword = null;
});
}
const videoReferences = bookingObj.references.filter((reference) => reference.type.includes("_video"));
const latestVideoReference = videoReferences[videoReferences.length - 1];
const videoReference = getCalVideoReference(bookingObj.references);
return {
props: {
meetingUrl: latestVideoReference.meetingUrl ?? "",
...(typeof latestVideoReference.meetingPassword === "string" && {
meetingPassword: latestVideoReference.meetingPassword,
meetingUrl: videoReference.meetingUrl ?? "",
...(typeof videoReference.meetingPassword === "string" && {
meetingPassword: videoReference.meetingPassword,
}),
booking: {
...bookingObj,
+62 -1
View File
@@ -3,9 +3,10 @@ import { expect } from "@playwright/test";
import dayjs from "@calcom/dayjs";
import prisma from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/enums";
import { bookingMetadataSchema } from "@calcom/prisma/zod-utils";
import { test } from "./lib/fixtures";
import { selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
import { selectFirstAvailableTimeSlotNextMonth, bookTimeSlot } from "./lib/testUtils";
const IS_STRIPE_ENABLED = !!(
process.env.STRIPE_CLIENT_ID &&
@@ -270,4 +271,64 @@ test.describe("Reschedule Tests", async () => {
await page.locator('[data-testid="confirm-reschedule-button"]').click();
await expect(page).toHaveURL(/.*booking/);
});
test("Should load Valid Cal video url after rescheduling Opt in events", async ({
page,
users,
bookings,
}) => {
const user = await users.create();
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const eventType = user.eventTypes.find((e) => e.slug === "opt-in")!;
const confirmBooking = async (bookingId: number) => {
await user.apiLogin();
await page.goto("/bookings/upcoming");
const elem = await page.locator(`[data-bookingid="${bookingId}"][data-testid="confirm"]`);
await elem.click();
await page.getByTestId("toast-success").waitFor();
await user.logout();
};
await page.goto(`/${user.username}/${eventType.slug}`);
await selectFirstAvailableTimeSlotNextMonth(page);
await bookTimeSlot(page);
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
const pageUrl = new URL(page.url());
const pathSegments = pageUrl.pathname.split("/");
const bookingUID = pathSegments[pathSegments.length - 1];
const currentBooking = await prisma.booking.findFirst({ where: { uid: bookingUID } });
expect(currentBooking).not.toBeUndefined();
// eslint-disable-next-line playwright/no-conditional-in-test
if (currentBooking) {
await confirmBooking(currentBooking.id);
await page.goto(`/${user.username}/${eventType.slug}?rescheduleUid=${currentBooking.uid}`);
await selectFirstAvailableTimeSlotNextMonth(page);
await page.locator('[data-testid="confirm-reschedule-button"]').click();
await expect(page).toHaveURL(/.*booking/);
const newBooking = await prisma.booking.findFirst({ where: { fromReschedule: currentBooking.uid } });
expect(newBooking).not.toBeUndefined();
expect(newBooking?.status).toBe(BookingStatus.PENDING);
// eslint-disable-next-line playwright/no-conditional-in-test
if (newBooking) {
await confirmBooking(newBooking?.id);
const booking = await prisma.booking.findFirst({ where: { id: newBooking.id } });
expect(booking).not.toBeUndefined();
expect(booking?.status).toBe(BookingStatus.ACCEPTED);
const locationVideoCallUrl = bookingMetadataSchema.parse(booking?.metadata || {})?.videoCallUrl;
expect(locationVideoCallUrl).not.toBeUndefined();
// eslint-disable-next-line playwright/no-conditional-in-test
if (booking && locationVideoCallUrl) {
await page.goto(locationVideoCallUrl);
await expect(page.frameLocator("iFrame").locator('text="Continue"')).toBeVisible();
}
}
}
});
});
@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";
import { getCalVideoReference } from "./get-cal-video-reference";
describe("Cal Video", () => {
it("should load latest cal video reference", () => {
expect(
getCalVideoReference([
{
uid: "UID1",
type: "daily_video",
meetingUrl: "ID1",
meetingPassword: "P1",
},
{
uid: "UID2",
type: "daily_video",
meetingUrl: "ID2",
meetingPassword: "P2",
},
])
).toEqual({
uid: "UID2",
type: "daily_video",
meetingUrl: "ID2",
meetingPassword: "P2",
});
});
});
@@ -0,0 +1,12 @@
export type Reference = {
uid: string;
type: string;
meetingUrl: string | null;
meetingPassword: string | null;
};
export const getCalVideoReference = (references: Reference[]) => {
const videoReferences = references.filter((reference) => reference.type.includes("_video"));
const latestVideoReference = videoReferences[videoReferences.length - 1];
return latestVideoReference;
};
@@ -21,6 +21,7 @@ export type ActionType = {
label: string;
disabled?: boolean;
color?: ButtonBaseProps["color"];
bookingId?: number;
} & (
| { href: string; onClick?: never; actions?: never }
| { href?: never; onClick: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void; actions?: never }
@@ -61,6 +62,7 @@ export const DropdownActions = ({
data-testid={action.id}
StartIcon={action.icon}
href={action.href}
data-bookingid={action.bookingId}
onClick={action.onClick || defaultAction}>
{action.label}
</DropdownItem>
@@ -87,6 +89,7 @@ export const TableActions: FC<Props> = ({ actions }) => {
StartIcon={action.icon}
{...(action?.actions ? { EndIcon: ChevronDown } : null)}
disabled={action.disabled}
data-bookingid={action.bookingId}
color={action.color || "secondary"}>
{action.label}
</Button>