import React from "react"; import { fireEvent, render, waitFor } from "@testing-library/react-native"; import { FormProvider, useForm } from "react-hook-form"; import { Keyboard } from "react-native"; import { InputTime } from "./InputTime"; import * as atlantisContext from "../AtlantisContext/AtlantisContext"; import { Button } from "../Button"; const keyboardDismissSpy = jest.spyOn(Keyboard, "dismiss"); afterEach(() => { jest.spyOn(atlantisContext, "useAtlantisContext").mockRestore(); }); describe("Visuals", () => { const placeholder = "Start time"; const expectedTime = "11:00 AM"; const value = new Date(2022, 2, 2, 11, 0); const handleChange = jest.fn(); const setup = (showIcon = true) => render( , ); it("should show a timer prefix icon", () => { const screen = setup(); const timerIcon = screen.getByTestId("timer"); expect(timerIcon).toBeDefined(); expect(timerIcon.type).toBe("RNSVGSvgView"); }); it("should not show a timer icon if showIcon is false", () => { const screen = setup(false); const timerIcon = screen.queryByTestId("timer"); expect(timerIcon).toBeNull(); }); it("should show a formatted time", () => { const screen = setup(); expect( screen.getByText(expectedTime, { includeHiddenElements: true }), ).toBeDefined(); }); it("should be clearable when there's a value", () => { const screen = setup(); const clearAction = screen.getByLabelText("Clear input"); expect(clearAction).toBeDefined(); fireEvent.press(clearAction); expect(handleChange).toHaveBeenCalledWith(undefined); }); }); describe("String value", () => { const handleChange = jest.fn(); it("should show a formatted time", () => { const expectedTime = "11:00 AM"; const value = new Date(2022, 2, 2, 11, 0).toISOString(); const screen = render(); expect( screen.getByText(expectedTime, { includeHiddenElements: true }), ).toBeDefined(); }); }); describe("With emptyValueLabel", () => { const handleChange = jest.fn(); it("should show the emptyValueLabel when there's no value", () => { const label = "Unscheduled"; const screen = render(); expect( screen.getByText(label, { includeHiddenElements: true }), ).toBeDefined(); expect( screen.queryByLabelText("Clear input", { includeHiddenElements: true }), ).toBeNull(); }); it("should not show the emptyValueLabel when there's a value", () => { const label = "Unscheduled"; const screen = render( , ); expect(screen.queryByText(label)).toBeNull(); expect(screen.getByLabelText("Clear input")).toBeDefined(); }); }); // eslint-disable-next-line max-statements describe("Time picker", () => { const placeholder = "Tap me"; const handleChange = jest.fn(); const getType = jest.fn().mockReturnValue(undefined); function renderTimePicker(value?: Date) { const screen = render( , ); fireEvent.press(screen.getByLabelText(placeholder)); expect(screen.getByTestId("inputTime-Picker")).toBeDefined(); return screen; } it("should not show a time picker", () => { const screen = render(); expect(screen.queryByTestId("inputTime-Picker")).toBeNull(); }); it("should fire the onChange with the current value after canceling a time selection", () => { const value = new Date(); const screen = renderTimePicker(value); fireEvent.press(screen.getByLabelText("Cancel")); expect(handleChange).toHaveBeenCalledWith(value); }); it("should fire the onChange after confirming a time selection", () => { const screen = renderTimePicker(); fireEvent.press(screen.getByLabelText("Confirm")); expect(handleChange).toHaveBeenCalledWith(expect.any(Date)); }); it("should dismiss the keyboard when the time picker is opened", () => { renderTimePicker(); expect(keyboardDismissSpy).toHaveBeenCalled(); }); it("should be a time picker", () => { const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.mode).toBe("time"); }); describe("Locale", () => { it("should be set to 12 hours", () => { const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.locale).toBe("en_US"); }); it("should be set to 24 hours", () => { jest.spyOn(atlantisContext, "useAtlantisContext").mockReturnValue({ ...atlantisContext.atlantisContextDefaultValues, timeZone: "UTC", timeFormat: "HH:mm", }); const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.locale).toBe("en_GB"); }); }); it("should set the minute interval to 5 by default", () => { const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.minuteInterval).toBe(5); }); it("should set the minute interval to 5 when the type is scheduling", () => { getType.mockReturnValueOnce("scheduling"); const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.minuteInterval).toBe(5); }); it("should set the minute interval to 1 when the type is granular", () => { getType.mockReturnValueOnce("granular"); const screen = renderTimePicker(); expect(screen.getByTestId("inputTime-Picker").props.minuteInterval).toBe(1); }); }); const mockOnSubmit = jest.fn(); const saveButtonText = "Submit"; const requiredError = "This is required"; function SimpleFormWithProvider({ children, defaultValues, }: { readonly children: React.ReactNode; readonly defaultValues?: Record; }) { const formMethods = useForm({ reValidateMode: "onChange", defaultValues, mode: "onTouched", }); return ( {children}