@octopusdeploy/design-system-components
Version:
The design systems component library.
200 lines (199 loc) • 9.9 kB
JavaScript
;
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);
},
};
}