@octopusdeploy/design-system-components
Version:
The design systems component library.
339 lines (338 loc) • 17.5 kB
JavaScript
"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 Button_1 = require("../../../Button");
const TextField_1 = require("../TextField");
(0, vitest_1.describe)("<TextField />", () => {
(0, vitest_1.test)("renders with correct label", () => {
const input = renderTextInput({ label: "Test Label" });
input.shouldHaveLabel("Test Label");
input.shouldBeInDocument();
});
(0, vitest_1.test)("renders with placeholder text", () => {
const placeholder = "Enter your text here";
const input = renderTextInput({ label: "Test Label", placeholder });
input.shouldHavePlaceholder(placeholder);
});
(0, vitest_1.test)("renders with initial value", () => {
const value = "Initial value";
const input = renderTextInput({ label: "Test Label", value });
input.shouldHaveValue(value);
});
(0, vitest_1.test)("renders with description", () => {
const description = "This is a helpful description";
const input = renderTextInput({ label: "Test Label", description });
input.shouldHaveDescription(description);
});
(0, vitest_1.describe)("validationState", () => {
(0, vitest_1.test)("defaults to error state when validationMessage is provided without validationState", () => {
const validationMessage = "This field is required";
const input = renderTextInput({ label: "Test Label", validationMessage });
input.shouldHaveValidationMessage(validationMessage);
input.shouldShowErrorValidationState();
});
(0, vitest_1.test)("renders error state when validationState=error and a validationMessage is provided", () => {
const validationMessage = "This field is required";
const input = renderTextInput({ label: "Test Label", validationMessage, validationState: "error" });
input.shouldHaveValidationMessage(validationMessage);
input.shouldShowErrorValidationState();
});
(0, vitest_1.test)("renders success state when validationState=success and a validationMessage is provided", () => {
const validationMessage = "Looks good";
const input = renderTextInput({ label: "Test Label", validationMessage, validationState: "success" });
input.shouldHaveValidationMessage(validationMessage);
input.shouldShowSuccessValidationState();
});
(0, vitest_1.test)("does not render any validation state when validationState=error but no validationMessage is provided", () => {
const input = renderTextInput({ label: "Test Label", validationState: "error" });
input.shouldNotShowAnyValidationState();
});
(0, vitest_1.test)("does not render any validation state when validationState=success but no validationMessage is provided", () => {
const input = renderTextInput({ label: "Test Label", validationState: "success" });
input.shouldNotShowAnyValidationState();
});
});
(0, vitest_1.test)("uses provided name attribute", () => {
const name = "custom-name";
const input = renderTextInput({ label: "Test Label", name });
input.shouldHaveName(name);
});
(0, vitest_1.test)("has autofocus when autoFocus is true", () => {
const input = renderTextInput({ label: "Test Label", autoFocus: true });
input.shouldHaveFocus();
});
(0, vitest_1.test)("handles empty onChange gracefully", () => {
(0, react_1.render)((0, jsx_runtime_1.jsx)(TextField_1.TextField, { label: "Test Label", onChange: vitest_1.vi.fn() }));
const input = react_1.screen.getByRole("textbox");
(0, vitest_1.expect)(input).toBeInTheDocument();
});
(0, vitest_1.test)("calls onChange when user types", async () => {
const input = renderTextInput({ label: "Test Label" });
await input.type("hello");
input.shouldHaveCalledOnChangeWith("hello");
});
(0, vitest_1.test)("supports different input types", () => {
const emailInput = renderTextInput({ label: "Email", type: "email" });
const passwordInput = renderTextInput({ label: "Password", type: "password" });
const numberInput = renderTextInput({ label: "Number", type: "number" });
emailInput.shouldHaveType("email");
passwordInput.shouldHaveType("password");
numberInput.shouldHaveType("number");
});
(0, vitest_1.describe)("disabled and readonly properties", () => {
(0, vitest_1.test)("renders as disabled when disabled prop is true", () => {
const input = renderTextInput({ label: "Test Label", disabled: true });
input.shouldBeDisabled();
});
(0, vitest_1.test)("disabled input cannot be typed in", async () => {
const input = renderTextInput({ label: "Test Label", disabled: true });
await input.attemptToType("should not work");
input.shouldNotHaveCalledOnChange();
});
(0, vitest_1.test)("renders as readonly when readOnly prop is true", () => {
const input = renderTextInput({ label: "Test Label", readOnly: true });
input.shouldBeReadOnly();
});
(0, vitest_1.test)("readonly input cannot be typed in", async () => {
const input = renderTextInput({ label: "Test Label", readOnly: true });
await input.attemptToType("should not work");
input.shouldNotHaveCalledOnChange();
});
});
(0, vitest_1.describe)("default, required and optional marker properties", () => {
(0, vitest_1.test)("renders with required marker when hasRequiredMarker is true", () => {
const input = renderTextInput({ label: "Test Label", hasRequiredMarker: true });
input.shouldHaveRequiredMarker();
});
(0, vitest_1.test)("renders with optional marker when hasOptionalMarker is true", () => {
const input = renderTextInput({ label: "Test Label", hasOptionalMarker: true });
input.shouldHaveOptionalMarker();
});
(0, vitest_1.test)("renders with default marker when hasDefaultMarker is true", () => {
const input = renderTextInput({ label: "Test Label", hasDefaultMarker: true });
input.shouldHaveDefaultMarker();
});
});
(0, vitest_1.describe)("accessibility attributes", () => {
(0, vitest_1.test)("has correct accessibility attributes when error is present", () => {
const validationMessage = "Invalid input";
const input = renderTextInput({ 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 = renderTextInput({ 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 = renderTextInput({ label: "Test Label", description, validationMessage });
input.shouldHaveAriaDescribedByBoth();
input.shouldHaveAriaInvalid(true);
});
});
(0, vitest_1.describe)("prefix property", () => {
(0, vitest_1.test)("renders with string prefix", () => {
const input = renderTextInput({ label: "Test Label", prefix: "$" });
input.shouldHavePrefix("$");
});
(0, vitest_1.test)("renders with long string prefix", () => {
const longPrefix = "dollars";
const input = renderTextInput({ label: "Test Label", prefix: longPrefix });
input.shouldHavePrefix("dollars");
});
(0, vitest_1.test)("does not render prefix when not provided", () => {
const input = renderTextInput({ label: "Test Label" });
input.shouldNotHavePrefix();
});
(0, vitest_1.test)("prefix has correct accessibility attributes", () => {
const prefix = "ABCDEFG";
const input = renderTextInput({ label: "Test Label", prefix });
input.shouldHavePrefixWithTitle(prefix);
});
});
(0, vitest_1.describe)("suffix property", () => {
(0, vitest_1.test)("renders with string suffix", () => {
const input = renderTextInput({ label: "Test Label", suffix: "sec" });
input.shouldHaveSuffix("sec");
});
(0, vitest_1.test)("renders with long string suffix and truncates it", () => {
const longSuffix = "hello";
const input = renderTextInput({ label: "Test Label", suffix: longSuffix });
input.shouldHaveSuffix("hell");
});
(0, vitest_1.test)("renders with React element suffix", () => {
const buttonSuffix = (0, jsx_runtime_1.jsx)("button", { type: "button", children: "X" });
const input = renderTextInput({ label: "Test Label", suffix: buttonSuffix });
input.shouldHaveSuffixElement();
input.shouldHaveSuffixButton();
});
(0, vitest_1.test)("renders with Button component suffix", () => {
const buttonSuffix = (0, jsx_runtime_1.jsx)(Button_1.Button, { icon: (0, jsx_runtime_1.jsx)("span", { children: "\uD83D\uDD0D" }), onClick: () => { }, importance: "primary" });
const input = renderTextInput({ label: "Test Label", suffix: buttonSuffix });
input.shouldHaveSuffixElement();
input.shouldHaveSuffixButton();
});
(0, vitest_1.test)("does not render suffix when not provided", () => {
const input = renderTextInput({ label: "Test Label" });
input.shouldNotHaveSuffix();
});
(0, vitest_1.test)("suffix button is clickable", async () => {
const handleClick = vitest_1.vi.fn();
const buttonSuffix = ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: handleClick, children: "Click me" }));
const input = renderTextInput({ label: "Test Label", suffix: buttonSuffix });
await input.clickSuffixButton();
input.shouldHaveCalledSuffixClick(handleClick);
});
});
});
function renderTextInput(options) {
const onChange = vitest_1.vi.fn();
(0, react_1.render)((0, jsx_runtime_1.jsx)(TextField_1.TextField, { ...options, onChange: onChange }));
return getTextInputInteractions(options.label, onChange);
}
function getTextInputInteractions(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) => {
(0, vitest_1.expect)(input()).toHaveValue(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();
},
shouldHaveValidationMessage: (message) => {
(0, vitest_1.expect)(react_1.screen.getByText(message)).toBeInTheDocument();
},
shouldShowErrorValidationState: () => {
(0, vitest_1.expect)(react_1.screen.getByRole("img", { name: "Error" })).toBeInTheDocument();
},
shouldShowSuccessValidationState: () => {
(0, vitest_1.expect)(react_1.screen.getByRole("img", { name: "Success" })).toBeInTheDocument();
},
shouldNotShowAnyValidationState: () => {
(0, vitest_1.expect)(react_1.screen.queryByRole("img", { name: "Error" })).not.toBeInTheDocument();
(0, vitest_1.expect)(react_1.screen.queryByRole("img", { name: "Success" })).not.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();
},
shouldHaveType: (type) => {
(0, vitest_1.expect)(input()).toHaveAttribute("type", type);
},
shouldHaveName: (name) => {
(0, vitest_1.expect)(input()).toHaveAttribute("name", name);
},
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) => {
(0, vitest_1.expect)(onChange).toHaveBeenCalledWith(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 textbox = react_1.screen.getByRole("textbox");
(0, vitest_1.expect)(textbox).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("textbox");
(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 textbox = react_1.screen.getByRole("textbox");
(0, vitest_1.expect)(textbox).toBeInTheDocument();
},
shouldNotHavePrefix: () => {
const input = react_1.screen.getByRole("textbox");
(0, vitest_1.expect)(input).not.toHaveClass("inputStylesWithPrefix");
},
shouldHavePrefixWithTitle: (title) => {
const prefixElement = react_1.screen.getByTitle(title);
(0, vitest_1.expect)(prefixElement).toBeInTheDocument();
},
};
}