UNPKG

@crossed/ui

Version:

A universal & performant styling library for React Native, Next.js & React

219 lines (218 loc) 9.83 kB
import { jsx, jsxs } from "react/jsx-runtime"; import { render } from "@crossed/test"; import { DropDownMenu } from "../index"; import { Popover, useFloatingContext } from "../../overlay"; import { MenuList } from "../MenuList"; import { Divider } from "../../layout/Divider"; import { useMedia } from "../../useMedia"; import { Text } from "../../typography"; jest.mock("../../overlay", () => ({ Popover: Object.assign( jest.fn(({ children }) => children), { Trigger: jest.fn(({ children }) => children), Content: jest.fn(({ children }) => children) } ), useFloatingContext: jest.fn() })); jest.mock("../MenuList", () => ({ MenuList: Object.assign( jest.fn(({ children }) => children), { Item: jest.fn(({ children }) => children), Label: jest.fn(({ children }) => children), Title: jest.fn(({ children }) => children) } ) })); jest.mock("../../layout/Divider", () => ({ Divider: jest.fn(() => null) })); jest.mock("../../useMedia", () => ({ useMedia: jest.fn() })); const PopoverMocked = jest.mocked(Popover); const MenuListMocked = jest.mocked(MenuList); const useFloatingContextMocked = jest.mocked(useFloatingContext); const useMediaMocked = jest.mocked(useMedia); const DividerMocked = jest.mocked(Divider); const mockUseMedia = (md) => { useMediaMocked.mockReturnValue({ md, sm: false, lg: false, xl: false }); }; const mockFloatingContext = (onClose = jest.fn()) => { useFloatingContextMocked.mockReturnValue({ onClose, open: true, onOpen: jest.fn() }); }; describe("DropDownMenu", () => { beforeEach(() => { mockUseMedia(true); mockFloatingContext(); }); afterEach(() => { jest.clearAllMocks(); }); test("renders with default props", () => { render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const call = PopoverMocked.mock.calls[0][0]; expect(call).toHaveProperty("placement", "bottom-end"); expect(call).toHaveProperty("triggerStrategy", "onPress"); expect(call).toHaveProperty("children"); }); test("accepts custom placement", () => { render( /* @__PURE__ */ jsxs(DropDownMenu, { placement: "top-start", children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const call = PopoverMocked.mock.calls[0][0]; expect(call).toHaveProperty("placement", "top-start"); }); test("accepts custom triggerStrategy", () => { render( /* @__PURE__ */ jsxs(DropDownMenu, { triggerStrategy: "onPointerEnter", children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const call = PopoverMocked.mock.calls[0][0]; expect(call).toHaveProperty("triggerStrategy", "onPointerEnter"); }); test("forwards additional props to Popover", () => { render( /* @__PURE__ */ jsxs(DropDownMenu, { offsetValue: 15, children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const call = PopoverMocked.mock.calls[0][0]; expect(call).toHaveProperty("offsetValue", 15); }); test("renders all static components", () => { expect(DropDownMenu.Trigger).toBeDefined(); expect(DropDownMenu.Content).toBeDefined(); expect(DropDownMenu.Item).toBeDefined(); expect(DropDownMenu.Label).toBeDefined(); expect(DropDownMenu.Title).toBeDefined(); expect(DropDownMenu.Divider).toBeDefined(); }); test("Content renders MenuList with bordered=true on desktop", () => { mockUseMedia(true); MenuListMocked.mockClear(); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const menuListCall = MenuListMocked.mock.calls[0][0]; expect(menuListCall).toHaveProperty("bordered", true); }); test("Content renders MenuList with bordered=false on mobile", () => { mockUseMedia(false); MenuListMocked.mockClear(); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const menuListCall = MenuListMocked.mock.calls[0][0]; expect(menuListCall).toHaveProperty("bordered", false); }); test("Item closes popover on press", () => { const onClose = jest.fn(); mockFloatingContext(onClose); const MenuListItemMocked = jest.mocked(MenuList.Item); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { onPress: () => { }, children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const itemCall = MenuListItemMocked.mock.calls[0][0]; expect(itemCall).toHaveProperty("onPress"); if ("onPress" in itemCall && typeof itemCall.onPress === "function") { itemCall.onPress({}); } expect(onClose).toHaveBeenCalledTimes(1); }); test("Item composes custom onPress with onClose", () => { const onClose = jest.fn(); const customOnPress = jest.fn(); mockFloatingContext(onClose); const MenuListItemMocked = jest.mocked(MenuList.Item); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { onPress: customOnPress, children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); const itemCall = MenuListItemMocked.mock.calls[0][0]; if ("onPress" in itemCall && typeof itemCall.onPress === "function") { itemCall.onPress({}); } expect(customOnPress).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledTimes(1); }); test("Label renders MenuList.Label", () => { const MenuListLabelMocked = jest.mocked(MenuList.Label); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }) }) ] }) ); expect(MenuListLabelMocked).toHaveBeenCalled(); }); test("Title renders MenuList.Title", () => { const MenuListTitleMocked = jest.mocked(MenuList.Title); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Title, { children: "Menu Title" }) }) ] }) ); expect(MenuListTitleMocked).toHaveBeenCalled(); }); test("Divider renders Divider component", () => { render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsxs(DropDownMenu.Content, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 1" }) }), /* @__PURE__ */ jsx(DropDownMenu.Divider, {}), /* @__PURE__ */ jsx(DropDownMenu.Item, { children: /* @__PURE__ */ jsx(DropDownMenu.Label, { children: "Item 2" }) }) ] }) ] }) ); expect(DividerMocked).toHaveBeenCalled(); }); test("Divider forwards props", () => { DividerMocked.mockClear(); render( /* @__PURE__ */ jsxs(DropDownMenu, { children: [ /* @__PURE__ */ jsx(DropDownMenu.Trigger, { children: /* @__PURE__ */ jsx(Text, { children: "Open Menu" }) }), /* @__PURE__ */ jsx(DropDownMenu.Content, { children: /* @__PURE__ */ jsx(DropDownMenu.Divider, { direction: "vertical" }) }) ] }) ); const dividerCall = DividerMocked.mock.calls[0][0]; expect(dividerCall).toHaveProperty("direction", "vertical"); }); }); //# sourceMappingURL=DropDownMenu.spec.js.map