import React from "react"; import { render, screen, waitFor, fireEvent } from "test/testUtils"; import DropDownControl from "./DropDownControl"; import { reduxForm } from "redux-form"; import "@testing-library/jest-dom"; import { Provider } from "react-redux"; import configureStore from "redux-mock-store"; import type { SelectOptionProps } from "@appsmith/ads"; const mockStore = configureStore([]); const initialValues = { actionConfiguration: { testPath: ["option1", "option2"] }, }; // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any function TestForm(props: any) { return
{props.children}
; } const ReduxFormDecorator = reduxForm({ form: "TestForm", initialValues })( TestForm, ); const mockOptions = [ { label: "Option 1", value: "option1", children: "Option 1" }, { label: "Option 2", value: "option2", children: "Option 2" }, { label: "Option 3", value: "option3", children: "Option 3" }, ]; const mockAction = { type: "API_ACTION", name: "Test API Action", datasource: { id: "datasource1", name: "Datasource 1" }, actionConfiguration: { body: "", headers: [], testPath: ["option1", "option2"], }, }; const dropDownProps = { options: mockOptions, placeholderText: "Select Columns", isMultiSelect: true, configProperty: "actionConfiguration.testPath", controlType: "PROJECTION", propertyValue: "", label: "Columns", id: "column", formName: "", isValid: true, formValues: mockAction, isLoading: false, maxTagCount: 3, }; describe("DropDownControl", () => { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any let store: any; beforeEach(() => { store = mockStore({ form: { TestForm: { values: initialValues } }, appState: {}, }); }); afterEach(() => { jest.clearAllMocks(); }); it("should renders dropdownControl and options properly", async () => { render( , ); const dropdownSelect = await waitFor(async () => screen.findByTestId("t--dropdown-actionConfiguration.testPath"), ); expect(dropdownSelect).toBeInTheDocument(); const options = screen.getAllByText(/Optio.../); const optionCount = options.length; expect(optionCount).toBe(2); }); it("should clear all selected options", async () => { render( , ); const clearAllButton = document.querySelector(".rc-select-clear"); expect(clearAllButton).toBeInTheDocument(); fireEvent.click(clearAllButton!); await waitFor(() => { const options = screen.queryAllByText(/Option.../); expect(options.length).toBe(0); }); }); it("should handle single select mode correctly", async () => { const singleSelectProps = { ...dropDownProps, isMultiSelect: false, configProperty: "actionConfiguration.singlePath", inputIcon: undefined, showArrow: undefined, }; render( , ); // Wait for component to be fully rendered const dropdownSelect = await screen.findByTestId( "t--dropdown-actionConfiguration.singlePath", ); // Open dropdown fireEvent.mouseDown(dropdownSelect.querySelector(".rc-select-selector")!); // Wait for dropdown to be visible await waitFor(() => { expect(screen.getByRole("listbox")).toBeVisible(); }); // Select Option 1 const option = screen.getByRole("option", { name: "Option 1" }); fireEvent.click(option); // Wait for selection to be applied and verify await waitFor(() => { // Check if the selection is displayed const selectedItem = screen.getByText("Option 1", { selector: ".rc-select-selection-item", }); expect(selectedItem).toBeInTheDocument(); }); // Check if the option is marked as selected const selectedOption = screen.getByRole("option", { name: "Option 1" }); expect(selectedOption).toHaveClass("rc-select-item-option-selected"); // Check that other options are not selected const options = screen.getAllByRole("option"); const selectedCount = options.filter((opt: SelectOptionProps) => opt.classList.contains("rc-select-item-option-selected"), ).length; expect(selectedCount).toBe(1); }); it("should handle multi-select mode correctly", async () => { render( , ); const dropdownSelect = await screen.findByTestId( "t--dropdown-actionConfiguration.testPath", ); // Open dropdown fireEvent.mouseDown(dropdownSelect.querySelector(".rc-select-selector")!); await waitFor(() => { expect(screen.getByRole("listbox")).toBeVisible(); }); // Verify initial selections (Option 1 and Option 2 are selected from initialValues) const initialSelectedOptions = screen .getAllByRole("option") .filter((opt) => opt.getAttribute("aria-selected") === "true"); expect(initialSelectedOptions).toHaveLength(2); }); it("should show placeholder if no option is selected", async () => { const updatedProps = { ...dropDownProps, options: [] }; render( , ); expect(screen.getByText("Select Columns")).toBeInTheDocument(); }); }); describe("DropDownControl grouping tests", () => { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any let store: any; beforeEach(() => { store = mockStore({ form: { GroupingTestForm: { values: { actionConfiguration: { testPath: [] } } }, }, }); }); it("should render grouped options correctly", async () => { const mockOptionGroupConfig = { group1: { label: "Group 1", children: [] }, group2: { label: "Group 2", children: [] }, }; const mockOptions = [ { label: "Option 1", value: "1", optionGroupType: "group1", children: [], }, { label: "Option 2", value: "2", children: [], // No group - should go to Others }, { label: "Option 3", value: "3", optionGroupType: "group2", children: [], }, ]; const props = { ...dropDownProps, options: mockOptions, optionGroupConfig: mockOptionGroupConfig, }; render( , ); // 1. Grab the dropdown container const dropdownSelect = await waitFor(async () => screen.findByTestId("t--dropdown-actionConfiguration.testPath"), ); // Open dropdown fireEvent.mouseDown(dropdownSelect.querySelector(".rc-select-selector")!); // Verify group headers are present await waitFor(() => { expect(screen.getByText("Group 1")).toBeInTheDocument(); }); expect(screen.getByText("Group 2")).toBeInTheDocument(); expect(screen.getByText("Others")).toBeInTheDocument(); // Verify options are in correct groups const group1Option = screen.getByText("Option 1"); const group2Option = screen.getByText("Option 3"); const othersOption = screen.getByText("Option 2"); expect(group1Option).toBeInTheDocument(); expect(group2Option).toBeInTheDocument(); expect(othersOption).toBeInTheDocument(); }); }); describe("DropdownControl Single select tests", () => { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any let store: any; const initialValuesSingleSelect = { actionConfiguration: { testPath: "option1", }, }; const mockActionSingleSelect = { type: "API_ACTION", name: "Test API Action", datasource: { id: "datasource1", name: "Datasource 1", }, actionConfiguration: { body: "", headers: [], testPath: "option1", }, }; const dropDownPropsSingleSelect = { options: mockOptions, placeholderText: "Select Columns", configProperty: "actionConfiguration.testPath", controlType: "PROJECTION", propertyValue: "", label: "Columns", id: "column", formName: "", isValid: true, formValues: mockActionSingleSelect, isLoading: false, maxTagCount: 3, isAllowClear: true, }; beforeEach(() => { store = mockStore({ form: { TestForm: { values: initialValuesSingleSelect, }, }, appState: {}, }); }); it("should clear selected option", async () => { render( , ); const clearAllButton = document.querySelector(".rc-select-clear"); expect(clearAllButton).toBeInTheDocument(); fireEvent.click(clearAllButton!); await waitFor(() => { const options = screen.queryAllByText(/Option.../); expect(options.length).toBe(0); }); }); });