UNPKG

@octopusdeploy/design-system-components

Version:
249 lines (248 loc) • 11.7 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 vitest_1 = require("vitest"); const NumberField_1 = require("../NumberField"); (0, vitest_1.describe)("<NumberField />", () => { (0, vitest_1.test)("renders with correct label", () => { const input = renderNumberInput({ label: "Test Label" }); input.shouldHaveLabel("Test Label"); input.shouldBeInDocument(); }); (0, vitest_1.test)("renders with placeholder text", () => { const placeholder = "Enter a number"; const input = renderNumberInput({ label: "Test Label", placeholder }); input.shouldHavePlaceholder(placeholder); }); (0, vitest_1.test)("renders with initial value", () => { const value = 42; const input = renderNumberInput({ label: "Test Label", value }); input.shouldHaveValue(value); }); (0, vitest_1.test)("renders with description", () => { const description = "This is a helpful description"; const input = renderNumberInput({ label: "Test Label", description }); input.shouldHaveDescription(description); }); (0, vitest_1.test)("renders with error state", () => { const validationMessage = "This field is required"; const input = renderNumberInput({ label: "Test Label", validationMessage }); input.shouldHaveError(validationMessage); input.shouldHaveAriaInvalid(true); }); (0, vitest_1.test)("handles empty onChange gracefully", () => { (0, react_1.render)((0, jsx_runtime_1.jsx)(NumberField_1.NumberField, { label: "Test Label", onChange: vitest_1.vi.fn() })); const input = react_1.screen.getByRole("spinbutton"); (0, vitest_1.expect)(input).toBeInTheDocument(); }); (0, vitest_1.test)("calls onChange with parsed number when user types", async () => { const input = renderNumberInput({ label: "Test Label" }); await input.type("123"); input.shouldHaveCalledOnChangeWith(123); }); (0, vitest_1.test)("calls onChange with undefined when input is cleared", async () => { const input = renderNumberInput({ label: "Test Label", value: 123 }); await input.clear(); input.shouldHaveCalledOnChangeWith(undefined); }); (0, vitest_1.test)("parses decimal numbers correctly", async () => { const input = renderNumberInput({ label: "Test Label" }); await input.type("123.45"); input.shouldHaveCalledOnChangeWith(123.45); }); (0, vitest_1.test)("parses negative numbers correctly", async () => { const input = renderNumberInput({ label: "Test Label" }); await input.type("-42"); input.shouldHaveCalledOnChangeWith(-42); }); (0, vitest_1.test)("handles partial invalid input", async () => { const input = renderNumberInput({ label: "Test Label" }); await input.type("12abc"); // parseFloat("12abc") returns 12 input.shouldHaveCalledOnChangeWith(12); }); (0, vitest_1.test)("uses provided min attribute", () => { const input = renderNumberInput({ label: "Test Label", min: 0 }); input.shouldHaveMin(0); }); (0, vitest_1.test)("uses provided max attribute", () => { const input = renderNumberInput({ label: "Test Label", max: 100 }); input.shouldHaveMax(100); }); (0, vitest_1.test)("uses provided step attribute", () => { const input = renderNumberInput({ label: "Test Label", step: 0.5 }); input.shouldHaveStep(0.5); }); (0, vitest_1.test)("uses 'any' as step attribute", () => { const input = renderNumberInput({ label: "Test Label", step: "any" }); input.shouldHaveStep("any"); }); (0, vitest_1.describe)("accessibility attributes", () => { (0, vitest_1.test)("has correct accessibility attributes when error is present", () => { const validationMessage = "Invalid input"; const input = renderNumberInput({ label: "Test Label", validationMessage }); input.shouldHaveAriaInvalid(true); input.shouldHaveAriaDescribedByError(); }); (0, vitest_1.test)("has correct accessibility attributes when description is present", () => { const description = "Help text"; const input = renderNumberInput({ label: "Test Label", description }); input.shouldHaveAriaDescribedByDescription(); }); (0, vitest_1.test)("has correct accessibility attributes when both description and error are present", () => { const description = "Help text"; const validationMessage = "Error message"; const input = renderNumberInput({ label: "Test Label", description, validationMessage }); input.shouldHaveAriaDescribedByBoth(); input.shouldHaveAriaInvalid(true); }); }); }); function renderNumberInput(options) { const onChange = vitest_1.vi.fn(); (0, react_1.render)((0, jsx_runtime_1.jsx)(NumberField_1.NumberField, { ...options, onChange: onChange })); return getNumberInputInteractions(options.label, onChange); } function getNumberInputInteractions(label, onChange) { const input = () => react_1.screen.getByLabelText(label); const user = user_event_1.default.setup(); return { shouldBeInDocument: () => { (0, vitest_1.expect)(input()).toBeInTheDocument(); }, shouldHaveLabel: (labelText) => { (0, vitest_1.expect)(react_1.screen.getByLabelText(labelText)).toBeInTheDocument(); }, shouldHavePlaceholder: (placeholder) => { (0, vitest_1.expect)(input()).toHaveAttribute("placeholder", placeholder); }, shouldHaveValue: (value) => { // HTML input.value is always a string, so convert expected value to string for comparison const inputElement = input(); if (inputElement instanceof HTMLInputElement) { (0, vitest_1.expect)(inputElement.value).toBe(String(value)); } else { (0, vitest_1.expect)(inputElement).toHaveValue(String(value)); } }, shouldHaveDescription: (description) => { (0, vitest_1.expect)(react_1.screen.getByText(description)).toBeInTheDocument(); }, shouldHaveError: (error) => { (0, vitest_1.expect)(react_1.screen.getByText(error)).toBeInTheDocument(); }, shouldBeDisabled: () => { (0, vitest_1.expect)(input()).toBeDisabled(); }, shouldBeReadOnly: () => { (0, vitest_1.expect)(input()).toHaveAttribute("readonly"); }, shouldHaveFocus: () => { (0, vitest_1.expect)(input()).toHaveFocus(); }, shouldHaveRequiredMarker: () => { (0, vitest_1.expect)(react_1.screen.getByText(/\(required\)/)).toBeInTheDocument(); }, shouldHaveOptionalMarker: () => { (0, vitest_1.expect)(react_1.screen.getByText(/\(optional\)/)).toBeInTheDocument(); }, shouldHaveDefaultMarker: () => { (0, vitest_1.expect)(react_1.screen.getByText(/\(Default\)/)).toBeInTheDocument(); }, shouldHaveName: (name) => { (0, vitest_1.expect)(input()).toHaveAttribute("name", name); }, shouldHaveMin: (min) => { (0, vitest_1.expect)(input()).toHaveAttribute("min", min.toString()); }, shouldHaveMax: (max) => { (0, vitest_1.expect)(input()).toHaveAttribute("max", max.toString()); }, shouldHaveStep: (step) => { (0, vitest_1.expect)(input()).toHaveAttribute("step", step.toString()); }, shouldHaveAriaInvalid: (invalid) => { (0, vitest_1.expect)(input()).toHaveAttribute("aria-invalid", invalid.toString()); }, shouldHaveAriaDescribedByError: () => { const inputElement = input(); const ariaDescribedBy = inputElement.getAttribute("aria-describedby"); (0, vitest_1.expect)(ariaDescribedBy).toContain("validation"); }, shouldHaveAriaDescribedByDescription: () => { const inputElement = input(); const ariaDescribedBy = inputElement.getAttribute("aria-describedby"); (0, vitest_1.expect)(ariaDescribedBy).toContain("description"); }, shouldHaveAriaDescribedByBoth: () => { const inputElement = input(); const ariaDescribedBy = inputElement.getAttribute("aria-describedby"); (0, vitest_1.expect)(ariaDescribedBy).toContain("description"); (0, vitest_1.expect)(ariaDescribedBy).toContain("validation"); }, type: async (text) => { await user.clear(input()); await user.type(input(), text); }, clear: async () => { await user.clear(input()); }, attemptToType: async (text) => { await user.type(input(), text); }, shouldHaveCalledOnChangeWith: (value) => { // Check the last call since typing fires onChange multiple times (0, vitest_1.expect)(onChange).toHaveBeenLastCalledWith(value); }, shouldNotHaveCalledOnChange: () => { (0, vitest_1.expect)(onChange).not.toHaveBeenCalled(); }, shouldHaveSuffix: (suffixText) => { const suffixElement = react_1.screen.getByText(suffixText); (0, vitest_1.expect)(suffixElement).toBeInTheDocument(); }, shouldHaveSuffixElement: () => { const spinbutton = react_1.screen.getByRole("spinbutton"); (0, vitest_1.expect)(spinbutton).toBeInTheDocument(); }, shouldHaveSuffixButton: () => { const suffixButton = react_1.screen.queryByRole("button"); (0, vitest_1.expect)(suffixButton).toBeInTheDocument(); }, shouldNotHaveSuffix: () => { const suffixButton = react_1.screen.queryByRole("button"); (0, vitest_1.expect)(suffixButton).not.toBeInTheDocument(); const input = react_1.screen.getByRole("spinbutton"); (0, vitest_1.expect)(input).not.toHaveClass("inputStylesWithSuffix"); }, clickSuffixButton: async () => { const suffixButton = react_1.screen.getByRole("button"); await user.click(suffixButton); }, shouldHaveCalledSuffixClick: (clickHandler) => { (0, vitest_1.expect)(clickHandler).toHaveBeenCalled(); }, shouldHavePrefix: (prefixText) => { const prefixElement = react_1.screen.getByText(prefixText); (0, vitest_1.expect)(prefixElement).toBeInTheDocument(); }, shouldHavePrefixElement: () => { const spinbutton = react_1.screen.getByRole("spinbutton"); (0, vitest_1.expect)(spinbutton).toBeInTheDocument(); }, shouldNotHavePrefix: () => { const input = react_1.screen.getByRole("spinbutton"); (0, vitest_1.expect)(input).not.toHaveClass("inputStylesWithPrefix"); }, shouldHavePrefixWithTitle: (title) => { const prefixElement = react_1.screen.getByTitle(title); (0, vitest_1.expect)(prefixElement).toBeInTheDocument(); }, }; }