UNPKG

@octopusdeploy/design-system-components

Version:
264 lines (263 loc) • 17.8 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 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(); }, }; }