* 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>
291 lines
7.6 KiB
TypeScript
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();
|
|
});
|
|
});
|
|
});
|