Merge remote-tracking branch 'origin/main' into chore/add-otel-new
commit
022cfe6ab2
|
@ -2,7 +2,6 @@ import type { NextApiRequest } from "next";
|
|||
import { z } from "zod";
|
||||
|
||||
import { getUserAvailability } from "@calcom/core/getUserAvailability";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import { availabilityUserSelect } from "@calcom/prisma";
|
||||
|
@ -120,10 +119,8 @@ const availabilitySchema = z
|
|||
async function handler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin, userId: reqUserId } = req;
|
||||
const { username, userId, eventTypeId, dateTo, dateFrom, teamId } = availabilitySchema.parse(req.query);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req.headers.host ?? "");
|
||||
if (!teamId)
|
||||
return getUserAvailability({
|
||||
orgSlug: isValidOrgDomain ? currentOrgDomain || undefined : undefined,
|
||||
username,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { TooltipProvider } from "@radix-ui/react-tooltip";
|
||||
import type { Session } from "next-auth";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { EventCollectionProvider } from "next-collect/client";
|
||||
|
@ -33,6 +34,7 @@ export type AppProps = Omit<
|
|||
NextAppProps<
|
||||
WithNonceProps & {
|
||||
themeBasis?: string;
|
||||
session: Session;
|
||||
} & Record<string, unknown>
|
||||
>,
|
||||
"Component"
|
||||
|
@ -81,6 +83,7 @@ const CustomI18nextProvider = (props: AppPropsWithoutNonce) => {
|
|||
},
|
||||
router: locale ? { locale } : props.router,
|
||||
} as unknown as ComponentProps<typeof I18nextAdapter>;
|
||||
|
||||
return <I18nextAdapter {...passedProps} />;
|
||||
};
|
||||
|
||||
|
@ -243,7 +246,6 @@ function OrgBrandProvider({ children }: { children: React.ReactNode }) {
|
|||
}
|
||||
|
||||
const AppProviders = (props: AppPropsWithChildren) => {
|
||||
const session = trpc.viewer.public.session.useQuery().data;
|
||||
// No need to have intercom on public pages - Good for Page Performance
|
||||
const isPublicPage = usePublicPage();
|
||||
const { pageProps, ...rest } = props;
|
||||
|
@ -257,7 +259,7 @@ const AppProviders = (props: AppPropsWithChildren) => {
|
|||
|
||||
const RemainingProviders = (
|
||||
<EventCollectionProvider options={{ apiPath: "/api/collect-events" }}>
|
||||
<SessionProvider session={session || undefined}>
|
||||
<SessionProvider session={pageProps.session ?? undefined}>
|
||||
<CustomI18nextProvider {...propsWithoutNonce}>
|
||||
<TooltipProvider>
|
||||
{/* color-scheme makes background:transparent not work which is required by embed. We need to ensure next-theme adds color-scheme to `body` instead of `html`(https://github.com/pacocoursey/next-themes/blob/main/src/index.tsx#L74). Once that's done we can enable color-scheme support */}
|
||||
|
|
|
@ -11,58 +11,62 @@ test.afterEach(({ users }) => users.deleteAll());
|
|||
|
||||
test.describe("Workflow tests", () => {
|
||||
test.describe("User Workflows", () => {
|
||||
test("Create default reminder workflow & trigger when event type is booked", async ({ page, users }) => {
|
||||
const user = await users.create();
|
||||
const [eventType] = user.eventTypes;
|
||||
await user.login();
|
||||
await page.goto(`/workflows`);
|
||||
// Fixme: This test is failing because the listing isn't immediately updated after the workflow is created
|
||||
test.fixme(
|
||||
"Create default reminder workflow & trigger when event type is booked",
|
||||
async ({ page, users }) => {
|
||||
const user = await users.create();
|
||||
const [eventType] = user.eventTypes;
|
||||
await user.login();
|
||||
await page.goto(`/workflows`);
|
||||
|
||||
await page.click('[data-testid="create-button"]');
|
||||
await page.click('[data-testid="create-button"]');
|
||||
|
||||
// select first event type
|
||||
await page.getByText("Select...").click();
|
||||
await page.getByText(eventType.title, { exact: true }).click();
|
||||
// select first event type
|
||||
await page.getByText("Select...").click();
|
||||
await page.getByText(eventType.title, { exact: true }).click();
|
||||
|
||||
// name workflow
|
||||
await page.fill('[data-testid="workflow-name"]', "Test workflow");
|
||||
// name workflow
|
||||
await page.fill('[data-testid="workflow-name"]', "Test workflow");
|
||||
|
||||
// save workflow
|
||||
await page.click('[data-testid="save-workflow"]');
|
||||
// save workflow
|
||||
await page.click('[data-testid="save-workflow"]');
|
||||
|
||||
// check if workflow is saved
|
||||
await expect(page.locator('[data-testid="workflow-list"] > li')).toHaveCount(1);
|
||||
// check if workflow is saved
|
||||
await expect(page.locator('[data-testid="workflow-list"] > li')).toHaveCount(1);
|
||||
|
||||
// book event type
|
||||
await page.goto(`/${user.username}/${eventType.slug}`);
|
||||
await selectSecondAvailableTimeSlotNextMonth(page);
|
||||
// book event type
|
||||
await page.goto(`/${user.username}/${eventType.slug}`);
|
||||
await selectSecondAvailableTimeSlotNextMonth(page);
|
||||
|
||||
await page.fill('[name="name"]', "Test");
|
||||
await page.fill('[name="email"]', "test@example.com");
|
||||
await page.press('[name="email"]', "Enter");
|
||||
await page.fill('[name="name"]', "Test");
|
||||
await page.fill('[name="email"]', "test@example.com");
|
||||
await page.press('[name="email"]', "Enter");
|
||||
|
||||
// Make sure booking is completed
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
// Make sure booking is completed
|
||||
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
|
||||
|
||||
const booking = await prisma.booking.findFirst({
|
||||
where: {
|
||||
eventTypeId: eventType.id,
|
||||
},
|
||||
});
|
||||
const booking = await prisma.booking.findFirst({
|
||||
where: {
|
||||
eventTypeId: eventType.id,
|
||||
},
|
||||
});
|
||||
|
||||
// check if workflow triggered
|
||||
const workflowReminders = await prisma.workflowReminder.findMany({
|
||||
where: {
|
||||
bookingUid: booking?.uid ?? "",
|
||||
},
|
||||
});
|
||||
// check if workflow triggered
|
||||
const workflowReminders = await prisma.workflowReminder.findMany({
|
||||
where: {
|
||||
bookingUid: booking?.uid ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
expect(workflowReminders).toHaveLength(1);
|
||||
expect(workflowReminders).toHaveLength(1);
|
||||
|
||||
const scheduledDate = dayjs(booking?.startTime).subtract(1, "day").toDate();
|
||||
const scheduledDate = dayjs(booking?.startTime).subtract(1, "day").toDate();
|
||||
|
||||
expect(workflowReminders[0].method).toBe(WorkflowMethods.EMAIL);
|
||||
expect(workflowReminders[0].scheduledDate.toISOString()).toBe(scheduledDate.toISOString());
|
||||
});
|
||||
expect(workflowReminders[0].method).toBe(WorkflowMethods.EMAIL);
|
||||
expect(workflowReminders[0].scheduledDate.toISOString()).toBe(scheduledDate.toISOString());
|
||||
}
|
||||
);
|
||||
|
||||
// add all other actions to this workflow and test if they triggered
|
||||
// cancel booking and test if workflow reminders are deleted
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
"email_verification_code_placeholder": "Geben Sie den Bestätigungscode ein, den Sie per E-Mail erhalten haben",
|
||||
"incorrect_email_verification_code": "Der Bestätigungscode ist falsch.",
|
||||
"email_sent": "E-Mail erfolgreich gesendet",
|
||||
"email_not_sent": "Fehler beim Senden der E-Mail aufgetreten",
|
||||
"event_declined_subject": "Abgelehnt: {{title}} am {{date}}",
|
||||
"event_cancelled_subject": "Abgesagt: {{title}} am {{date}}",
|
||||
"event_request_declined": "Ihre Event-Anfrage wurde abgelehnt",
|
||||
|
@ -83,6 +84,7 @@
|
|||
"event_awaiting_approval_recurring": "Ein wiederkehrender Termin wartet auf Ihre Bestätigung",
|
||||
"someone_requested_an_event": "Jemand hat eine Terminanfrage gestellt.",
|
||||
"someone_requested_password_reset": "Jemand hat einen Link angefordert, um Ihr Passwort zu ändern.",
|
||||
"password_reset_email_sent": "Wenn diese E-Mail-Adresse in unserem System existiert, sollten Sie eine Zurücksetzungs-E-Mail erhalten.",
|
||||
"password_reset_instructions": "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail sicher ignorieren und Ihr Passwort wird nicht geändert.",
|
||||
"event_awaiting_approval_subject": "Warte auf Bestätigung: {{title}} um {{date}}",
|
||||
"event_still_awaiting_approval": "Ein Termin wartet noch auf Ihre Bestätigung",
|
||||
|
@ -222,6 +224,9 @@
|
|||
"already_have_an_account": "Haben Sie bereits ein Konto?",
|
||||
"create_account": "Konto erstellen",
|
||||
"confirm_password": "Passwort bestätigen",
|
||||
"confirm_auth_change": "Dies ändert die Art und Weise, wie Sie sich anmelden",
|
||||
"reset_your_password": "Legen Sie Ihr neues Passwort mit den Anweisungen fest, die an Ihre E-Mail-Adresse gesendet wurden.",
|
||||
"email_change": "Melden Sie sich mit Ihrer neuen E-Mail-Adresse und Ihrem Passwort wieder an.",
|
||||
"create_your_account": "Erstellen Sie Ihr Konto",
|
||||
"sign_up": "Registrieren",
|
||||
"youve_been_logged_out": "Sie wurden abgemeldet",
|
||||
|
@ -851,6 +856,7 @@
|
|||
"team_view_user_availability_disabled": "Der Benutzer muss die Einladung annehmen, um freie Termine zu sehen",
|
||||
"set_as_away": "Stelle deinen Status auf Abwesend",
|
||||
"set_as_free": "Abwesenheitsstatus deaktivieren",
|
||||
"toggle_away_error": "Fehler beim Aktualisieren des Abwesenheitsstatus",
|
||||
"user_away": "Dieser Benutzer ist derzeit abwesend.",
|
||||
"user_away_description": "Die Person, mit der Sie einen Termin buchen wollen, ist zur Zeit abwesend und akzeptiert daher keine neuen Buchungen.",
|
||||
"meet_people_with_the_same_tokens": "Triff Leute mit den selben Token",
|
||||
|
@ -1965,5 +1971,10 @@
|
|||
"org_team_names_example_5": "z.B. Data Analytics Team",
|
||||
"org_max_team_warnings": "Weitere Teams können Sie zu einem späteren Zeitpunkt hinzufügen.",
|
||||
"what_is_this_meeting_about": "Worum geht es in diesem Termin?",
|
||||
"org_admin_other_teams": "Weitere Teams",
|
||||
"no_other_teams_found": "Keine weiteren Teams gefunden",
|
||||
"no_other_teams_found_description": "Es gibt keine weiteren Teams in dieser Organisation.",
|
||||
"attendee_first_name_variable": "Vorname des Teilnehmers",
|
||||
"attendee_last_name_variable": "Nachname des Teilnehmers",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Fügen Sie Ihre neuen Zeichenketten über dieser hinzu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
|
|
@ -3,10 +3,7 @@ import { intersect } from "@calcom/lib/date-ranges";
|
|||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
export const getAggregatedAvailability = (
|
||||
userAvailability: (Omit<
|
||||
Awaited<ReturnType<Awaited<typeof import("./getUserAvailability")>["getUserAvailability"]>>,
|
||||
"currentSeats"
|
||||
> & { user?: { isFixed?: boolean } })[],
|
||||
userAvailability: { dateRanges: DateRange[]; user?: { isFixed?: boolean } }[],
|
||||
schedulingType: SchedulingType | null
|
||||
): DateRange[] => {
|
||||
const fixedHosts = userAvailability.filter(
|
||||
|
|
|
@ -90,8 +90,11 @@ export default function CalComAdapter(prismaClient: PrismaClient) {
|
|||
return { user, session };
|
||||
},
|
||||
createSession: (data: Prisma.SessionCreateInput) => prismaClient.session.create({ data }),
|
||||
updateSession: (data: Prisma.SessionWhereUniqueInput) =>
|
||||
prismaClient.session.update({ where: { sessionToken: data.sessionToken }, data }),
|
||||
updateSession: (data: Prisma.SessionUpdateInput) =>
|
||||
prismaClient.session.update({
|
||||
where: { sessionToken: typeof data.sessionToken === "string" ? data.sessionToken : undefined },
|
||||
data,
|
||||
}),
|
||||
deleteSession: (sessionToken: string) => prismaClient.session.delete({ where: { sessionToken } }),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,9 +11,11 @@ import z from "zod";
|
|||
import { getCalendar } from "@calcom/app-store/_utils/getCalendar";
|
||||
import { metadata as GoogleMeetMetadata } from "@calcom/app-store/googlevideo/_metadata";
|
||||
import type { LocationObject } from "@calcom/app-store/locations";
|
||||
import { OrganizerDefaultConferencingAppType } from "@calcom/app-store/locations";
|
||||
import { getLocationValueForDB } from "@calcom/app-store/locations";
|
||||
import { MeetLocationType } from "@calcom/app-store/locations";
|
||||
import {
|
||||
getLocationValueForDB,
|
||||
MeetLocationType,
|
||||
OrganizerDefaultConferencingAppType,
|
||||
} from "@calcom/app-store/locations";
|
||||
import type { EventTypeAppsList } from "@calcom/app-store/utils";
|
||||
import { getAppFromSlug } from "@calcom/app-store/utils";
|
||||
import { cancelScheduledJobs, scheduleTrigger } from "@calcom/app-store/zapier/lib/nodeScheduler";
|
||||
|
@ -26,8 +28,8 @@ import {
|
|||
sendAttendeeRequestEmail,
|
||||
sendOrganizerRequestEmail,
|
||||
sendRescheduledEmails,
|
||||
sendScheduledEmails,
|
||||
sendRescheduledSeatEmail,
|
||||
sendScheduledEmails,
|
||||
sendScheduledSeatsEmails,
|
||||
} from "@calcom/emails";
|
||||
import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields";
|
||||
|
@ -38,8 +40,8 @@ import {
|
|||
allowDisablingHostConfirmationEmails,
|
||||
} from "@calcom/features/ee/workflows/lib/allowDisablingStandardEmails";
|
||||
import {
|
||||
scheduleWorkflowReminders,
|
||||
cancelWorkflowReminders,
|
||||
scheduleWorkflowReminders,
|
||||
} from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler";
|
||||
import { getFullName } from "@calcom/features/form-builder/utils";
|
||||
import type { GetSubscriberOptions } from "@calcom/features/webhooks/lib/getWebhooks";
|
||||
|
@ -47,7 +49,7 @@ import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks";
|
|||
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
|
||||
import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser";
|
||||
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
|
||||
import { getDefaultEvent, getGroupName, getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
import { getDefaultEvent, getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import getIP from "@calcom/lib/getIP";
|
||||
import getPaymentAppData from "@calcom/lib/getPaymentAppData";
|
||||
|
@ -65,9 +67,9 @@ import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat";
|
|||
import prisma, { userSelect } from "@calcom/prisma";
|
||||
import type { BookingReference } from "@calcom/prisma/client";
|
||||
import { BookingStatus, SchedulingType, WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { bookingCreateSchemaLegacyPropsForApi } from "@calcom/prisma/zod-utils";
|
||||
import {
|
||||
bookingCreateBodySchemaForApi,
|
||||
bookingCreateSchemaLegacyPropsForApi,
|
||||
customInputSchema,
|
||||
EventTypeMetaDataSchema,
|
||||
extendedBookingCreateBody,
|
||||
|
@ -653,9 +655,7 @@ async function handler(
|
|||
const tAttendees = await getTranslation(language ?? "en", "common");
|
||||
const tGuests = await getTranslation("en", "common");
|
||||
log.debug(`Booking eventType ${eventTypeId} started`);
|
||||
const dynamicUserList = Array.isArray(reqBody.user)
|
||||
? getGroupName(reqBody.user)
|
||||
: getUsernameList(reqBody.user);
|
||||
const dynamicUserList = Array.isArray(reqBody.user) ? reqBody.user : getUsernameList(reqBody.user);
|
||||
if (!eventType) throw new HttpError({ statusCode: 404, message: "eventType.notFound" });
|
||||
|
||||
const isTeamEventType =
|
||||
|
|
|
@ -40,11 +40,7 @@ interface handleChildrenEventTypesProps {
|
|||
};
|
||||
}[]
|
||||
| undefined;
|
||||
prisma: PrismaClient<
|
||||
Prisma.PrismaClientOptions,
|
||||
never,
|
||||
Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
|
||||
>;
|
||||
prisma: PrismaClient;
|
||||
}
|
||||
|
||||
const sendAllSlugReplacementEmails = async (
|
||||
|
|
|
@ -93,7 +93,7 @@ export function buildDateRanges({
|
|||
...groupedDateOverrides,
|
||||
}).map(
|
||||
// remove 0-length overrides that were kept to cancel out working dates until now.
|
||||
(ranges) => ranges.filter((range) => !range.start.isSame(range.end))
|
||||
(ranges) => ranges.filter((range) => range.start.valueOf() !== range.end.valueOf())
|
||||
);
|
||||
|
||||
return dateRanges.flat();
|
||||
|
|
|
@ -18,11 +18,7 @@ import { TRPCError } from "@trpc/server";
|
|||
interface getEventTypeByIdProps {
|
||||
eventTypeId: number;
|
||||
userId: number;
|
||||
prisma: PrismaClient<
|
||||
Prisma.PrismaClientOptions,
|
||||
never,
|
||||
Prisma.RejectOnNotFound | Prisma.RejectPerOperation | undefined
|
||||
>;
|
||||
prisma: PrismaClient;
|
||||
isTrpcCall?: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@calcom/lib": "*",
|
||||
"@prisma/client": "^4.16.0",
|
||||
"@prisma/generator-helper": "^4.13.0",
|
||||
"prisma": "^4.16.0",
|
||||
"@prisma/client": "^5.0.0",
|
||||
"@prisma/generator-helper": "^5.0.0",
|
||||
"prisma": "^5.0.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"zod": "^3.20.2",
|
||||
"zod-prisma": "^0.5.4"
|
||||
|
|
|
@ -8,7 +8,7 @@ datasource db {
|
|||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
previewFeatures = ["views", "jsonProtocol"]
|
||||
previewFeatures = ["views"]
|
||||
}
|
||||
|
||||
generator zod {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { countBy } from "lodash";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
import { getAggregateWorkingHours } from "@calcom/core/getAggregateWorkingHours";
|
||||
import { getAggregatedAvailability } from "@calcom/core/getAggregatedAvailability";
|
||||
import type { CurrentSeats } from "@calcom/core/getUserAvailability";
|
||||
import { getUserAvailability } from "@calcom/core/getUserAvailability";
|
||||
|
@ -150,7 +149,11 @@ export async function getDynamicEventType(input: TGetScheduleInputSchema) {
|
|||
const users = await prisma.user.findMany({
|
||||
where: {
|
||||
username: {
|
||||
in: input.usernameList,
|
||||
in: Array.isArray(input.usernameList)
|
||||
? input.usernameList
|
||||
: input.usernameList
|
||||
? [input.usernameList]
|
||||
: [],
|
||||
},
|
||||
},
|
||||
select: {
|
||||
|
@ -226,8 +229,6 @@ export async function getAvailableSlots(input: TGetScheduleInputSchema) {
|
|||
);
|
||||
const {
|
||||
busy,
|
||||
workingHours,
|
||||
dateOverrides,
|
||||
dateRanges,
|
||||
currentSeats: _currentSeats,
|
||||
timeZone,
|
||||
|
@ -253,8 +254,6 @@ export async function getAvailableSlots(input: TGetScheduleInputSchema) {
|
|||
userAvailabilitySpan.end();
|
||||
return {
|
||||
timeZone,
|
||||
workingHours,
|
||||
dateOverrides,
|
||||
dateRanges,
|
||||
busy,
|
||||
user: currentUser,
|
||||
|
@ -298,8 +297,6 @@ export async function getAvailableSlots(input: TGetScheduleInputSchema) {
|
|||
const timeSlots = getSlots({
|
||||
inviteeDate: startTime,
|
||||
eventLength: input.duration || eventType.length,
|
||||
workingHours,
|
||||
dateOverrides,
|
||||
offsetStart: eventType.offsetStart,
|
||||
dateRanges: getAggregatedAvailability(userAvailability, eventType.schedulingType),
|
||||
minimumBookingNotice: eventType.minimumBookingNotice,
|
||||
|
|
|
@ -62,7 +62,7 @@ export const DefaultToast = ({ message, toastVisible, onClose, toastId }: IToast
|
|||
<span>
|
||||
<Check className="h-4 w-4" />
|
||||
</span>
|
||||
<p>{message}</p>
|
||||
<p data-testid="toast-default">{message}</p>
|
||||
</button>
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { render, screen, fireEvent } from "@testing-library/react";
|
||||
import { vi } from "vitest";
|
||||
|
||||
import { SuccessToast, ErrorToast, WarningToast, DefaultToast } from "./showToast";
|
||||
|
||||
describe("Tests for Toast Components", () => {
|
||||
const testToastComponent = (Component: typeof DefaultToast, toastTestId: string) => {
|
||||
const message = "This is a test message";
|
||||
const toastId = "some-id";
|
||||
|
||||
const onCloseMock = vi.fn();
|
||||
render(<Component message={message} toastVisible={true} onClose={onCloseMock} toastId={toastId} />);
|
||||
|
||||
const toast = screen.getByTestId(toastTestId);
|
||||
expect(toast).toBeInTheDocument();
|
||||
expect(toast.textContent).toContain(message);
|
||||
|
||||
const closeButton = screen.getByRole("button");
|
||||
fireEvent.click(closeButton);
|
||||
expect(onCloseMock).toHaveBeenCalledWith(toastId);
|
||||
};
|
||||
|
||||
const toastComponents: [string, typeof DefaultToast, string][] = [
|
||||
["SuccessToast", SuccessToast, "toast-success"],
|
||||
["ErrorToast", ErrorToast, "toast-error"],
|
||||
["WarningToast", WarningToast, "toast-warning"],
|
||||
["DefaultToast", DefaultToast, "toast-default"],
|
||||
];
|
||||
|
||||
test.each(toastComponents)("Should render and close %s component", (_, ToastComponent, expectedClass) => {
|
||||
testToastComponent(ToastComponent, expectedClass);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue