123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- * 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 userEvent from "@testing-library/user-event";
- import "@testing-library/jest-dom";
- import { LocalizationProvider } from "@mui/x-date-pickers";
- import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFnsV3";
- import DateRange from "./DateRange";
- import { TaipyContext } from "../../context/taipyContext";
- import { TaipyState, INITIAL_STATE } from "../../context/taipyReducers";
- import { getClientServerTimeZoneOffset } from "../../utils";
- jest.mock("../../utils", () => {
- const originalModule = jest.requireActual("../../utils");
- //Mock getClientServerTimeZoneOffset
- return {
- __esModule: true,
- ...originalModule,
- getClientServerTimeZoneOffset: () => 0,
- };
- });
- beforeEach(() => {
- // add window.matchMedia
- // this is necessary for the date picker to be rendered in desktop mode.
- // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior
- Object.defineProperty(window, "matchMedia", {
- writable: true,
- value: (query: string): MediaQueryList => ({
- media: query,
- // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device
- matches: query === "(pointer: fine)",
- onchange: () => {},
- addEventListener: () => {},
- removeEventListener: () => {},
- addListener: () => {},
- removeListener: () => {},
- dispatchEvent: () => false,
- }),
- });
- });
- afterEach(() => {
- // @ts-ignore
- delete window.matchMedia;
- });
- const curDate = new Date();
- curDate.setHours(1, 1, 1, 1);
- const curDateStr = curDate.toISOString();
- const nextDate = new Date(curDate);
- nextDate.setDate(nextDate.getDate() + 1);
- const nextDateStr = nextDate.toISOString();
- const curDates = [curDateStr, nextDateStr];
- const cleanText = (val: string) => val.replace(/\u200e|\u2066|\u2067|\u2068|\u2069/g, "");
- const defaultDates = '["2001-01-01T00:00:01.001Z","2001-01-31T00:00:01.001Z"]';
- describe("DateRange Component", () => {
- it("renders", async () => {
- const { getAllByTestId } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} />
- </LocalizationProvider>
- );
- const elts = getAllByTestId("CalendarIcon");
- expect(elts).toHaveLength(2);
- expect(elts[0].parentElement?.tagName).toBe("BUTTON");
- });
- it("displays the right info for string", async () => {
- const { getAllByTestId } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} defaultDates={defaultDates} className="taipy-date-2" />
- </LocalizationProvider>
- );
- const elts = getAllByTestId("CalendarIcon");
- expect(elts).toHaveLength(2);
- expect(elts[0].parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-date-2-picker",
- "taipy-date-2-picker-start"
- );
- expect(elts[0].parentElement?.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-date-2"
- );
- expect(elts[1].parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-date-2-picker",
- "taipy-date-2-picker-end"
- );
- expect(elts[1].parentElement?.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-date-2"
- );
- });
- it("displays the default value", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates={defaultDates}
- dates={undefined as unknown as string[]}
- className="taipy-date-range"
- />
- </LocalizationProvider>
- );
- const input = document.querySelector(".taipy-date-range-picker-start input") as HTMLInputElement;
- expect(input).toBeInTheDocument();
- expect(cleanText(input?.value || "")).toEqual("01/01/2001");
- const input2 = document.querySelector(".taipy-date-range-picker-end input") as HTMLInputElement;
- expect(input2).toBeInTheDocument();
- expect(cleanText(input2?.value || "")).toEqual("01/31/2001");
- });
- it("displays the default value with format", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates={defaultDates}
- dates={undefined as unknown as string[]}
- className="taipy-date-range"
- format="dd-MM-yyyy"
- />
- </LocalizationProvider>
- );
- const input = document.querySelector(".taipy-date-range-picker-start input") as HTMLInputElement;
- expect(input).toBeInTheDocument();
- expect(cleanText(input?.value || "")).toEqual("01-01-2001");
- const input2 = document.querySelector(".taipy-date-range-picker-end input") as HTMLInputElement;
- expect(input2).toBeInTheDocument();
- expect(cleanText(input2?.value || "")).toEqual("31-01-2001");
- });
- it("shows labels", async () => {
- const { getByLabelText } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates={defaultDates}
- dates={undefined as unknown as string[]}
- className="taipy-date-range"
- labelStart="start"
- labelEnd="end"
- />
- </LocalizationProvider>
- );
- const startInput = getByLabelText("start") as HTMLInputElement;
- expect(startInput.value).toBe("01/01/2001");
- const endInput = getByLabelText("end") as HTMLInputElement;
- expect(endInput.value).toBe("01/31/2001");
- });
- it("displays with width=70%", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} width="70%" />
- </LocalizationProvider>
- );
- const elt = document.querySelector(".MuiStack-root");
- expect(elt).toHaveStyle("width: 70%");
- });
- it("displays with width=500", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} width={500} />
- </LocalizationProvider>
- );
- const elt = document.querySelector(".MuiStack-root");
- expect(elt).toHaveStyle("width: 500px");
- });
- it("is disabled", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} active={false} className="taipy-date-range" />
- </LocalizationProvider>
- );
- const input = document.querySelector(".taipy-date-range-picker-start input");
- expect(input).toBeInTheDocument();
- expect(input).toBeDisabled();
- const input2 = document.querySelector(".taipy-date-range-picker-end input");
- expect(input2).toBeInTheDocument();
- expect(input2).toBeDisabled();
- });
- it("is enabled by default", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} />
- </LocalizationProvider>
- );
- const input = document.querySelector("input");
- expect(input).toBeInTheDocument();
- expect(input).not.toBeDisabled();
- });
- it("is enabled by active", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} active={true} />
- </LocalizationProvider>
- );
- const input = document.querySelector("input");
- expect(input).toBeInTheDocument();
- expect(input).not.toBeDisabled();
- });
- it("dispatch a well formed message", async () => {
- const dispatch = jest.fn();
- const state: TaipyState = INITIAL_STATE;
- render(
- <TaipyContext.Provider value={{ state, dispatch }}>
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} className="taipy-date-range" />
- </LocalizationProvider>
- </TaipyContext.Provider>
- );
- const input = document.querySelector(".taipy-date-range-picker-start input");
- expect(input).toBeInTheDocument();
- const input2 = document.querySelector(".taipy-date-range-picker-end input");
- expect(input2).toBeInTheDocument();
- if (input && input2) {
- // await userEvent.clear(input);
- await userEvent.type(input, "{ArrowLeft}{ArrowLeft}{ArrowLeft}01012001", { delay: 1 });
- // await userEvent.clear(input2);
- await userEvent.type(input2, "{ArrowLeft}{ArrowLeft}{ArrowLeft}01312001", { delay: 1 });
- expect(dispatch).toHaveBeenLastCalledWith({
- name: "",
- payload: { value: ["Mon Jan 01 2001", "Wed Jan 31 2001"] },
- propagate: true,
- type: "SEND_UPDATE_ACTION",
- });
- }
- });
- });
- describe("DateRange with time Component", () => {
- it("renders", async () => {
- const { getAllByTestId } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} />
- </LocalizationProvider>
- );
- const elts = getAllByTestId("CalendarIcon");
- expect(elts).toHaveLength(2);
- expect(elts[0].parentElement?.tagName).toBe("BUTTON");
- });
- it("displays the right info for string", async () => {
- const { getAllByTestId } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} className="taipy-time" />
- </LocalizationProvider>
- );
- const elts = getAllByTestId("CalendarIcon");
- expect(elts).toHaveLength(2);
- expect(elts[0].parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-time-picker",
- "taipy-time-picker-start"
- );
- expect(elts[0].parentElement?.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-time"
- );
- expect(elts[1].parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-time-picker",
- "taipy-time-picker-end"
- );
- expect(elts[1].parentElement?.parentElement?.parentElement?.parentElement?.parentElement).toHaveClass(
- "taipy-time"
- );
- });
- it("displays the default value", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates='["2001-01-01T00:00:01.001Z","2001-01-31T00:00:01.001Z"]'
- withTime={true}
- dates={undefined as unknown as string[]}
- className="tp-dt"
- />
- </LocalizationProvider>
- );
- const input = document.querySelector(".tp-dt-picker-start input") as HTMLInputElement;
- expect(input).toBeInTheDocument();
- expect(cleanText(input?.value || "").toLocaleLowerCase()).toEqual("01/01/2001 12:00 am");
- const input2 = document.querySelector(".tp-dt-picker-end input") as HTMLInputElement;
- expect(input2).toBeInTheDocument();
- expect(cleanText(input2?.value || "").toLocaleLowerCase()).toEqual("01/31/2001 12:00 am");
- });
- it("displays the default value with format", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates='["2001-01-01T00:10:01.001Z","2001-01-31T00:11:01.001Z"]'
- withTime={true}
- dates={undefined as unknown as string[]}
- className="tp-dt"
- format="dd-MM-yyyy mm"
- />
- </LocalizationProvider>
- );
- const input = document.querySelector(".tp-dt-picker-start input") as HTMLInputElement;
- expect(input).toBeInTheDocument();
- expect(cleanText(input?.value || "").toLocaleLowerCase()).toEqual("01-01-2001 10");
- const input2 = document.querySelector(".tp-dt-picker-end input") as HTMLInputElement;
- expect(input2).toBeInTheDocument();
- expect(cleanText(input2?.value || "").toLocaleLowerCase()).toEqual("31-01-2001 11");
- });
- it("shows labels", async () => {
- const { getByLabelText } = render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange
- defaultDates='["2001-01-01T00:00:01.001Z","2001-01-31T00:00:01.001Z"]'
- dates={undefined as unknown as string[]}
- withTime={true}
- className="taipy-date-range"
- labelStart="start"
- labelEnd="end"
- />
- </LocalizationProvider>
- );
- const startInput = getByLabelText("start") as HTMLInputElement;
- expect(startInput.value.toLocaleLowerCase()).toBe("01/01/2001 12:00 am");
- const endInput = getByLabelText("end") as HTMLInputElement;
- expect(endInput.value.toLocaleLowerCase()).toBe("01/31/2001 12:00 am");
- });
- it("is disabled", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} active={false} className="tp-dt" />
- </LocalizationProvider>
- );
- const input = document.querySelector(".tp-dt-picker-start input");
- expect(input).toBeInTheDocument();
- expect(input).toBeDisabled();
- const input2 = document.querySelector(".tp-dt-picker-end input");
- expect(input2).toBeInTheDocument();
- expect(input2).toBeDisabled();
- });
- it("is enabled by default", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} />
- </LocalizationProvider>
- );
- const input = document.querySelector("input");
- expect(input).toBeInTheDocument();
- expect(input).not.toBeDisabled();
- });
- it("is enabled by active", async () => {
- render(
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} active={true} />
- </LocalizationProvider>
- );
- const input = document.querySelector("input");
- expect(input).toBeInTheDocument();
- expect(input).not.toBeDisabled();
- });
- it("dispatch a well formed message", async () => {
- const dispatch = jest.fn();
- const state: TaipyState = INITIAL_STATE;
- render(
- <TaipyContext.Provider value={{ state, dispatch }}>
- <LocalizationProvider dateAdapter={AdapterDateFns}>
- <DateRange dates={curDates} withTime={true} updateVarName="varname" className="tp-dt" />
- </LocalizationProvider>
- </TaipyContext.Provider>
- );
- const input = document.querySelector(".tp-dt-picker-start input");
- expect(input).toBeInTheDocument();
- const input2 = document.querySelector(".tp-dt-picker-end input");
- expect(input2).toBeInTheDocument();
- if (input && input2) {
- // await userEvent.clear(input);
- await userEvent.type(
- input,
- "{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}010120010101am",
- { delay: 1 }
- );
- // await userEvent.clear(input2);
- await userEvent.type(
- input2,
- "{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}{ArrowLeft}123120010101am",
- { delay: 1 }
- );
- expect(dispatch).toHaveBeenLastCalledWith({
- name: "varname",
- payload: { value: ["2001-01-01T01:01:00.000Z", "2001-12-31T01:01:00.000Z"] },
- propagate: true,
- type: "SEND_UPDATE_ACTION",
- });
- }
- });
- });
|