test: Create unit tests for the questions (teste2e-multiSelectQuestion) (#11569)
* Remove unnecessary changes * add changes * Requested changes * Requested changes * FIx failing tests * FIx failing tests * Update regularBookings.ts * FIx failing tests * Refactor * add unit tests for all questions --------- Co-authored-by: gitstart-calcom <gitstart-calcom@users.noreply.github.com> Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com> Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
This commit is contained in:
co-authored by
gitstart-calcom
GitStart-Cal.com
gitstart-calcom
Morgan
Joe Au-Yeung
parent
e0ac95578c
commit
4ebd52c9af
@@ -213,6 +213,7 @@ export const FormBuilder = function FormBuilder({
|
||||
)}
|
||||
{isUserField && (
|
||||
<Button
|
||||
data-testid="delete-field-action"
|
||||
color="destructive"
|
||||
disabled={!isUserField}
|
||||
variant="icon"
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import { TooltipProvider } from "@radix-ui/react-tooltip";
|
||||
import { render } from "@testing-library/react";
|
||||
import type { ReactNode } from "react";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { vi } from "vitest";
|
||||
|
||||
import { FormBuilder } from "@calcom/features/form-builder/FormBuilder";
|
||||
|
||||
import { mockProps, questionUtils, setMockIntersectionObserver, setMockMatchMedia } from "./utils";
|
||||
|
||||
vi.mock("@formkit/auto-animate/react", () => ({
|
||||
useAutoAnimate: () => [null],
|
||||
}));
|
||||
|
||||
const renderComponent = () => {
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => {
|
||||
const methods = useForm();
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<FormProvider {...methods}>{children}</FormProvider>
|
||||
</TooltipProvider>
|
||||
);
|
||||
};
|
||||
|
||||
return render(<FormBuilder {...mockProps} />, { wrapper: Wrapper });
|
||||
};
|
||||
|
||||
describe("MultiSelect Question", () => {
|
||||
beforeEach(() => {
|
||||
renderComponent();
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
setMockMatchMedia();
|
||||
setMockIntersectionObserver();
|
||||
});
|
||||
|
||||
const questionTypes = [
|
||||
{ questionType: "email", label: "Email Field" },
|
||||
{ questionType: "phone", label: "Phone Field" },
|
||||
{ questionType: "address", label: "Address Field" },
|
||||
{ questionType: "text", label: "Short Text Field" },
|
||||
{ questionType: "number", label: "Number Field" },
|
||||
{ questionType: "textarea", label: "LongText Field" },
|
||||
{ questionType: "select", label: "Select Field" },
|
||||
{ questionType: "multiselect", label: "MultiSelect Field" },
|
||||
{ questionType: "multiemail", label: "Multiple Emails Field" },
|
||||
{ questionType: "checkbox", label: "CheckBox Group Field" },
|
||||
{ questionType: "radio", label: "Radio Group Field" },
|
||||
{ questionType: "boolean", label: "Checkbox Field" },
|
||||
];
|
||||
|
||||
for (const { questionType, label } of questionTypes) {
|
||||
it(`Should handle ${label}`, async () => {
|
||||
const defaultIdentifier = `${questionType}-id`;
|
||||
const newIdentifier = `${defaultIdentifier}-edited`;
|
||||
|
||||
await questionUtils.addQuestion({
|
||||
questionType,
|
||||
identifier: defaultIdentifier,
|
||||
label,
|
||||
});
|
||||
|
||||
await questionUtils.editQuestion({
|
||||
identifier: newIdentifier,
|
||||
existingQuestionId: defaultIdentifier,
|
||||
});
|
||||
|
||||
await questionUtils.requiredAndOptionalQuestion();
|
||||
|
||||
await questionUtils.hideQuestion();
|
||||
|
||||
await questionUtils.deleteQuestion(newIdentifier);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
import { fireEvent, waitFor, screen } from "@testing-library/react";
|
||||
import { vi } from "vitest";
|
||||
|
||||
export interface QuestionProps {
|
||||
questionType: string;
|
||||
identifier: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
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 }[]>;
|
||||
};
|
||||
}
|
||||
|
||||
export const mockProps: FormBuilderProps = {
|
||||
formProp: "formProp",
|
||||
title: "FormBuilder Title",
|
||||
description: "FormBuilder Description",
|
||||
addFieldLabel: "Add Field",
|
||||
disabled: false,
|
||||
LockedIcon: false,
|
||||
dataStore: { options: {} },
|
||||
};
|
||||
|
||||
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 questionUtils = {
|
||||
addQuestion: async (props: QuestionProps) => {
|
||||
fireEvent.click(screen.getByTestId("add-field"));
|
||||
fireEvent.keyDown(screen.getByTestId("test-field-type"), { key: "ArrowDown", code: "ArrowDown" });
|
||||
fireEvent.click(screen.getByTestId("select-option-email"));
|
||||
fireEvent.change(screen.getAllByRole("textbox")[0], { target: { value: props.identifier } });
|
||||
fireEvent.change(screen.getAllByRole("textbox")[1], { target: { value: props.label } });
|
||||
fireEvent.click(screen.getByTestId("field-add-save"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId(`field-${props.identifier}`)).toBeInTheDocument();
|
||||
});
|
||||
},
|
||||
editQuestion: async (props: { identifier: string; existingQuestionId: string }) => {
|
||||
fireEvent.click(screen.getByTestId("edit-field-action"));
|
||||
fireEvent.change(screen.getAllByRole("textbox")[0], { target: { value: props.identifier } });
|
||||
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();
|
||||
});
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user