From 759e1003978fb197eca6a4d69d15495b64851c71 Mon Sep 17 00:00:00 2001 From: Anurag Hazra Date: Mon, 12 Oct 2020 15:42:06 +0530 Subject: [PATCH] test: added test for timepicker (#86) --- src/timepicker/TimePickerColumn.ts | 4 +- src/timepicker/TimePickerColumnState.ts | 10 +- src/timepicker/TimePickerState.ts | 6 +- src/timepicker/__keys.ts | 2 +- src/timepicker/__tests__/TimePicker.test.tsx | 148 +++++++++++++++++++ 5 files changed, 159 insertions(+), 11 deletions(-) create mode 100644 src/timepicker/__tests__/TimePicker.test.tsx diff --git a/src/timepicker/TimePickerColumn.ts b/src/timepicker/TimePickerColumn.ts index 9c5d601c8..7d1837db3 100644 --- a/src/timepicker/TimePickerColumn.ts +++ b/src/timepicker/TimePickerColumn.ts @@ -9,7 +9,7 @@ import { TIME_PICKER_COLUMN_KEYS } from "./__keys"; import { TimePickerColumnStateReturn } from "./TimePickerColumnState"; export type TimePickerColumnOptions = CompositeOptions & - Pick; + Pick; export type TimePickerColumnHTMLProps = CompositeHTMLProps; @@ -27,7 +27,7 @@ export const useTimePickerColumn = createHook< useProps(options, htmlProps) { return { role: "listbox", - "aria-label": options.type, + "aria-label": options.columnType, ...htmlProps, }; }, diff --git a/src/timepicker/TimePickerColumnState.ts b/src/timepicker/TimePickerColumnState.ts index ba03bf919..04198927f 100644 --- a/src/timepicker/TimePickerColumnState.ts +++ b/src/timepicker/TimePickerColumnState.ts @@ -8,7 +8,7 @@ export type ColumnType = "hour" | "minute" | "meridian"; export interface TimePickerColumnInitialState extends ValueBase { visible?: boolean; - type?: ColumnType; + columnType?: ColumnType; } export const useTimePickerColumnState = ( @@ -19,7 +19,7 @@ export const useTimePickerColumnState = ( defaultValue = new Date(), onChange, visible, - type = "hour", + columnType = "hour", } = props; const [date, setDate] = useControllableState({ @@ -28,7 +28,7 @@ export const useTimePickerColumnState = ( onChange, }); - const selected = getSelectedValueFromDate(date, type); + const selected = getSelectedValueFromDate(date, columnType); const composite = useCompositeState({ loop: true, @@ -37,10 +37,10 @@ export const useTimePickerColumnState = ( }); const setSelected = (value: number) => { - setDate(getSelectedDateFromValue(value, date, type)); + setDate(getSelectedDateFromValue(value, date, columnType)); }; - return { selected, setSelected, visible, type, ...composite }; + return { selected, setSelected, visible, columnType, ...composite }; }; export type TimePickerColumnStateReturn = ReturnType< diff --git a/src/timepicker/TimePickerState.ts b/src/timepicker/TimePickerState.ts index 00191d5c5..5101bd7ea 100644 --- a/src/timepicker/TimePickerState.ts +++ b/src/timepicker/TimePickerState.ts @@ -55,21 +55,21 @@ export const useTimePickerState = (props: TimePickerStateProps = {}) => { }; const hourState = useTimePickerColumnState({ - type: "hour", + columnType: "hour", value: time, onChange: setTimeProp, visible: popover.visible, }); const minuteState = useTimePickerColumnState({ - type: "minute", + columnType: "minute", value: time, onChange: setTimeProp, visible: popover.visible, }); const meridiesState = useTimePickerColumnState({ - type: "meridian", + columnType: "meridian", value: time, onChange: setTimeProp, visible: popover.visible, diff --git a/src/timepicker/__keys.ts b/src/timepicker/__keys.ts index 99ae6f4c4..99b1eb964 100644 --- a/src/timepicker/__keys.ts +++ b/src/timepicker/__keys.ts @@ -37,7 +37,7 @@ const TIME_PICKER_COLUMN_STATE_KEYS = [ "selected", "setSelected", "visible", - "type", + "columnType", ] as const; const TIME_PICKER_STATE_KEYS = [ "fieldValue", diff --git a/src/timepicker/__tests__/TimePicker.test.tsx b/src/timepicker/__tests__/TimePicker.test.tsx new file mode 100644 index 000000000..2fcad837e --- /dev/null +++ b/src/timepicker/__tests__/TimePicker.test.tsx @@ -0,0 +1,148 @@ +import * as React from "react"; +import { axe, render, press } from "reakit-test-utils"; +import { + TimePicker, + TimePickerColumn, + TimePickerTrigger, + TimePickerSegment, + TimePickerContent, + useTimePickerState, + TimePickerStateProps, + TimePickerColumnValue, + TimePickerSegmentField, +} from ".."; + +beforeAll(() => { + // https://github.com/jsdom/jsdom/issues/1695 + Element.prototype.scrollIntoView = jest.fn(); + + // ChakraUI's focus() uses requestAnimationFrame so we need to mock it + jest + .spyOn(window, "requestAnimationFrame") + .mockImplementation((cb: any) => cb()); +}); + +afterAll(() => { + (window.requestAnimationFrame as any).mockRestore(); +}); + +const TimePickerComp: React.FC = props => { + const state = useTimePickerState(props); + + return ( + <> + + + {state.segments.map((segment, i) => ( + + ))} + + open + + + + {state.hours.map(n => { + return ( + + {n} + + ); + })} + + + {state.minutes.map((n, i) => { + return ( + + {n} + + ); + })} + + + {state.meridies.map((n, i) => { + return ( + + {n} + + ); + })} + + + + ); +}; + +describe("TimePicker", () => { + it("should render correctly", () => { + const { getByTestId: testId } = render( + , + ); + + expect(testId("current-time")).toHaveTextContent("12:45 PM"); + }); + + it("should open and change time value", () => { + const { getByTestId: testId } = render( + , + ); + + expect(testId("timepicker-content")).not.toBeVisible(); + press.Tab(); + + press.ArrowDown(null, { altKey: true }); + + expect(testId("timepicker-content")).toBeVisible(); + + expect(document.activeElement).toHaveTextContent("12"); + press.ArrowDown(); + expect(document.activeElement).toHaveTextContent("1"); + + press.Enter(); + expect(testId("timepicker-content")).not.toBeVisible(); + expect(testId("current-time")).toHaveTextContent("1:45 PM"); + }); + + it("should be able to navigate with keyboard", () => { + const { getByTestId: testId } = render( + , + ); + + expect(testId("timepicker-content")).not.toBeVisible(); + press.Tab(); + + press.ArrowDown(null, { altKey: true }); + + expect(testId("timepicker-content")).toBeVisible(); + + expect(document.activeElement).toHaveTextContent("12"); + press.ArrowDown(); + press.ArrowDown(); + press.ArrowDown(); + expect(document.activeElement).toHaveTextContent("3"); + + // Go to minute column + press.ArrowRight(); + expect(document.activeElement).toHaveTextContent("45"); + press.ArrowUp(); + press.ArrowUp(); + press.ArrowUp(); + expect(document.activeElement).toHaveTextContent("42"); + + // Go to meridian column + press.ArrowRight(); + expect(document.activeElement).toHaveTextContent("PM"); + press.ArrowUp(); + expect(document.activeElement).toHaveTextContent("AM"); + + press.Enter(); + expect(testId("timepicker-content")).not.toBeVisible(); + expect(testId("current-time")).toHaveTextContent("12:45 AM"); + }); + + test("TimePicker renders with no a11y violations", async () => { + const { container } = render(); + const results = await axe(container); + + expect(results).toHaveNoViolations(); + }); +});