* Copy changes
* Move search bar inline with new button
* Get rid of no more results message
* Change hidden badge to (hidden)
* Remove Cal.ai badge from sidebar
* Add dropdown to create button when there is multiple options
* Fix delete dialog
* Saved filters updates
* More string fixes
* Switch members table to use names
* Fix member spacing
* Fix routing form identifier field
* Fix routing forms stuff
* Only show SMS hint on SMS options
* Make workflow delete button minimal
* Fix padding on workflow steps
* Remove min width on workflow title
* Fix delete workflow PR
* Fix org profile buttons
* Fix org profile screen partially scrolled down
* Improve logos & banner uploads
* Personal profile fixes
* Fix settings general view stuff
* Sentence case consistency
* Fix stuff I broke
* Fix fab
* Fix hidden translation string
* Fix text fields
* Make button small for solo users too
* fix: update E2E tests to match sentence case labels in routing forms
* fix: update tests to match sentence case label changes
- insights.e2e.ts: chart titles (14 strings)
- event-types.e2e.ts: Organizer phone number location
- EditLocationDialog.test.tsx: phone number labels
* fix: address Cubic AI review feedback (confidence 9+)
- Replace hardcoded text-gray-500 with text-muted in TextField.tsx hint section
- Replace text locator with data-testid in E2E test for location select
Co-Authored-By: unknown <>
* fix: update E2E tests for sentence case label changes
- Use data-testid selectors for location options (more reliable than text)
- Update field identifiers in routing-forms tests to match new labels
- Fix Long text selector in manage-booking-questions test
* fix: replace text locator with data-testid in manage-booking-questions E2E test
Replace fragile text="Long text" locator with resilient
page.getByTestId("select-option-textarea") selector per E2E best practices.
Addresses Cubic AI review feedback (confidence 9/10).
Co-Authored-By: unknown <>
* fix: use .last() for multiple location select items
---------
Co-authored-by: Pedro Castro <pedro@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
240 lines
7.6 KiB
TypeScript
240 lines
7.6 KiB
TypeScript
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
|
import * as React from "react";
|
|
import { vi } from "vitest";
|
|
|
|
import LocationSelect from "@calcom/features/form/components/LocationSelect";
|
|
|
|
import { QueryCell } from "../../../lib/QueryCell";
|
|
import { EditLocationDialog } from "../EditLocationDialog";
|
|
|
|
// // Mock the trpc hook
|
|
vi.mock("@calcom/trpc/react", () => ({
|
|
trpc: {
|
|
viewer: {
|
|
apps: {
|
|
locationOptions: {
|
|
useQuery: vi.fn(),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}));
|
|
|
|
vi.mock("next/navigation", async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import("next/navigation")>();
|
|
return {
|
|
...actual,
|
|
useRouter: vi.fn(() => ({
|
|
push: vi.fn(() => {
|
|
return;
|
|
}),
|
|
})),
|
|
};
|
|
});
|
|
|
|
vi.mock("@calcom/lib/hooks/useLocale", () => ({
|
|
useLocale: () => ({ t: (key: string) => key }),
|
|
}));
|
|
|
|
vi.mock("../../../lib/QueryCell", () => ({
|
|
QueryCell: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@calcom/features/form/components/LocationSelect", () => {
|
|
return {
|
|
default: vi.fn(),
|
|
};
|
|
});
|
|
|
|
const AttendeePhoneNumberLabel = "Attendee phone number";
|
|
const OrganizerPhoneLabel = "Organizer phone number";
|
|
const CampfireLabel = "Campfire";
|
|
const ZoomVideoLabel = "Zoom Video";
|
|
const OrganizerDefaultConferencingAppLabel = "Organizer's default app";
|
|
|
|
describe("EditLocationDialog", () => {
|
|
const mockProps = {
|
|
saveLocation: vi.fn(),
|
|
setShowLocationModal: vi.fn(),
|
|
isOpenDialog: true,
|
|
};
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
QueryCell.mockImplementation(({ success }) => {
|
|
return success({
|
|
data: [
|
|
{
|
|
label: "Conferencing",
|
|
options: [
|
|
{
|
|
value: "integrations:campfire_video",
|
|
label: CampfireLabel,
|
|
disabled: false,
|
|
icon: "/app-store/campfire/icon.svg",
|
|
slug: "campfire",
|
|
credentialId: 2,
|
|
teamName: null,
|
|
},
|
|
{
|
|
value: "integrations:daily",
|
|
label: "Cal Video (Default)",
|
|
disabled: false,
|
|
icon: "/app-store/dailyvideo/icon.svg",
|
|
slug: "daily-video",
|
|
credentialId: 0,
|
|
teamName: "Global",
|
|
},
|
|
{
|
|
value: "integrations:zoom",
|
|
label: ZoomVideoLabel,
|
|
disabled: false,
|
|
icon: "/app-store/zoomvideo/icon.svg",
|
|
slug: "zoom",
|
|
credentialId: 1,
|
|
teamName: null,
|
|
},
|
|
{
|
|
label: "Organizer's default app",
|
|
value: "conferencing",
|
|
icon: "/link.svg",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "in person",
|
|
options: [
|
|
{
|
|
label: "In Person (Attendee Address)",
|
|
value: "attendeeInPerson",
|
|
icon: "/map-pin-dark.svg",
|
|
},
|
|
{
|
|
label: "In Person (Organizer Address)",
|
|
value: "inPerson",
|
|
icon: "/map-pin-dark.svg",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Other",
|
|
options: [
|
|
{
|
|
label: "Custom attendee location",
|
|
value: "somewhereElse",
|
|
icon: "/message-pin.svg",
|
|
},
|
|
{
|
|
label: "Link meeting",
|
|
value: "link",
|
|
icon: "/link.svg",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "phone",
|
|
options: [
|
|
{
|
|
label: AttendeePhoneNumberLabel,
|
|
value: "phone",
|
|
icon: "/phone.svg",
|
|
},
|
|
{
|
|
label: OrganizerPhoneLabel,
|
|
value: "userPhone",
|
|
icon: "/phone.svg",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
LocationSelect.mockImplementation(
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
({ options, defaultValue, onChange }: { options: any; defaultValue: any; onChange: any }) => {
|
|
return (
|
|
<select
|
|
data-testid="location-select"
|
|
defaultValue={defaultValue}
|
|
onChange={(e) => {
|
|
const selectedOption = options
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
.flatMap((opt: any) => opt.options || [opt])
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
.find((opt: any) => opt.value === e.target.value);
|
|
onChange(selectedOption);
|
|
}}>
|
|
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
|
|
{options.map((group: any) => (
|
|
<optgroup key={group.value} label={group.label}>
|
|
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
|
|
{(group.options || [group]).map((option: any) => (
|
|
<option key={option.value} value={option.value}>
|
|
{option.label}
|
|
</option>
|
|
))}
|
|
</optgroup>
|
|
))}
|
|
</select>
|
|
);
|
|
}
|
|
);
|
|
});
|
|
|
|
it("renders the dialog when open", () => {
|
|
// It shows whatever the location even if it isn't in the options list
|
|
render(<EditLocationDialog {...mockProps} booking={{ location: "Office" }} />);
|
|
expect(screen.getByText("edit_location")).toBeInTheDocument();
|
|
expect(screen.getByText("current_location:")).toBeInTheDocument();
|
|
expect(screen.getByText("Office")).toBeInTheDocument();
|
|
});
|
|
|
|
it("closes the dialog when cancel is clicked", async () => {
|
|
render(<EditLocationDialog {...mockProps} booking={{ location: "Office" }} />);
|
|
fireEvent.click(screen.getByText("cancel"));
|
|
expect(mockProps.setShowLocationModal).toHaveBeenCalledWith(false);
|
|
});
|
|
|
|
describe("Team Booking Case", () => {
|
|
it("should not show Attendee Phone Number but show Organizer Phone Number and dynamic link Conferencing apps", async () => {
|
|
render(<EditLocationDialog {...mockProps} booking={{ location: "Office" }} teamId={1} />);
|
|
|
|
expect(screen.queryByText(AttendeePhoneNumberLabel)).not.toBeInTheDocument();
|
|
expect(screen.queryByText(OrganizerPhoneLabel)).toBeInTheDocument();
|
|
expect(screen.queryByText(CampfireLabel)).toBeInTheDocument();
|
|
expect(screen.queryByText(ZoomVideoLabel)).toBeInTheDocument();
|
|
});
|
|
|
|
it("should update location to Organizer Default App", async () => {
|
|
render(<EditLocationDialog {...mockProps} booking={{ location: "Office" }} teamId={1} />);
|
|
|
|
const select = screen.getByRole("combobox");
|
|
fireEvent.change(select, { target: { value: "conferencing" } });
|
|
// Submit the form
|
|
fireEvent.click(screen.getByText("update"));
|
|
|
|
await waitFor(() => {
|
|
expect(mockProps.saveLocation).toHaveBeenCalledWith({
|
|
newLocation: "conferencing",
|
|
credentialId: null,
|
|
});
|
|
expect(mockProps.setShowLocationModal).toHaveBeenCalledWith(false);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Non Team Booking Case", () => {
|
|
it("should not show Organizer's default app", async () => {
|
|
render(<EditLocationDialog {...mockProps} booking={{ location: "Office" }} />);
|
|
|
|
expect(screen.queryByText(OrganizerDefaultConferencingAppLabel)).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|