|
| 1 | +## Test Cases |
| 2 | + |
| 3 | +<!-- |
| 4 | +Unit tests use Jest + RTL and mock `hooks/useFloatingMenu` via |
| 5 | +`src/hooks/__mocks__/useFloatingMenu.ts` (the mock returns stable refs + a marker |
| 6 | +style so specs don't depend on real layout). The real middleware behavior (flip, |
| 7 | +size/shrink) is not exercisable in jsdom (no layout), so it is verified by e2e / |
| 8 | +manual showcase rather than unit tests. Unit tests assert the WIRING and the |
| 9 | +alwaysOpen bypass; e2e asserts the observable no-jump / shrink behavior. |
| 10 | +--> |
| 11 | + |
| 12 | +### Reproduction Tests |
| 13 | + |
| 14 | +- Menu wiring uses floating-ui, not the old style hook - `useMenuStyle` is gone and the |
| 15 | + wrapper is positioned via floating refs (unit) |
| 16 | + - **Given**: `SingleSelection` rendered open with a mocked `useFloatingMenu` |
| 17 | + - **When**: component mounts and the menu opens |
| 18 | + - **Then**: the menu wrapper (`.widget-combobox-menu`) receives the floating ref and the |
| 19 | + `floatingStyles` from the hook; no import of `useMenuStyle` remains in the module graph |
| 20 | + |
| 21 | +- Menu placement does not oscillate near the viewport bottom (e2e) |
| 22 | + - **Given**: a Combobox positioned so there is less space below than the menu's natural |
| 23 | + height, with enough options to fill the menu |
| 24 | + - **When**: the menu is opened and left open |
| 25 | + - **Then**: the menu settles in a single placement within one animation frame and its |
| 26 | + `top` (bounding rect) does not change across subsequent frames (no flip-flop) |
| 27 | + |
| 28 | +- Menu does not jump when the option count changes while open (e2e) |
| 29 | + - **Given**: an open Combobox near the viewport bottom with a text filter |
| 30 | + - **When**: the user types to reduce, then clear, the number of matching options |
| 31 | + - **Then**: the menu re-anchors smoothly and does not flip between above/below the input |
| 32 | + |
| 33 | +### Edge Cases |
| 34 | + |
| 35 | +- Menu shrinks and scrolls instead of overflowing when space is tight (e2e) |
| 36 | + - **Given**: a Combobox with many options and limited space below it |
| 37 | + - **When**: the menu opens |
| 38 | + - **Then**: the menu height is capped to the available space (`maxHeight <= availableHeight`), |
| 39 | + the option list scrolls internally, and the menu bottom stays within the viewport |
| 40 | + (respecting the 8px padding) |
| 41 | + |
| 42 | +- Menu width matches the input width (unit + e2e) |
| 43 | + - **Given**: a Combobox of a known input-container width, menu open |
| 44 | + - **When**: floating-ui's `size` middleware applies |
| 45 | + - **Then**: the menu wrapper width equals the reference (input container) width |
| 46 | + |
| 47 | +- Menu header and footer remain visible when the menu shrinks (e2e) |
| 48 | + - **Given**: a Combobox configured with `menuHeaderContent` and `menuFooterContent`, in a |
| 49 | + tight space so the menu shrinks |
| 50 | + - **When**: the menu opens |
| 51 | + - **Then**: header and footer are both fully visible; only the option list scrolls; footer |
| 52 | + is not clipped below the fold |
| 53 | + |
| 54 | +- Menu does not flash before it is positioned (e2e) |
| 55 | + - **Given**: a Combobox opened |
| 56 | + - **When**: the first render occurs before floating-ui reports `isPositioned` |
| 57 | + - **Then**: the menu is `visibility: hidden` until positioned (no visible jump-from-origin) |
| 58 | + |
| 59 | +### Regression Tests |
| 60 | + |
| 61 | +- alwaysOpen (`keepMenuOpen`) renders inline and does not use floating positioning (unit) |
| 62 | + - **Given**: `SingleSelection` and `MultiSelection` rendered with `keepMenuOpen` |
| 63 | + - **When**: the menu renders |
| 64 | + - **Then**: the wrapper style is `position: relative` (inline block), it does NOT carry the |
| 65 | + floating ref/`floatingStyles`, and `useFloatingMenu` is called with `open = false` |
| 66 | + |
| 67 | +- MultiSelection wires floating identically to SingleSelection (unit) |
| 68 | + - **Given**: `MultiSelection` rendered open (not alwaysOpen) |
| 69 | + - **When**: it mounts |
| 70 | + - **Then**: reference ref is on the input container, floating ref + styles are on the menu |
| 71 | + wrapper — same contract as `SingleSelection` |
| 72 | + |
| 73 | +- Lazy-loading scroll still works (unit) |
| 74 | + - **Given**: a Combobox with `lazyLoading` enabled and `hasMore` options, menu open |
| 75 | + - **When**: the option list is scrolled |
| 76 | + - **Then**: the `onScroll` handler fires and the `widget-combobox-menu-lazy-scroll` class is |
| 77 | + applied to the list — unchanged from current behavior |
| 78 | + |
| 79 | +- Existing Single/Multi/Static selection specs pass with the new mock (unit) |
| 80 | + - **Given**: the existing `SingleSelection.spec`, `MultiSelection.spec`, `StaticSelection.spec` |
| 81 | + - **When**: run against the floating-ui implementation with `useFloatingMenu` mocked |
| 82 | + - **Then**: all previously-passing assertions still pass (menu render, item selection, |
| 83 | + open/close, a11y attributes) |
| 84 | + |
| 85 | +## Notes |
| 86 | + |
| 87 | +<!-- Track unexpected behaviors, additional edge cases found, test failures and resolutions. --> |
| 88 | + |
| 89 | +- Real flip/shrink math is not unit-testable in jsdom (no layout engine). The no-jump and |
| 90 | + shrink outcomes are the reporter's core complaint, so they are covered by real Playwright |
| 91 | + e2e in `e2e/Combobox.spec.js` (stable `top` near the bottom edge, capped `maxHeight`, width |
| 92 | + == input) plus the manual showcase for Takuma / Ana. |
| 93 | +- Transformed/`contain`/`filter` ancestor + `position: fixed` mis-anchoring is a known |
| 94 | + limitation (no portal this pass) — not covered by a test, documented in proposal. |
0 commit comments