LearnNewsExamplesServices
Frontmatter
id12807
titleMake Neo column-DnD (Mouse.mjs sensor) whitebox-e2e-simulatable
stateClosed
labels
enhancementaitestingmodel-experience
assigneesneo-opus-ada
createdAtJun 9, 2026, 4:12 AM
updatedAtJun 11, 2026, 10:08 PM
githubUrlhttps://github.com/neomjs/neo/issues/12807
authorneo-opus-ada
commentsCount13
parentIssuenull
subIssues
12898 Locked-column DnD whitebox substrate: spec scaffold, DOM-layer proof, worker-oracle design
subIssuesCompleted1
subIssuesTotal1
blockedBy[x] 12897 neuralLink connectToApp binds to wrong App Worker, not the test''s page
blocking[]
closedAtJun 11, 2026, 10:08 PM

Make Neo column-DnD (Mouse.mjs sensor) whitebox-e2e-simulatable

Closed v13.0.0/archive-v13-0-0-chunk-17 enhancementaitestingmodel-experience
neo-opus-ada
neo-opus-ada commented on Jun 9, 2026, 4:12 AM

Context

Surfaced during #9491 / PR #12792 whitebox-e2e (operator-greenlit: "if NL does not give you the tools you need, create new tickets"). To verify the cross-toolbar column drag-and-drop re-homes the full column, I needed to simulate a column drag in e2e. I could not: the sanctioned nlApp.simulateEvent path cannot dispatch pointer events, and Neo's drag is pointer-based — so no pointer-drag (SortZone column DnD, draggable dashboards, sort zones) can currently be driven from a whitebox-e2e test.

The Problem

Neo's drag pipeline = real pointer input → Neo.main.DomEvents → synthesized drag:start / drag:move / drag:end custom events → DragDrop addon + the worker SortZone. The whitebox-e2e simulateEvent fixture dispatches through Neo.main.addon.EventSimulator.dispatch(), which constructs events by type but has no PointerEvent branchpointerdown / pointermove / pointerup fall to the generic Event ctor (no pointer semantics, no clientX). So drag:start never arms.

Empirically (this session): three approaches — Playwright page.mouse (CDP coords) on the unstyled grid, simulateEvent mouse events, and page.mouse on the styled grid — all dispatched but none armed drag:start (mid-drag screenshot showed no drag proxy; column.locked stayed null). The column re-home itself is sound — verified via setProperties({locked}), which exercises the same onColumnLockChange redistribution path onDragEnd triggers. Only the pointer gesture is un-simulatable.

The Architectural Reality

  • src/main/addon/EventSimulator.mjsdispatch() switch (type) covers mouse / touch / drag(HTML5 DragEvent) / key / input / wheel; no case 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel'default: ctor = Event.
  • src/main/addon/DragDrop.mjs:186-188document.addEventListener('drag:start' | 'drag:move' | 'drag:end', …, true); these drag:* events are synthesized upstream from real pointer input.
  • learn/guides/testing/WhiteboxE2E.md (~line 126) explicitly claims simulateEvent is the path for "Grid locked columns" drag — a doc overclaim: it can dispatch a click, not a pointer-drag.

The Fix

Add case 'pointerdown' | 'pointermove' | 'pointerup' | 'pointercancel' to EventSimulator.dispatch() using new PointerEvent(type, options) (options carrying pointerId, clientX, clientY, buttons, bubbles). Verify a dispatched pointer sequence arms Neo's drag:* pipeline end-to-end. Correct the WhiteboxE2E guide to match real capability + add a worked DnD-drag example.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
simulate_event event type (nlApp.simulateEventEventSimulator.dispatch) src/main/addon/EventSimulator.mjs accept pointerdown/pointermove/pointerup/pointercancelnew PointerEvent(type, options) today: silently builds a generic Event (no pointer semantics) learn/guides/testing/WhiteboxE2E.md EventSimulator switch has no pointer case; #9491 drag-sim failures (no drag:start)

Decision Record impact

none — no ADR governs EventSimulator.

Acceptance Criteria

  • EventSimulator.dispatch() supports pointerdown/pointermove/pointerup/pointercancel via PointerEvent with positional + pointer options.
  • A whitebox-e2e pointer sequence (pointerdown → pointermove×N → pointerup) arms Neo's drag:start (drag proxy appears) and drives a SortZone column re-home (column.locked changes region). Risk/falsifier: if synthetic PointerEvents still do not arm drag:*, the gap is deeper in DomEvents — this AC surfaces that; escalate with the finding rather than declaring done.
  • The #9491 scaffold test/playwright/e2e/GridColumnCrossBodyDnD.spec.mjs completes (full column header + cells re-homes across toolbars).
  • learn/guides/testing/WhiteboxE2E.md updated: real pointer-drag capability + worked example; the unbacked "Grid locked columns" drag claim removed or backed.

Out of Scope

  • Neo's drag pipeline itself (DomEvents / DragDrop) — only the simulation tooling.
  • The column-DnD feature logic (#9491 / PR #12792).

Related

  • #9491 / PR #12792 — the cross-toolbar DnD e2e this unblocks (scaffold test/playwright/e2e/GridColumnCrossBodyDnD.spec.mjs is ready to consume the fix).
  • learn/guides/testing/WhiteboxE2E.md — doc to correct.

Origin Session ID: 31325e4f-0fdf-4627-96ed-7983dd1b1002

Retrieval Hint: "EventSimulator PointerEvent whitebox-e2e SortZone drag arming" / src/main/addon/EventSimulator.mjs dispatch() switch.

Authored by Claude Opus 4.8 (Claude Code), @neo-opus-ada.

tobiu referenced in commit e1eae16 - "test(grid): locked-column DnD whitebox-e2e — landing + cross-region re-home (#12807) (#12893) on Jun 11, 2026, 2:42 PM