@octopusdeploy/design-system-components
Version:
The design systems component library.
264 lines (263 loc) • 17.8 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 react_2 = require("react");
const vitest_1 = require("vitest");
const UpsellDialog_1 = require("../UpsellDialog");
const defaultDialogContent = "The dialog content";
(0, vitest_1.describe)("UpsellDialog", () => {
(0, vitest_1.test)("shows the dialog when it is open", () => {
const title = "Upsell Dialog";
const { assertDialogIsOpen } = renderUpsellDialog({ open: true, title });
assertDialogIsOpen(title);
});
(0, vitest_1.test)("does not show the dialog when closed", () => {
const title = "Upsell Dialog";
renderUpsellDialog({ open: false, title });
(0, vitest_1.expect)(react_1.screen.queryByRole("dialog", { name: title })).not.toBeInTheDocument();
});
(0, vitest_1.test)("will close the dialog when the close button is clicked", async () => {
const title = "Upsell Dialog";
const { clickCloseButton, assertOnCloseDialogCalled } = renderUpsellDialog({ open: true, title });
await clickCloseButton();
assertOnCloseDialogCalled();
});
(0, vitest_1.test)("will close the dialog when escape is pressed", async () => {
const title = "Upsell Dialog";
const { pressEscape, assertOnCloseDialogCalled } = renderUpsellDialog({ open: true, title });
await pressEscape();
assertOnCloseDialogCalled();
});
(0, vitest_1.test)("will close the dialog when the overlay is clicked", async () => {
const title = "Upsell Dialog";
const { clickOverlay, assertOnCloseDialogCalled } = renderUpsellDialog({ open: true, title });
await clickOverlay();
assertOnCloseDialogCalled();
});
(0, vitest_1.test)("shows the dialog title", () => {
const title = "Upsell Dialog";
const { assertHasDialogTitle } = renderUpsellDialog({ open: true, title });
assertHasDialogTitle(title);
});
(0, vitest_1.test)("shows the dialog content", () => {
const expectedContent = "Test Dialog Content";
const { assertHasDialogContent } = renderUpsellDialog({ open: true, title: "Upsell Dialog", content: expectedContent });
assertHasDialogContent(expectedContent);
});
(0, vitest_1.test)("renders the side panel content", () => {
const content = "This is the main dialog content";
const sidePanelText = "This is an image placeholder";
const { assertHasDialogContent } = renderUpsellDialog({ open: true, title: "Upsell Dialog", content, sidePanel: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: sidePanelText }) });
assertHasDialogContent(content);
assertHasDialogContent(sidePanelText);
});
(0, vitest_1.test)("does not show side panel toggle (upsell has no toggle)", () => {
const sidePanelContent = "Upsell side panel content";
const { assertHasNoSidePanelToggle } = renderUpsellDialog({
open: true,
title: "Upsell Dialog",
sidePanel: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: sidePanelContent }),
});
assertHasNoSidePanelToggle();
});
(0, vitest_1.test)("can click primary button when provided", async () => {
const onClick = vitest_1.vi.fn();
const { clickButton } = renderUpsellDialog({ open: true, title: "Upsell Dialog", primaryActionOptions: { onClick, label: "Upgrade now" } });
await clickButton("Upgrade now");
(0, vitest_1.expect)(onClick).toHaveBeenCalled();
});
(0, vitest_1.test)("can click secondary button when provided", async () => {
const onClick = vitest_1.vi.fn();
const { clickButton } = renderUpsellDialog({ open: true, title: "Upsell Dialog", secondaryActionOptions: { onClick, label: "Maybe later" } });
await clickButton("Maybe later");
(0, vitest_1.expect)(onClick).toHaveBeenCalled();
});
(0, vitest_1.test)("renders error panels when errors are provided", () => {
const errorMessage = "Something went wrong";
const errors = [{ message: errorMessage, details: [] }];
const { assertHasDialogContent } = renderUpsellDialog({ open: true, title: "Upsell Dialog", errors });
assertHasDialogContent(errorMessage);
});
(0, vitest_1.test)("renders progress tracker when provided", () => {
const progressTracker = (0, jsx_runtime_1.jsx)("span", { children: "Progress tracker content" });
renderUpsellDialog({ open: true, title: "Upsell Dialog", progressTracker });
(0, vitest_1.expect)(react_1.screen.getByText("Progress tracker content")).toBeInTheDocument();
});
(0, vitest_1.describe)("multi-step", () => {
const defaultSteps = [{ content: (0, jsx_runtime_1.jsx)("p", { children: "Step 1 content" }) }, { content: (0, jsx_runtime_1.jsx)("p", { children: "Step 2 content" }) }, { content: (0, jsx_runtime_1.jsx)("p", { children: "Step 3 content" }) }];
function renderMultiStep(options = {}) {
const onClose = vitest_1.vi.fn();
const { steps = defaultSteps, open = true, onComplete, completeButtonLabel, backButtonDisabled, nextButtonDisabled } = options;
(0, react_1.render)((0, jsx_runtime_1.jsx)(UpsellDialog_1.UpsellDialog, { open: open, onClose: onClose, title: "Multi-step Upsell", steps: steps, onComplete: onComplete, completeButtonLabel: completeButtonLabel, backButtonDisabled: backButtonDisabled, nextButtonDisabled: nextButtonDisabled, sidePanel: defaultSidePanel }));
return { onClose, ...getInteractions(onClose) };
}
(0, vitest_1.test)("renders the first step content", () => {
renderMultiStep();
(0, vitest_1.expect)(react_1.screen.getByText("Step 1 content")).toBeInTheDocument();
});
(0, vitest_1.test)("shows a step indicator when there are multiple steps", () => {
renderMultiStep();
(0, vitest_1.expect)(react_1.screen.getByText("1 of 3")).toBeInTheDocument();
});
(0, vitest_1.test)("does not show a step indicator for a single step", () => {
renderMultiStep({ steps: [{ content: (0, jsx_runtime_1.jsx)("p", { children: "Only step" }) }] });
(0, vitest_1.expect)(react_1.screen.queryByRole("navigation", { name: "Step progress" })).not.toBeInTheDocument();
});
(0, vitest_1.test)("shows a Next button on non-final steps", () => {
renderMultiStep();
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Next" })).toBeInTheDocument();
});
(0, vitest_1.test)("does not show a Back button on the first step", () => {
renderMultiStep();
(0, vitest_1.expect)(react_1.screen.queryByRole("button", { name: "Back" })).not.toBeInTheDocument();
});
(0, vitest_1.test)("clicking Next moves to the next step", async () => {
renderMultiStep();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 2 content")).toBeInTheDocument();
});
(0, vitest_1.test)("shows a Back button after navigating forward", async () => {
renderMultiStep();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Back" })).toBeInTheDocument();
});
(0, vitest_1.test)("clicking Back moves to the previous step", async () => {
renderMultiStep();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Back" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 1 content")).toBeInTheDocument();
});
(0, vitest_1.test)("shows 'Complete' button on the last step by default", async () => {
renderMultiStep();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Complete" })).toBeInTheDocument();
});
(0, vitest_1.test)("shows custom completeButtonLabel on the last step", async () => {
renderMultiStep({ completeButtonLabel: "Upgrade now" });
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Upgrade now" })).toBeInTheDocument();
});
(0, vitest_1.test)("clicking the complete button calls onComplete", async () => {
const onComplete = vitest_1.vi.fn();
renderMultiStep({ onComplete });
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Complete" }));
(0, vitest_1.expect)(onComplete).toHaveBeenCalledTimes(1);
});
(0, vitest_1.test)("clicking the cancel button calls onClose", async () => {
const { onClose } = renderMultiStep();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Cancel" }));
(0, vitest_1.expect)(onClose).toHaveBeenCalledTimes(1);
});
(0, vitest_1.test)("onBeforeNext returning false blocks navigation", async () => {
const steps = [{ content: (0, jsx_runtime_1.jsx)("p", { children: "Step 1 content" }), onBeforeNext: () => false }, { content: (0, jsx_runtime_1.jsx)("p", { children: "Step 2 content" }) }];
renderMultiStep({ steps });
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 1 content")).toBeInTheDocument();
});
(0, vitest_1.test)("onBeforeBack returning false blocks back navigation", async () => {
const steps = [{ content: (0, jsx_runtime_1.jsx)("p", { children: "Step 1 content" }) }, { content: (0, jsx_runtime_1.jsx)("p", { children: "Step 2 content" }), onBeforeBack: () => false }];
renderMultiStep({ steps });
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 2 content")).toBeInTheDocument();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Back" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 2 content")).toBeInTheDocument();
});
(0, vitest_1.test)("back button is disabled when backButtonDisabled is true", async () => {
renderMultiStep({ backButtonDisabled: true });
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Back" })).toBeDisabled();
});
(0, vitest_1.test)("next button is disabled when nextButtonDisabled is true", () => {
renderMultiStep({ nextButtonDisabled: true });
(0, vitest_1.expect)(react_1.screen.getByRole("button", { name: "Next" })).toBeDisabled();
});
(0, vitest_1.test)("per-step sidePanel overrides the dialog-level sidePanel", async () => {
const steps = [{ content: (0, jsx_runtime_1.jsx)("p", { children: "Step 1" }), sidePanel: (0, jsx_runtime_1.jsx)("p", { children: "Step 1 panel" }) }, { content: (0, jsx_runtime_1.jsx)("p", { children: "Step 2" }) }];
(0, react_1.render)((0, jsx_runtime_1.jsx)(UpsellDialog_1.UpsellDialog, { open: true, onClose: vitest_1.vi.fn(), title: "Test", steps: steps, sidePanel: (0, jsx_runtime_1.jsx)("p", { children: "Dialog panel" }) }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 1 panel")).toBeInTheDocument();
(0, vitest_1.expect)(react_1.screen.queryByText("Dialog panel")).not.toBeInTheDocument();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByText("Dialog panel")).toBeInTheDocument();
(0, vitest_1.expect)(react_1.screen.queryByText("Step 1 panel")).not.toBeInTheDocument();
});
(0, vitest_1.test)("resets to step 0 when the dialog closes and reopens", async () => {
function TestWrapper() {
const [open, setOpen] = (0, react_2.useState)(true);
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setOpen(false), children: "close" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setOpen(true), children: "open" }), (0, jsx_runtime_1.jsx)(UpsellDialog_1.UpsellDialog, { open: open, onClose: () => setOpen(false), title: "Test", steps: defaultSteps, sidePanel: defaultSidePanel })] }));
}
(0, react_1.render)((0, jsx_runtime_1.jsx)(TestWrapper, {}));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "Next" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 2 content")).toBeInTheDocument();
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "close" }));
await user_event_1.default.click(react_1.screen.getByRole("button", { name: "open" }));
(0, vitest_1.expect)(react_1.screen.getByText("Step 1 content")).toBeInTheDocument();
});
});
(0, vitest_1.describe)("extraLarge size", () => {
(0, vitest_1.test)("renders both main content and side panel content (stacked layout)", () => {
const sidePanelText = "Stacked side panel";
const { assertHasDialogContent } = renderUpsellDialog({
open: true,
title: "Extra Large Upsell",
width: "extraLarge",
content: "Main content body",
sidePanel: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: sidePanelText }),
});
assertHasDialogContent("Main content body");
assertHasDialogContent(sidePanelText);
});
});
});
const defaultPrimaryAction = { onClick: () => { }, label: "Upgrade now" };
const defaultSidePanel = (0, jsx_runtime_1.jsx)("div", { children: "Side panel" });
function renderUpsellDialog({ open, primaryActionOptions, title, content, sidePanel, secondaryActionOptions, errors, progressTracker, width }) {
const onClose = vitest_1.vi.fn();
(0, react_1.render)((0, jsx_runtime_1.jsx)(UpsellDialog_1.UpsellDialog, { open: open, onClose: onClose, title: title, width: width, primaryAction: primaryActionOptions ?? defaultPrimaryAction, sidePanel: sidePanel ?? defaultSidePanel, secondaryAction: secondaryActionOptions, errors: errors, progressTracker: progressTracker, children: content ?? defaultDialogContent }));
return getInteractions(onClose);
}
function dispatchDialogFadeOutAnimationEnd() {
const dialogElement = react_1.screen.getByRole("dialog");
const animationEndEvent = new Event("animationend", { bubbles: true });
Object.defineProperty(animationEndEvent, "animationName", { value: "dialogFadeOut", writable: false });
(0, react_2.act)(() => {
dialogElement.dispatchEvent(animationEndEvent);
});
}
function getInteractions(onClose) {
return {
clickOverlay: async () => {
const overlay = react_1.screen.getByRole("presentation", { name: "overlay" });
await user_event_1.default.click(overlay);
dispatchDialogFadeOutAnimationEnd();
},
pressEscape: async () => {
await user_event_1.default.keyboard("{Escape}");
dispatchDialogFadeOutAnimationEnd();
},
clickCloseButton: async () => {
const button = react_1.screen.getByRole("button", { name: "Close dialog" });
await user_event_1.default.click(button);
},
clickButton: async (accessibleName) => {
const button = react_1.screen.getByRole("button", { name: accessibleName });
await user_event_1.default.click(button);
},
assertHasDialogContent: (content) => (0, vitest_1.expect)(react_1.screen.getByText(content)).toBeInTheDocument(),
assertDialogIsOpen: (accessibleName) => (0, vitest_1.expect)(react_1.screen.getByRole("dialog", { name: accessibleName })).toBeInTheDocument(),
assertOnCloseDialogCalled: () => (0, vitest_1.expect)(onClose).toHaveBeenCalled(),
assertHasDialogTitle: (title) => (0, vitest_1.expect)(react_1.screen.getByText(title)).toBeInTheDocument(),
assertHasNoSidePanelToggle: () => {
(0, vitest_1.expect)(react_1.screen.queryByRole("button", { name: "Open side panel" })).not.toBeInTheDocument();
(0, vitest_1.expect)(react_1.screen.queryByRole("button", { name: "Close side panel" })).not.toBeInTheDocument();
},
};
}