* feat:add prefilcheck check box in the field creation * chore:formatted the li8 translations * feat:add e2e test case for this feature * refactor:reanmed the key from prefilledCheck to disableOnPrefill and moved the readOnly logic to formbuilderField * chore:fixed the type check * fix:if prefilled has error. do not disabble it * chore:removed the e2e tests for prefill in e2e * chore:revert back to old changes * chore:remove unwanted code frome2e * Support name field as well * refactor:handled the feedback changes. still unit test cases pending * feat: add unit tests for disable field on prefill logic * chore: resolved the type check and typos * chore:renamed the files and type clean up * Apply suggestions from code review * chore:renaming test files and moving the disableonprefill hook to formbuilderFeild. * refactor: add unit test for serach params and form values check and minor code formatting and file name changes * fix: validating the input value partially at the intialising phase. so that form response values and from ui values are same and making sure invalid data not sent to backend on submit. * chore:fix the type check issue * fix: field value valdiation at initilisation and add the unit test cases for that change * chore:add comments to the tests * chore:resolve type check * chore: moved the tests to the formBuilder * Simplify codebase by ensuring select and multiselect changes the value when no option is found * Relocate and refactor tests * handle special cases * Dont disable for dirty fields * Update schema.prisma --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Hariom <hariombalhara@gmail.com>
185 lines
5.8 KiB
TypeScript
185 lines
5.8 KiB
TypeScript
import { fireEvent, waitFor, screen } from "@testing-library/react";
|
|
import { vi } from "vitest";
|
|
import type { z } from "zod";
|
|
|
|
import type { fieldsSchema } from "@calcom/features/form-builder/schema";
|
|
|
|
type RhfForm = {
|
|
fields: z.infer<typeof fieldsSchema>;
|
|
};
|
|
|
|
type RhfFormFields = RhfForm["fields"];
|
|
|
|
export type RhfFormField = RhfFormFields[number];
|
|
|
|
export type FieldType = RhfFormField["type"];
|
|
export interface QuestionProps {
|
|
questionType: string;
|
|
identifier: string;
|
|
label: string;
|
|
disableOnPrefill?: boolean;
|
|
}
|
|
|
|
export interface FormBuilderProps {
|
|
formProp: string;
|
|
title: string;
|
|
description: string;
|
|
addFieldLabel: string;
|
|
disabled: boolean;
|
|
LockedIcon: false | JSX.Element;
|
|
dataStore: {
|
|
options: Record<string, { label: string; value: string; inputPlaceholder?: string }[]>;
|
|
};
|
|
disableOnPrefill?: boolean;
|
|
}
|
|
|
|
export interface FormBuildFieldProps {
|
|
field: Omit<RhfFormField, "editable" | "label"> & {
|
|
// Label is optional because radioInput doesn't have a label
|
|
label?: string;
|
|
value: string;
|
|
};
|
|
readOnly: boolean;
|
|
}
|
|
|
|
export const mockProps: FormBuilderProps = {
|
|
formProp: "formProp",
|
|
title: "FormBuilder Title",
|
|
description: "FormBuilder Description",
|
|
addFieldLabel: "Add Field",
|
|
disabled: false,
|
|
LockedIcon: false,
|
|
dataStore: { options: {} },
|
|
disableOnPrefill: false,
|
|
};
|
|
|
|
export const mockFieldProps: FormBuildFieldProps = {
|
|
field: {
|
|
type: "text",
|
|
name: "test-text-n",
|
|
variant: "text",
|
|
placeholder: "text-test-p",
|
|
required: false,
|
|
label: "text-test-l",
|
|
disableOnPrefill: false,
|
|
value: "",
|
|
},
|
|
readOnly: false,
|
|
};
|
|
|
|
export const setMockMatchMedia = () => {
|
|
Object.defineProperty(window, "matchMedia", {
|
|
value: vi.fn().mockImplementation((query) => ({
|
|
matches: false,
|
|
media: query,
|
|
onchange: null,
|
|
addEventListener: vi.fn(),
|
|
removeEventListener: vi.fn(),
|
|
dispatchEvent: vi.fn(),
|
|
})),
|
|
});
|
|
};
|
|
|
|
export const setMockIntersectionObserver = () => {
|
|
Object.defineProperty(window, "IntersectionObserver", {
|
|
value: vi.fn().mockImplementation(() => ({
|
|
observe: vi.fn(),
|
|
unobserve: vi.fn(),
|
|
disconnect: vi.fn(),
|
|
takeRecords: vi.fn(() => []),
|
|
})),
|
|
});
|
|
};
|
|
|
|
export const clickDisablePrefillBasedOnUserInput = (disableOnPrefill?: boolean) => {
|
|
if (typeof disableOnPrefill === "boolean") {
|
|
// Get the checkbox element
|
|
const checkbox = getDisablePrefillCheckbox(disableOnPrefill) as HTMLInputElement;
|
|
|
|
// Determine if the checkbox's current state differs from the `disableOnPrefill` prop
|
|
const isChecked = checkbox ? checkbox.checked : false;
|
|
|
|
// Click the checkbox only if its current state differs from the `disableOnPrefill` value
|
|
if (isChecked !== disableOnPrefill) {
|
|
fireEvent.click(checkbox);
|
|
}
|
|
}
|
|
};
|
|
|
|
export const getDisablePrefillCheckbox = (disableOnPrefill?: boolean) => {
|
|
if (typeof disableOnPrefill === "boolean") {
|
|
const checkbox = screen.getByRole("checkbox", { name: /disable_input_if_prefilled/i });
|
|
return checkbox;
|
|
}
|
|
};
|
|
|
|
export const checkForDisablePreFillCheckox = (disableOnPrefill?: boolean) => {
|
|
const checkbox = getDisablePrefillCheckbox(disableOnPrefill);
|
|
expect(checkbox).toBeInTheDocument();
|
|
};
|
|
|
|
export const questionUtils = {
|
|
addQuestion: async (props: QuestionProps) => {
|
|
fireEvent.click(screen.getByTestId("add-field"));
|
|
checkForDisablePreFillCheckox(props?.disableOnPrefill);
|
|
fireEvent.keyDown(screen.getByTestId("test-field-type"), { key: "ArrowDown", code: "ArrowDown" });
|
|
fireEvent.click(screen.getByTestId(`select-option-${props.questionType}`));
|
|
fireEvent.change(screen.getAllByRole("textbox")[0], { target: { value: props.identifier } });
|
|
fireEvent.change(screen.getAllByRole("textbox")[1], { target: { value: props.label } });
|
|
clickDisablePrefillBasedOnUserInput(props?.disableOnPrefill);
|
|
fireEvent.click(screen.getByTestId("field-add-save"));
|
|
await waitFor(() => {
|
|
expect(screen.queryByTestId(`field-${props.identifier}`)).toBeInTheDocument();
|
|
});
|
|
},
|
|
editQuestion: async (props: {
|
|
identifier: string;
|
|
existingQuestionId: string;
|
|
disableOnPrefill?: boolean;
|
|
}) => {
|
|
fireEvent.click(screen.getByTestId("edit-field-action"));
|
|
checkForDisablePreFillCheckox(props?.disableOnPrefill);
|
|
fireEvent.change(screen.getAllByRole("textbox")[0], { target: { value: props.identifier } });
|
|
clickDisablePrefillBasedOnUserInput(props?.disableOnPrefill);
|
|
|
|
fireEvent.click(screen.getByTestId("field-add-save"));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByTestId(`field-${props.identifier}`)).toBeInTheDocument();
|
|
expect(screen.queryByTestId(`field-${props.existingQuestionId}`)).not.toBeInTheDocument();
|
|
});
|
|
},
|
|
deleteQuestion: async (existingQuestionId: string) => {
|
|
expect(screen.queryByTestId(`field-${existingQuestionId}`)).toBeInTheDocument();
|
|
|
|
fireEvent.click(screen.getByTestId("delete-field-action"));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByTestId(`field-${existingQuestionId}`)).not.toBeInTheDocument();
|
|
});
|
|
},
|
|
hideQuestion: async () => {
|
|
fireEvent.click(screen.getByTestId("toggle-field"));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByText(/hidden/i)).toBeInTheDocument();
|
|
});
|
|
},
|
|
requiredAndOptionalQuestion: async () => {
|
|
expect(screen.queryByTestId("required")).toBeInTheDocument();
|
|
|
|
fireEvent.click(screen.getByTestId("edit-field-action"));
|
|
fireEvent.click(screen.getAllByRole("radio")[1]);
|
|
fireEvent.click(screen.getByTestId("field-add-save"));
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId("optional")).toBeInTheDocument();
|
|
});
|
|
},
|
|
expectedValueForDisablePreFillCheckox: async (expectedValue: boolean) => {
|
|
fireEvent.click(screen.getByTestId("edit-field-action"));
|
|
const checkbox = getDisablePrefillCheckbox(expectedValue) as HTMLInputElement;
|
|
await expect(checkbox?.checked).toBe(expectedValue);
|
|
},
|
|
};
|