PromucFlow_constructor/app/client/src/components/formControls/DropDownControl.test.tsx

222 lines
5.8 KiB
TypeScript
Raw Normal View History

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";
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 <div>{props.children}</div>;
}
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,
};
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: {},
});
});
it("should renders dropdownControl and options properly", async () => {
render(
<Provider store={store}>
<ReduxFormDecorator>
<DropDownControl {...dropDownProps} />
</ReduxFormDecorator>
</Provider>,
);
const dropdownSelect = await waitFor(async () =>
screen.findByTestId("t--dropdown-actionConfiguration.testPath"),
);
expect(dropdownSelect).toBeInTheDocument();
const options = screen.getAllByText(/Optio.../);
const optionCount = options.length;
chore: add blank line eslint rule (#36369) ## Description Added ESLint rule to force blank lines between statements. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### :mag: Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10924926728> > Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.All > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Wed, 18 Sep 2024 16:33:36 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No --------- Co-authored-by: Valera Melnikov <valera@appsmith.com>
2024-09-18 16:35:28 +00:00
expect(optionCount).toBe(2);
});
it("should clear all selected options", async () => {
render(
<Provider store={store}>
<ReduxFormDecorator>
<DropDownControl {...dropDownProps} />
</ReduxFormDecorator>
</Provider>,
);
const clearAllButton = document.querySelector(".rc-select-clear");
expect(clearAllButton).toBeInTheDocument();
fireEvent.click(clearAllButton!);
await waitFor(() => {
const options = screen.queryAllByText(/Option.../);
chore: add blank line eslint rule (#36369) ## Description Added ESLint rule to force blank lines between statements. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.All" ### :mag: Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!CAUTION] > 🔴 🔴 🔴 Some tests have failed. > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10924926728> > Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank">Cypress dashboard</a>. > Tags: @tag.All > Spec: > The following are new failures, please fix them before merging the PR: <ol> > <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts > <li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol> > <a href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master" target="_blank">List of identified flaky tests</a>. > <hr>Wed, 18 Sep 2024 16:33:36 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No --------- Co-authored-by: Valera Melnikov <valera@appsmith.com>
2024-09-18 16:35:28 +00:00
expect(options.length).toBe(0);
});
});
});
feat: select widget grouping (#38686) ## Description This PR adds grouping capabilities to our dropdown control component (using `rc-select`). Specifically: - Introduces an `optionGroupConfig` object that maps each group key to a label and collects relevant options under it. - Defaults any ungrouped options to the “Others” group if no matching group is found. - Includes refactoring to maintain backward compatibility for non-grouped dropdown usage. Additionally: - New tests are added to validate grouped dropdown behaviour. - Existing multi-select and clear-all functionality is unaffected. Sample config for the grouping to be enabled ``` { "label": "Command", "description": "Choose method you would like to use to query the database", "configProperty": "actionConfiguration.formData.command.data", "controlType": "DROP_DOWN", "initialValue": "FIND", "options": [ { "label": "Find document(s)", "value": "FIND", "optionGroupType": "testGrp1" }, { "label": "Insert document(s)", "value": "INSERT", "optionGroupType": "testGrp1" }, { "label": "Update document(s)", "value": "UPDATE", "optionGroupType": "testGrp2" }, { "label": "Delete document(s)", "value": "DELETE", "optionGroupType": "testGrp2" }, { "label": "Count", "value": "COUNT", "optionGroupType": "testGrp2" }, { "label": "Distinct", "value": "DISTINCT", "optionGroupType": "testGrp3" }, { "label": "Aggregate", "value": "AGGREGATE", "optionGroupType": "testGrp3" }, { "label": "Raw", "value": "RAW", "optionGroupType": "testGrp3" } ], "optionGroupConfig": { "testGrp1": { "label": "Group 1", "children": [] }, "testGrp2": { "label": "Group 2", "children": [] }, "testGrp3": { "label": "Group 3", "children": [] } } } ``` Fixes #38079 ## Automation /ok-to-test tags="@tag.Sanity, @tag.IDE" ### :mag: Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/13059919318> > Commit: f08c31b3e5d81318144e3a71d652526fd1b01a00 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=13059919318&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity, @tag.IDE` > Spec: > <hr>Thu, 30 Jan 2025 20:22:48 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes - **New Features** - Added option grouping functionality to the Select component. - Introduced the ability to organize dropdown options into labeled groups. - Enhanced dropdown visual hierarchy with group-based option display. - **Improvements** - Updated Select component type definitions to support option grouping. - Added CSS styles for improved presentation of option groups and grouped options. - **Testing** - Added comprehensive test coverage for dropdown option grouping functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-01-31 07:06:42 +00:00
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 when optionGroupConfig is provided", async () => {
// These config & options demonstrate grouping
const mockOptionGroupConfig = {
testGrp1: {
label: "Group 1",
children: [],
},
testGrp2: {
label: "Group 2",
children: [],
},
};
const mockGroupedOptions = [
{
label: "Option 1",
value: "option1",
children: "Option 1",
optionGroupType: "testGrp1",
},
{
label: "Option 2",
value: "option2",
children: "Option 2",
// Intentionally no optionGroupType => Should fall under default "Others" group
},
{
label: "Option 3",
value: "option3",
children: "Option 3",
optionGroupType: "testGrp2",
},
];
const props = {
...dropDownProps,
controlType: "DROP_DOWN",
options: mockGroupedOptions,
optionGroupConfig: mockOptionGroupConfig,
};
render(
<Provider store={store}>
<ReduxFormDecorator>
<DropDownControl {...props} />
</ReduxFormDecorator>
</Provider>,
);
// 1. Grab the dropdown container
const dropdownSelect = await waitFor(async () =>
screen.findByTestId("t--dropdown-actionConfiguration.testPath"),
);
expect(dropdownSelect).toBeInTheDocument();
// 2. Click to open the dropdown
// @ts-expect-error: the test will fail if component doesn't exist
fireEvent.mouseDown(dropdownSelect.querySelector(".rc-select-selector"));
// 3. We expect to see group labels from the config
// 'Group 1' & 'Group 2' come from the mockOptionGroupConfig
const group1Label = await screen.findByText("Group 1");
const group2Label = await screen.findByText("Group 2");
expect(group1Label).toBeInTheDocument();
expect(group2Label).toBeInTheDocument();
// 4. Check that the 'Others' group also exists because at least one option did not have optionGroupType
// The default group label is 'Others' (in your code)
const othersGroupLabel = await screen.findByText("Others");
expect(othersGroupLabel).toBeInTheDocument();
// 5. Confirm the correct distribution of options
// For group1 -> "Option 1"
expect(screen.getByText("Option 1")).toBeInTheDocument();
// For group2 -> "Option 3"
expect(screen.getByText("Option 3")).toBeInTheDocument();
// For default "Others" -> "Option 2"
expect(screen.getByText("Option 2")).toBeInTheDocument();
});
});