8c39210a12
* chore: add new view for two step slot selection for embed * fix: make sure two step slot selection is false by default * chore: update embed playground to showcase two step slot selection * chore: add tests * chore: update embed snippet generator code to include two step slot selection * chore: update docs * fix: back button styling * chore: implement feedback from cubic * fix: add missing isEnableTwoStepSlotSelectionVisible properties to test mock store Co-Authored-By: unknown <> * chore: implement PR feedback * chore: update slot selection modal * chore: add prop to hide available times header * fix: scope two-step slot selection visibility to mobile only Restores the isMobile check in the timeslot visibility guard to ensure desktop embeds continue to show the booking UI when two-step slot selection is enabled. The feature should only hide the timeslot list on mobile devices. Addresses Cubic AI review feedback (confidence 9/10). Co-Authored-By: unknown <> * fixup: use translations for loading instead of actual word * fix: type check * fix: add window.matchMedia mock for jsdom test environment Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: add window.matchMedia mock to packages/testing/src/setupVitest.ts Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: unit tests failing * add a width style to the two-step slot selection embed container. * refactor: rename enableTwoStepSlotSelection to useSlotsViewOnSmallScreen - Rename external-facing embed config option from enableTwoStepSlotSelection to useSlotsViewOnSmallScreen - Update URL parameter parsing in embed-iframe.ts - Update type definitions in types.ts and index.d.ts - Update internal variable names to slotsViewOnSmallScreen for consistency - Update documentation, playground examples, and tests Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * Add config to prefill all booking fields so that slot has confirm button along with it * chore: implement PR feedback * fix: move twoStepSlotSelection embed outside misc-embeds div to fix e2e test The e2e test was failing because the misc-embeds div content was intercepting pointer events on mobile viewport. This follows the same pattern used for skeletonDemo - the embed is now outside misc-embeds and the div is hidden when testing this namespace. Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: prevent pointer event interception in twoStepSlotSelection embed Hide heading and note elements and set pointer-events: none on container elements while keeping pointer-events: auto on the iframe container. This prevents the container from intercepting clicks on the iframe during mobile viewport e2e tests. Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: hide all non-essential content for twoStepSlotSelection e2e test Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: disable pointer-events on body for twoStepSlotSelection e2e test Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: remove pointer-events: auto on container to let clicks pass through to iframe Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: explicitly set pointer-events: none on container and inline-embed-container Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: also set pointer-events: none on html element to prevent interception Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: make .place div fill viewport for twoStepSlotSelection e2e test Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * fix: failing embed tests * fixup * fixup fixup * fix: failing tests * fix: update checks for verifying prefilled date --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
import dayjs from "@calcom/dayjs";
|
|
import { BookerLayouts } from "@calcom/prisma/zod-utils";
|
|
import type { RenderOptions } from "@testing-library/react";
|
|
import { render } from "@testing-library/react";
|
|
import React, { type ReactElement, type ReactNode } from "react";
|
|
import { vi } from "vitest";
|
|
import type { StoreApi } from "zustand";
|
|
|
|
import { BookerStoreContext } from "../BookerStoreProvider";
|
|
import type { BookerStore } from "../store";
|
|
|
|
interface CustomRenderOptions extends Omit<RenderOptions, "wrapper"> {
|
|
mockStore?: Partial<BookerStore>;
|
|
}
|
|
|
|
// biome-ignore lint/complexity/noExcessiveLinesPerFunction: mock store requires many properties
|
|
const createMockStore = (initialState?: Partial<BookerStore>): StoreApi<BookerStore> => {
|
|
let state: BookerStore = {
|
|
username: null,
|
|
eventSlug: null,
|
|
eventId: null,
|
|
verifiedEmail: null,
|
|
setVerifiedEmail: vi.fn(),
|
|
month: dayjs().format("YYYY-MM"),
|
|
setMonth: vi.fn(),
|
|
state: "loading",
|
|
setState: vi.fn(),
|
|
layout: BookerLayouts.MONTH_VIEW,
|
|
setLayout: vi.fn(),
|
|
selectedDate: null,
|
|
setSelectedDate: vi.fn(),
|
|
addToSelectedDate: vi.fn(),
|
|
selectedDatesAndTimes: null,
|
|
setSelectedDatesAndTimes: vi.fn(),
|
|
durationConfig: null,
|
|
selectedDuration: null,
|
|
setSelectedDuration: vi.fn(),
|
|
selectedTimeslot: null,
|
|
setSelectedTimeslot: vi.fn(),
|
|
tentativeSelectedTimeslots: [],
|
|
setTentativeSelectedTimeslots: vi.fn(),
|
|
recurringEventCount: null,
|
|
setRecurringEventCount: vi.fn(),
|
|
recurringEventCountQueryParam: null,
|
|
setRecurringEventCountQueryParam: vi.fn(),
|
|
dayCount: null,
|
|
setDayCount: vi.fn(),
|
|
rescheduleUid: null,
|
|
rescheduledBy: null,
|
|
bookingUid: null,
|
|
bookingData: null,
|
|
setBookingData: vi.fn(),
|
|
setRescheduleUid: vi.fn(),
|
|
initialize: vi.fn(),
|
|
formValues: {},
|
|
setFormValues: vi.fn(),
|
|
isTeamEvent: false,
|
|
seatedEventData: {},
|
|
setSeatedEventData: vi.fn(),
|
|
isInstantMeeting: false,
|
|
org: null,
|
|
setOrg: vi.fn(),
|
|
timezone: null,
|
|
setTimezone: vi.fn(),
|
|
teamMemberEmail: null,
|
|
crmOwnerRecordType: null,
|
|
crmAppSlug: null,
|
|
crmRecordId: null,
|
|
isPlatform: false,
|
|
allowUpdatingUrlParams: true,
|
|
verificationCode: null,
|
|
setVerificationCode: vi.fn(),
|
|
isSlotSelectionModalVisible: false,
|
|
setIsSlotSelectionModalVisible: vi.fn(),
|
|
...initialState,
|
|
};
|
|
|
|
state.setMonth = vi.fn((month: string | null) => {
|
|
state.month = month;
|
|
});
|
|
|
|
return {
|
|
getState: () => state,
|
|
setState: vi.fn((updater) => {
|
|
if (typeof updater === "function") {
|
|
const newState = updater(state);
|
|
state = { ...state, ...newState };
|
|
} else {
|
|
state = { ...state, ...updater };
|
|
}
|
|
}),
|
|
subscribe: vi.fn(),
|
|
destroy: vi.fn(),
|
|
} as unknown as StoreApi<BookerStore>;
|
|
};
|
|
|
|
export const renderWithBookerStore = (
|
|
ui: ReactElement,
|
|
options?: CustomRenderOptions
|
|
): ReturnType<typeof render> => {
|
|
const mockStore = createMockStore(options?.mockStore);
|
|
|
|
const Wrapper = ({ children }: { children: ReactNode }): ReactElement => (
|
|
<BookerStoreContext.Provider value={mockStore}>{children}</BookerStoreContext.Provider>
|
|
);
|
|
|
|
return render(ui, { wrapper: Wrapper, ...options });
|
|
};
|
|
|
|
export * from "@testing-library/react";
|
|
|
|
export { renderWithBookerStore as render };
|