orcs-design-system
Version:
TeamForm's Design System, aka: ORCS
329 lines (298 loc) • 11.4 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
/* eslint-disable react/prop-types */
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import SideNavV2 from "../SideNav";
import { SideNavStateProvider } from "../context/SideNavStateProvider";
import SystemThemeProvider from "../../../SystemThemeProvider";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const renderWithTheme = (ui, options) => render(/*#__PURE__*/_jsx(SystemThemeProvider, {
children: ui
}), options);
// Mock components
jest.mock("../components/ExpandedPanel", () => {
return function MockExpandedPanel(_ref) {
let {
item,
onItemClick
} = _ref;
return /*#__PURE__*/_jsxs("div", {
"data-testid": "expanded-panel",
children: [/*#__PURE__*/_jsx("button", {
onClick: () => onItemClick(item, true),
"data-testid": "hide-panel-button",
children: "Hide Panel"
}), item.name]
});
};
});
jest.mock("../components/ItemSection", () => {
return function MockItemSection(_ref2) {
let {
items,
handleItemClick
} = _ref2;
return /*#__PURE__*/_jsx("div", {
"data-testid": "item-section",
children: items.map((item, index) => /*#__PURE__*/_jsx("button", {
onClick: () => handleItemClick(_objectSpread(_objectSpread({}, item), {}, {
index
})),
"data-testid": "nav-item-".concat(item.name),
children: item.name
}, index))
});
};
});
jest.mock("../components/CurrentViewSectionPortalTarget", () => {
return function MockCurrentViewSectionPortalTarget() {
return /*#__PURE__*/_jsx("div", {
"data-testid": "current-view-section"
});
};
});
jest.mock("../sections/SideNavTeamsSection", () => {
return function MockSideNavTeamsSection() {
return /*#__PURE__*/_jsx("div", {
"data-testid": "teams-section"
});
};
});
jest.mock("../sections/SideNavPinnedSection", () => {
return function MockSideNavPinnedSection() {
return /*#__PURE__*/_jsx("div", {
"data-testid": "pinned-section"
});
};
});
// Mock hooks
jest.mock("../hooks/useResponsive", () => ({
__esModule: true,
default: () => ({
isSmallScreen: false
})
}));
jest.mock("../hooks/useResize", () => ({
__esModule: true,
default: () => ({
handleResizeStart: jest.fn()
})
}));
const mockItems = [{
iconName: "home",
name: "Home",
actionType: "link",
link: "/home"
}, {
iconName: "settings",
name: "Settings",
actionType: "component",
component: () => /*#__PURE__*/_jsx("div", {
children: "Settings Panel"
})
}, {
iconName: "profile",
name: "Profile",
actionType: "component",
component: () => /*#__PURE__*/_jsx("div", {
children: "Profile Panel"
})
}];
const renderSideNav = function () {
let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return renderWithTheme(/*#__PURE__*/_jsx(SideNavStateProvider, {
children: /*#__PURE__*/_jsx(SideNavV2, _objectSpread({
items: mockItems,
sideNavHeight: "100vh"
}, props))
}));
};
const getToggleButton = () => screen.getByTestId("toggle-handle");
/**
* SideNavV2 interaction tests.
* Note: The side nav does NOT auto-expand or auto-collapse on hover; expand/collapse is only via the toggle button.
*/
describe("SideNavV2 Interaction Scenarios", () => {
beforeEach(() => {
// Reset all mocks
jest.clearAllMocks();
});
describe("Scenario 1: Page load with expanded nav", () => {
it("should load with expanded nav", () => {
renderSideNav();
// Nav should be expanded
const sideNavItems = screen.getByTestId("side-nav-items");
expect(sideNavItems).toBeInTheDocument();
// Toggle should be present
const toggleButton = getToggleButton();
expect(toggleButton).toBeInTheDocument();
});
});
describe("Scenario 2: Toggle nav collapse/expand", () => {
it("should toggle navigation state when clicking toggle button", async () => {
renderSideNav();
// Initially toggle should be present
const toggleButton = getToggleButton();
expect(toggleButton).toBeInTheDocument();
// Click toggle to collapse
fireEvent.click(toggleButton);
// Wait for state to settle
await new Promise(resolve => setTimeout(resolve, 100));
// Check that the toggle button is still present
expect(getToggleButton()).toBeInTheDocument();
// Click toggle again to expand
fireEvent.click(toggleButton);
await waitFor(() => {
expect(getToggleButton()).toBeInTheDocument();
});
});
});
describe("Scenario 3: Open expanded panel", () => {
it("should open expanded panel and keep it open on repeated clicks", async () => {
renderSideNav();
// Nav should be expanded initially
const sideNavItems = screen.getByTestId("side-nav-items");
expect(sideNavItems).toBeInTheDocument();
// Click nav item to open expanded panel
const settingsButton = screen.getByTestId("nav-item-Settings");
fireEvent.click(settingsButton);
// Expanded panel should be open
await waitFor(() => {
expect(screen.getByTestId("expanded-panel")).toBeInTheDocument();
});
// Click the same item again - panel should stay open (no toggle behavior)
fireEvent.click(settingsButton);
await waitFor(() => {
expect(screen.getByTestId("expanded-panel")).toBeInTheDocument();
});
// Toggle should still be present
expect(getToggleButton()).toBeInTheDocument();
});
});
describe("Scenario 4: Toggle between different panels", () => {
it("should switch between different expanded panels", async () => {
renderSideNav();
// Open Settings panel
const settingsButton = screen.getByTestId("nav-item-Settings");
fireEvent.click(settingsButton);
await waitFor(() => {
const panel = screen.getByTestId("expanded-panel");
expect(panel).toBeInTheDocument();
expect(panel).toHaveTextContent("Settings");
});
// Open Profile panel
const profileButton = screen.getByTestId("nav-item-Profile");
fireEvent.click(profileButton);
await waitFor(() => {
const panel = screen.getByTestId("expanded-panel");
expect(panel).toBeInTheDocument();
expect(panel).toHaveTextContent("Profile");
});
});
});
describe("Scenario 5: Close button functionality", () => {
it("should close panel when close button is clicked", async () => {
renderSideNav();
// Open Settings panel
const settingsButton = screen.getByTestId("nav-item-Settings");
fireEvent.click(settingsButton);
// Panel should be open
await waitFor(() => {
expect(screen.getByTestId("expanded-panel")).toBeInTheDocument();
});
// Click close button
const closeButton = screen.getByTestId("hide-panel-button");
fireEvent.click(closeButton);
// Panel should be closed
await waitFor(() => {
expect(screen.queryByTestId("expanded-panel")).toBeNull();
});
// Nav should still be expanded
const sideNavItems = screen.getByTestId("side-nav-items");
expect(sideNavItems).toBeInTheDocument();
});
});
describe("Scenario 6: onKeepExpandedChange callback", () => {
it("should call onKeepExpandedChange with new expanded state when toggle is clicked", async () => {
const onKeepExpandedChange = jest.fn();
renderSideNav({
onKeepExpandedChange
});
const toggleButton = getToggleButton();
// Click to collapse (starts expanded by default)
fireEvent.click(toggleButton);
await waitFor(() => {
expect(onKeepExpandedChange).toHaveBeenCalledWith(false);
});
// Click again to expand
fireEvent.click(toggleButton);
await waitFor(() => {
expect(onKeepExpandedChange).toHaveBeenCalledWith(true);
});
expect(onKeepExpandedChange).toHaveBeenCalledTimes(2);
});
});
describe("Scenario 7: Link item click", () => {
it("should close expanded panel when a link item is clicked", async () => {
renderSideNav();
// Open Settings panel
const settingsButton = screen.getByTestId("nav-item-Settings");
fireEvent.click(settingsButton);
await waitFor(() => {
expect(screen.getByTestId("expanded-panel")).toBeInTheDocument();
});
// Click link item (Home) - should close the panel
const homeButton = screen.getByTestId("nav-item-Home");
fireEvent.click(homeButton);
await waitFor(() => {
expect(screen.queryByTestId("expanded-panel")).toBeNull();
});
});
it("should not open expanded panel when only link items are clicked", () => {
renderSideNav();
const homeButton = screen.getByTestId("nav-item-Home");
fireEvent.click(homeButton);
expect(screen.queryByTestId("expanded-panel")).toBeNull();
});
});
describe("Scenario 8: Toggle button positioning", () => {
it("should have toggle button positioned at the right edge of sidenav when expanded", () => {
renderSideNav({
startExpanded: true
});
const toggleButton = getToggleButton();
expect(toggleButton).toBeInTheDocument();
// Toggle button should be visible and positioned correctly
const styles = window.getComputedStyle(toggleButton);
expect(styles.position).toBe("absolute");
expect(styles.zIndex).toBe("100");
});
it("should have toggle button positioned at the right edge of sidenav when collapsed", () => {
renderSideNav({
startExpanded: false
});
const toggleButton = getToggleButton();
expect(toggleButton).toBeInTheDocument();
// Toggle button should be visible and positioned correctly
const styles = window.getComputedStyle(toggleButton);
expect(styles.position).toBe("absolute");
expect(styles.zIndex).toBe("100");
});
it("should toggle button be clickable and functional", async () => {
renderSideNav({
startExpanded: true
});
const toggleButton = getToggleButton();
// Toggle button should exist and be clickable
expect(toggleButton).toBeInTheDocument();
// Should be able to click it
fireEvent.click(toggleButton);
await new Promise(resolve => setTimeout(resolve, 100));
// Should still be present after click
expect(getToggleButton()).toBeInTheDocument();
});
});
});