UNPKG

@octopusdeploy/design-system-components

Version:
200 lines (199 loc) • 9.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("@testing-library/react"); const user_event_1 = __importDefault(require("@testing-library/user-event")); const react_2 = require("react"); const vitest_1 = require("vitest"); const TimePicker_1 = require("../TimePicker"); (0, vitest_1.describe)("TimePicker", () => { const defaultProps = { label: "Select Time", onChange: vitest_1.vi.fn(), }; (0, vitest_1.describe)("dropdown functionality", () => { (0, vitest_1.it)("shows dropdown button", () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); timePicker.shouldShowDropdownButton(); }); (0, vitest_1.it)("opens listbox when caret icon button is clicked", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); timePicker.shouldHaveListbox(); }); (0, vitest_1.it)("does not automatically open listbox when input is focused", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); await timePicker.clickInput(); timePicker.shouldNotHaveListbox(); }); (0, vitest_1.it)("displays correct time options for hourly increment", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); timePicker.shouldHaveTimeOption("12:00 AM"); timePicker.shouldHaveTimeOption("1:00 AM"); timePicker.shouldHaveTimeOption("11:00 PM"); timePicker.shouldNotHaveTimeOption("12:30 AM"); }); (0, vitest_1.it)("displays correct time options for half-hourly increment", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "half-hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); timePicker.shouldHaveTimeOption("12:00 AM"); timePicker.shouldHaveTimeOption("12:30 AM"); timePicker.shouldHaveTimeOption("1:00 AM"); timePicker.shouldHaveTimeOption("11:30 PM"); }); (0, vitest_1.it)("selects time when option is clicked", async () => { const handleChange = vitest_1.vi.fn(); const timePicker = renderTimePicker({ ...defaultProps, onChange: handleChange, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); timePicker.shouldHaveTimeOption("2:00 PM"); await timePicker.selectTimeOption("2:00 PM"); timePicker.shouldHaveCalledOnChangeWith("14:00"); await timePicker.waitForListboxToBeClosed(); }); (0, vitest_1.it)("allows typing in the input field", async () => { const handleChange = vitest_1.vi.fn(); const timePicker = renderTimePicker({ ...defaultProps, onChange: handleChange, increment: "hourly" }); await timePicker.typeInInput("14:00"); timePicker.shouldHaveValue("14:00"); timePicker.shouldHaveCalledOnChange(); }); (0, vitest_1.it)("has proper ARIA attributes on dropdown button", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); const dropdownButton = timePicker.getDropdownButton(); (0, vitest_1.expect)(dropdownButton).toHaveAttribute("aria-expanded", "false"); (0, vitest_1.expect)(dropdownButton).toHaveAttribute("aria-haspopup", "listbox"); (0, vitest_1.expect)(dropdownButton).not.toHaveAttribute("aria-controls"); await timePicker.clickDropdown(); await timePicker.waitForListbox(); (0, vitest_1.expect)(dropdownButton).toHaveAttribute("aria-expanded", "true"); (0, vitest_1.expect)(dropdownButton).toHaveAttribute("aria-controls"); }); (0, vitest_1.it)("has proper ARIA attributes on listbox and options", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); const listbox = timePicker.getListbox(); (0, vitest_1.expect)(listbox).toHaveAttribute("role", "listbox"); const options = timePicker.getAllOptions(); options.forEach((option) => { (0, vitest_1.expect)(option).toHaveAttribute("id"); (0, vitest_1.expect)(option).toHaveAttribute("role", "option"); (0, vitest_1.expect)(option).toHaveAttribute("aria-selected"); }); }); }); (0, vitest_1.describe)("keyboard navigation", () => { (0, vitest_1.it)("navigates options with arrow keys and selects with Enter", async () => { const handleChange = vitest_1.vi.fn(); const timePicker = renderTimePicker({ ...defaultProps, onChange: handleChange, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); await timePicker.pressArrowDown(); await timePicker.pressArrowDown(); await timePicker.pressArrowUp(); await timePicker.pressEnter(); timePicker.shouldHaveCalledOnChangeWith("01:00"); }); (0, vitest_1.it)("closes listbox with Escape key", async () => { const timePicker = renderTimePicker({ ...defaultProps, increment: "hourly" }); await timePicker.clickDropdown(); await timePicker.waitForListbox(); await timePicker.pressEscape(); await timePicker.waitForListboxToBeClosed(); timePicker.shouldNotHaveListbox(); }); }); }); function renderTimePicker(options) { const onChange = vitest_1.vi.fn(); (0, react_1.render)((0, jsx_runtime_1.jsx)(ControlledTimePicker, { ...options, onChange: onChange })); return getTimePickerInteractions(options.label || "Select Time", onChange); } // Keeps the field genuinely controlled (mirroring how a real consumer feeds onChange back into value), so // typing accumulates correctly across keystrokes instead of resetting to the initial prop on every render. function ControlledTimePicker({ onChange, value: initialValue, ...options }) { const [value, setValue] = (0, react_2.useState)(initialValue); return ((0, jsx_runtime_1.jsx)(TimePicker_1.TimePicker, { ...options, value: value, onChange: (newValue) => { setValue(newValue); onChange(newValue); } })); } function getTimePickerInteractions(label, onChange) { const user = user_event_1.default.setup(); const getInput = () => react_1.screen.getByLabelText(new RegExp(label)); const getDropdownButton = () => react_1.screen.getByRole("button", { name: "Toggle time options" }); const getListbox = () => react_1.screen.getByRole("listbox"); const queryListbox = () => react_1.screen.queryByRole("listbox"); const getAllOptions = () => react_1.screen.getAllByRole("option"); return { typeInInput: async (text) => { await user.type(getInput(), text); }, clickInput: async () => { await user.click(getInput()); }, clickDropdown: async () => { await user.click(getDropdownButton()); }, waitForListbox: async () => { await (0, react_1.waitFor)(() => { (0, vitest_1.expect)(getListbox()).toBeInTheDocument(); }); }, waitForListboxToBeClosed: async () => { await (0, react_1.waitFor)(() => { (0, vitest_1.expect)(queryListbox()).not.toBeInTheDocument(); }); }, selectTimeOption: async (time) => { await user.click(react_1.screen.getByText(time)); }, getDropdownButton: () => getDropdownButton(), getListbox: () => getListbox(), getAllOptions: () => getAllOptions(), pressArrowDown: async () => { await user.keyboard("{ArrowDown}"); }, pressArrowUp: async () => { await user.keyboard("{ArrowUp}"); }, pressEnter: async () => { await user.keyboard("{Enter}"); }, pressEscape: async () => { await user.keyboard("{Escape}"); }, shouldHaveTimeOption: (time) => { (0, vitest_1.expect)(react_1.screen.getByText(time)).toBeInTheDocument(); }, shouldNotHaveTimeOption: (time) => { (0, vitest_1.expect)(react_1.screen.queryByText(time)).not.toBeInTheDocument(); }, shouldHaveValue: (value) => { (0, vitest_1.expect)(getInput()).toHaveValue(value); }, shouldShowDropdownButton: () => { (0, vitest_1.expect)(getDropdownButton()).toBeInTheDocument(); }, shouldHaveListbox: () => { (0, vitest_1.expect)(getListbox()).toBeInTheDocument(); }, shouldNotHaveListbox: () => { (0, vitest_1.expect)(queryListbox()).not.toBeInTheDocument(); }, shouldHaveCalledOnChange: () => { (0, vitest_1.expect)(onChange).toHaveBeenCalled(); }, shouldHaveCalledOnChangeWith: (value) => { (0, vitest_1.expect)(onChange).toHaveBeenCalledWith(value); }, }; }