/*
* Copyright 2021-2024 Avaiga Private Limited
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
import React from "react";
import { render } from "@testing-library/react";
import "@testing-library/jest-dom";
import userEvent from "@testing-library/user-event";
import Selector from "./Selector";
import { LoV } from "./lovUtils";
import { INITIAL_STATE, TaipyState } from "../../context/taipyReducers";
import { TaipyContext } from "../../context/taipyContext";
import { stringIcon } from "../../utils/icon";
const lov: LoV = [
["id1", "Item 1"],
["id2", "Item 2"],
["id3", "Item 3"],
["id4", "Item 4"],
];
const defLov = '[["id10","Default Item"]]';
const imageItem: [string, stringIcon] = ["ii1", { path: "/img/fred.png", text: "Image" }];
describe("Selector Component", () => {
it("renders", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.tagName).toBe("SPAN");
});
it("uses the class", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
"taipy-selector"
);
});
it("can display an image", async () => {
const lovWithImage = [...lov, imageItem];
const { getByAltText } = render();
const elt = getByAltText("Image");
expect(elt.tagName).toBe("IMG");
});
it("displays the right info for lov vs defaultLov", async () => {
const { getByText, queryAllByText } = render();
getByText("Item 1");
expect(queryAllByText("Default Item")).toHaveLength(0);
});
it("displays the default LoV", async () => {
const { getByText } = render();
getByText("Default Item");
});
it("shows a selection at start", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.parentElement).toHaveClass("Mui-selected");
});
it("shows a selection at start through value", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.parentElement).not.toHaveClass("Mui-selected");
const elt2 = getByText("Item 2");
expect(elt2.parentElement?.parentElement).toHaveClass("Mui-selected");
});
it("is disabled", async () => {
const { getAllByRole } = render();
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).toHaveClass("Mui-disabled"));
});
it("is enabled by default", async () => {
const { getAllByRole } = render();
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).not.toHaveClass("Mui-disabled"));
});
it("is enabled by active", async () => {
const { getAllByRole } = render();
const elts = getAllByRole("button");
elts.forEach((elt) => expect(elt).not.toHaveClass("Mui-disabled"));
});
it("dispatch a well formed message", async () => {
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByText } = render(
);
const elt = getByText("Item 1");
await userEvent.click(elt);
expect(dispatch).toHaveBeenCalledWith({
name: "varname",
payload: { value: "id1", relvar: "lov" },
propagate: true,
type: "SEND_UPDATE_ACTION",
});
});
//multiple
describe("Selector Component with multiple", () => {
it("displays checkboxes when multiple", async () => {
const { queryAllByRole } = render();
expect(queryAllByRole("checkbox")).toHaveLength(4);
});
it("does not display checkboxes when not multiple", async () => {
const { queryAllByRole } = render();
expect(queryAllByRole("checkbox")).toHaveLength(0);
});
it("selects 2 items", async () => {
const { queryAllByRole } = render();
const cks = queryAllByRole("checkbox");
const ccks = cks.filter((ck) => (ck as HTMLInputElement).checked);
expect(ccks).toHaveLength(2);
});
it("selects the checkbox when the line is selected", async () => {
const { getByText } = render();
const elt = getByText("Item 2");
const ck = elt.parentElement?.parentElement?.querySelector('input[type="checkbox"]') as HTMLInputElement;
expect(ck).toBeDefined();
expect(ck.checked).toBe(true);
});
it("dispatch a well formed message for multiple", async () => {
const user = userEvent.setup();
const dispatch = jest.fn();
const state: TaipyState = INITIAL_STATE;
const { getByText } = render(
);
const elt = getByText("Item 1");
await user.click(elt);
const elt2 = getByText("Item 2");
await user.click(elt2);
const elt3 = getByText("Item 3");
await user.click(elt3);
await user.click(elt2);
expect(dispatch).toHaveBeenLastCalledWith({
name: "varname",
payload: { value: ["id1", "id3"] },
propagate: true,
type: "SEND_UPDATE_ACTION",
});
});
});
describe("Selector Component with filter", () => {
//filter
it("displays an input when filter", async () => {
const { getByPlaceholderText } = render();
getByPlaceholderText("Search field");
});
it("does not display an input when filter is off", async () => {
const { queryAllByPlaceholderText } = render();
expect(queryAllByPlaceholderText("Search field")).toHaveLength(0);
});
it("filters items by name", async () => {
const { getByPlaceholderText, queryAllByText } = render();
expect(queryAllByText(/Item /)).toHaveLength(4);
const search = getByPlaceholderText("Search field");
await userEvent.type(search, "m 3");
expect(queryAllByText(/Item /)).toHaveLength(1);
await userEvent.clear(search);
expect(queryAllByText(/Item /)).toHaveLength(4);
});
});
describe("Selector Component with dropdown", () => {
//dropdown
it("displays as an empty control with arrow", async () => {
const { getByTestId } = render();
getByTestId("ArrowDropDownIcon");
});
it("displays as an simple input with default value", async () => {
const { getByText, getByTestId, queryAllByTestId } = render();
getByText("Item 1");
expect(queryAllByTestId("CancelIcon")).toHaveLength(0);
getByTestId("ArrowDropDownIcon");
});
it("displays a delete icon when multiple", async () => {
const { getByTestId } = render();
getByTestId("CancelIcon");
});
it("is disabled", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement).toHaveClass("Mui-disabled");
});
it("is enabled by default", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement).not.toHaveClass("Mui-disabled");
});
it("is enabled by active", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement).not.toHaveClass("Mui-disabled");
});
it("opens a dropdown on click", async () => {
const { getByText, getByRole, queryAllByRole } = render();
const butElt = getByRole("combobox");
expect(butElt).toBeInTheDocument()
await userEvent.click(butElt);
getByRole("listbox");
const elt = getByText("Item 2");
await userEvent.click(elt);
expect(queryAllByRole("listbox")).toHaveLength(0);
});
});
describe("Selector Component radio mode", () => {
//dropdown
it("displays a list of unselected radios", async () => {
const { getByText, getByRole } = render();
getByText("Item 1");
getByRole("radiogroup");
expect(document.querySelector("div.taipy-selector-radio-group")).not.toBeNull();
});
it("displays a list of radios with one selected", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
});
it("selects on click", async () => {
const { getByText, getByRole, queryAllByRole } = render();
const elt = getByText("Item 2");
expect(elt.parentElement?.querySelector("span.Mui-checked")).toBeNull();
await userEvent.click(elt);
expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
});
});
describe("Selector Component check mode", () => {
//dropdown
it("displays a list of unselected checks", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.parentElement).toHaveClass("taipy-selector-check-group");
expect(document.querySelector("span.MuiCheckbox-root")).not.toBeNull();
});
it("displays a list of checks with one selected", async () => {
const { getByText } = render();
const elt = getByText("Item 1");
expect(elt.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
});
it("selects on click", async () => {
const { getByText, getByRole, queryAllByRole } = render();
const elt1 = getByText("Item 1");
expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
const elt2 = getByText("Item 2");
expect(elt2.parentElement?.querySelector("span.Mui-checked")).toBeNull();
await userEvent.click(elt2);
expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
const elt3 = getByText("Item 3");
expect(elt3.parentElement?.querySelector("span.Mui-checked")).toBeNull();
await userEvent.click(elt3);
expect(elt1.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
expect(elt3.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
await userEvent.click(elt1);
expect(elt1.parentElement?.querySelector("span.Mui-checked")).toBeNull();
expect(elt2.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
expect(elt3.parentElement?.querySelector("span.Mui-checked")).not.toBeNull();
});
});
});