Files
cal.diy/packages/features/bookings/Booker/components/hooks/useInitialFormValues.test.ts
T
a0eca13c18 feat: add organization-level autofill disable setting (#23504)
* feat: add organization-level autofill disable setting

- Create DisableAutofillOnBookingPageSwitch component following existing patterns
- Add toggle to organization general page alongside other settings
- Update tRPC organizations update handler to support new field
- Add organization-level check to useShouldBeDisabledDueToPrefill hook
- Add translation keys for new autofill disable setting
- Include database migration for disableAutofillOnBookingPage field
- Maintain backward compatibility with individual field settings

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* feat: complete autofill disable implementation

- Add disableAutofillOnBookingPage to orgSettings type definition
- Update Prisma schema with new organization setting field
- Clean up test file formatting

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* fix: resolve tRPC mocking issues in tests and add missing disableAutofillOnBookingPage to organization repository

- Fix tRPC module mocking in useShouldBeDisabledDueToPrefill tests
- Add disableAutofillOnBookingPage to organization repository select and return statements
- All form builder tests now pass (24/24)
- Organization-level autofill disable tests working correctly

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* test: simplify autofill disable test to single focused test

- Replace multiple tests with one test that verifies org setting blocks autocomplete
- Test includes searchParams with prefill data to verify blocking behavior
- Removes unnecessary test complexity as requested

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* fix: add missing disableAutofillOnBookingPage to organizationSettings select statements

- Add disableAutofillOnBookingPage to both parent and main organizationSettings select statements in getTeamWithMembers
- Resolves TypeScript error in getServerSideProps.tsx where MinimumOrganizationSettings type requires this property
- Ensures organization settings type compatibility across the codebase

Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>

* Remove disableAutofillOnBookingPage setting

Removed 'disableAutofillOnBookingPage' setting from organization configuration.

* update

* Remove duplicate settings in common.json

Removed duplicate entries for automatic transcription and autofill settings.

* Fix syntax error in common.json

* update

* add tests

* Remove comments for autofill disabled check

Removed comments explaining scenarios for autofill check.

* addressed review

* fix

* change

* Add handling for disableAutofillOnBookingPage input

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-11-19 08:25:46 +00:00

291 lines
7.6 KiB
TypeScript

/**
* @vitest-environment jsdom
*/
import { renderHook, waitFor } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach } from "vitest";
import type { BookerEvent } from "@calcom/features/bookings/types";
import { useInitialFormValues } from "./useInitialFormValues";
vi.mock("@calcom/features/bookings/Booker/store", () => ({
useBookerStore: vi.fn((selector) => {
const state = {
bookingData: null,
formValues: {},
};
return selector(state);
}),
}));
vi.mock("@calcom/features/bookings/lib/getBookingResponsesSchema", () => ({
getBookingResponsesPartialSchema: vi.fn(() => ({
parseAsync: vi.fn((data) => Promise.resolve(data)),
})),
}));
describe("useInitialFormValues - Autofill Disable Feature", () => {
const mockBookingFields = [
{ name: "name", type: "text" as const, required: true },
{ name: "email", type: "email" as const, required: true },
{ name: "phone", type: "phone" as const, required: false },
] as unknown as BookerEvent["bookingFields"];
const baseProps = {
rescheduleUid: null,
isRescheduling: false,
email: null,
name: null,
username: null,
hasSession: false,
extraOptions: {},
prefillFormParams: {
guests: [],
name: null,
},
};
beforeEach(() => {
vi.clearAllMocks();
});
describe("when organization has NOT disabled autofill", () => {
it("should use URL parameters to prefill form fields", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: {
organizationSettings: {
disableAutofillOnBookingPage: false,
},
},
owner: null,
};
const extraOptions = {
phone: "+1234567890",
customField: "custom value",
};
const prefillFormParams = {
guests: ["guest1@example.com", "guest2@example.com"],
name: "John Doe",
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
prefillFormParams,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses).toMatchObject({
name: "John Doe",
phone: "+1234567890",
});
});
it("should use URL parameters when organizationSettings is undefined", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: null,
owner: null,
};
const extraOptions = {
phone: "+1234567890",
};
const prefillFormParams = {
guests: [],
name: "Jane Smith",
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
prefillFormParams,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses).toMatchObject({
name: "Jane Smith",
phone: "+1234567890",
});
});
});
describe("when organization HAS disabled autofill", () => {
it("should NOT use URL parameters when team.organizationSettings.disableAutofillOnBookingPage is true", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: {
parent: {
organizationSettings: {
disableAutofillOnBookingPage: true,
},
},
},
owner: null,
};
const extraOptions = {
phone: "+1234567890",
customField: "custom value",
};
const prefillFormParams = {
guests: ["guest1@example.com"],
name: "John Doe",
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
prefillFormParams,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses?.phone).toBeUndefined();
expect(result.current.values.responses?.name).toBe("");
});
it("should NOT use URL parameters when team.parent.organizationSettings.disableAutofillOnBookingPage is true", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: {
organizationSettings: null,
parent: {
organizationSettings: {
disableAutofillOnBookingPage: true,
},
},
},
owner: null,
};
const extraOptions = {
phone: "+9876543210",
};
const prefillFormParams = {
guests: [],
name: "Parent Team User",
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
prefillFormParams,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses?.phone).toBeUndefined();
expect(result.current.values.responses?.name).toBe("");
});
it("should NOT use URL parameters when owner.organization.organizationSettings.disableAutofillOnBookingPage is true", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: null,
owner: {
profile: {
organization: {
organizationSettings: {
disableAutofillOnBookingPage: true,
},
},
},
},
};
const extraOptions = {
phone: "+5555555555",
};
const prefillFormParams = {
guests: [],
name: "Personal Event User",
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
prefillFormParams,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses?.phone).toBeUndefined();
expect(result.current.values.responses?.name).toBe("");
});
});
describe("session data handling with autofill disabled", () => {
it("should not use session email/name when autofill is disabled", async () => {
const eventType: Pick<BookerEvent, "bookingFields" | "team" | "owner"> = {
bookingFields: mockBookingFields,
team: {
parent: {
organizationSettings: {
disableAutofillOnBookingPage: true,
},
},
},
owner: null,
};
const extraOptions = {
phone: "+1234567890", // This should be blocked
};
const { result } = renderHook(() =>
useInitialFormValues({
...baseProps,
eventType,
extraOptions,
email: "session@example.com", // Session data
name: "Session User", // Session data
hasSession: true,
})
);
await waitFor(() => {
expect(result.current.values.responses).toBeDefined();
});
expect(result.current.values.responses?.email).toBe("");
expect(result.current.values.responses?.name).toBe("");
expect(result.current.values.responses?.phone).toBeUndefined();
});
});
});