LearnNewsExamplesServices
Frontmatter
id18848
titleWitness the menu hover and keyboard paths that already work
stateClosed
labels
enhancementaitesting
assigneesneo-opus-grace
createdAtSep 18, 2026, 1:02 PM
updatedAtSep 18, 2026, 2:24 PM
githubUrlhttps://github.com/neomjs/neo/issues/18848
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 18, 2026, 2:24 PM

Witness the menu hover and keyboard paths that already work

Closed Backlog/active-chunk-23 enhancementaitesting
neo-opus-grace
neo-opus-grace commented on Sep 18, 2026, 1:02 PM

Context

The operator asked for more tests of menu hover and keyboard navigation, submenus included (2026-09-18). Scratch Playwright arms against dev@3f859a4803 measured the paths below as correct today. None has an arm. @neo-opus-ada, who built the menu stack, cross-checked each gap by grepping component/menu, unit/menu and component/button/Base.spec.mjs. The defects the same probes found are filed separately.

# path measured
1 Arrowing past a parent faster than subMenuHoverDelay never previews (maximum levels observed: 1), while resting on it previews (2). This is the debounce contract of the focus rest (#18780)
2 Arrow keys over a disabled row and a separator skipped both ways
3 A pointer rest on a disabled parent previews nothing
4 Hover to depth 3, then a rest on a root leaf the whole branch goes in one step: level counts [3, 1]
5 A click on a leaf inside a hover preview that focus never entered every level closes, and the item's route fires exactly once
6 Enter on a leaf two levels down every level closes together ([3, 0]), and the route fires once
7 Escape from depth 3 walks back one level per press, focusing each parent item, then dismisses
8 Arrowing inside a submenu previews and drops that submenu's own child level, never closing itself
9 Tab out of a submenu dismisses the whole floating cascade
10 The pointer leaving the menu while a preview shows the preview stays
11 A press on dead space in a form.field.ComboBox's bound list (added after #18854, at @neo-opus-vega's review note) the input keeps focus. This is the one Navigator consumer whose focus lives outside the subject, so the walk's subject.parentNode limit is what the arm witnesses

The Problem

The 09-16 stack (#18758 → #18804) pinned what it changed. Everything above works because of how those pieces compose, and a regression in any of them would ship green. Row 1 is the most exposed: the focus-rest arms use subMenuHoverDelay 0 or 1000, never a pass-through faster than the delay.

The Architectural Reality

  • The fixtures already exist in test/playwright/component/menu/List.spec.mjs: createMenu(page, config), the three-level items tree, restItems, recordLevelCounts / levelCounts and focusedItem. A route on a leaf gives an exactly-once witness: count hashchange events, because Neo.Main.setRoute writes location.hash.
  • Absence needs a bounded wait before it is read, the way the existing arms "outlast the delay". Presence polls.

The Fix

Add one arm per row to test/playwright/component/menu/List.spec.mjs, reusing its fixtures. It is a test-only change.

Acceptance Criteria

  • Rows 1–11 each have an arm, green on dev (row 11 once #18854 is on dev, which it is).

  • Rows 1 and 4 each fail under a one-line source mutation that breaks the behaviour they claim, recorded in the PR:

    • row 1: startRest ignores subMenuHoverDelay
    • row 4: a level's unmount() stops hiding its own submenu

    Row 3 has two independent guards, the row's pointer-events: none and the hover delegate's nonInteractiveItemCls check, so no single mutation reddens it. The PR says so rather than claiming one.

  • No arm asserts a process-global or timing-sensitive count, and each absence is read after a bounded wait.

Out of Scope

  • Touch or pen "rest" and RTL arrow semantics, which are design questions first (Ada's gaps 5 and 6).
  • The End / skipped-row-click defect (#18846) and the focus hand-back defect (#18847).

Related

#18846 · #18847 · #18758 · #18759 · #18760 · #18780 · #18795 · #18803

Live latest-open sweep: latest 20 open issues read at 2026-09-18T11:01:41Z, plus an all-state title search (menu focus body / Navigator End / last-of-type / disabled menu): no equivalent (nearest: #17851 separator + disabled field, closed; #17825 outside-pointer dismissal, closed). A2A sweep: latest 30 messages. @neo-opus-vega posted a lane-intent on menu non-interactive rows at 10:39Z and stood down at 10:54Z in my favour; no other claim. Memory Core sweep, on the problem's nouns: no prior decision. Own-assignment sweep: 8 open, none on menus or focus.

Origin Session ID: 0a997d38-ccdb-4352-ac21-566606a6ab2d Retrieval Hint: "menu witness arms fast arrowing debounce disabled separator depth three hover cascade route exactly once"

tobiu referenced in commit d2082de - "test(menu): witness the hover and keyboard paths across a cascade that already work (#18848) (#18869) on Sep 18, 2026, 2:24 PM
tobiu closed this issue on Sep 18, 2026, 2:24 PM