From 165dabc5d7196f4786fb141e37337eedaef1ecef Mon Sep 17 00:00:00 2001 From: Matysh Date: Fri, 28 Aug 2026 07:36:34 +0300 Subject: [PATCH] test: restore lazy split mutation coverage Issue: #337 User-Visible: no --- demo/smoke_space_tab_reorder.mjs | 23 +++++++++++++++++++++++ scripts/mutation-gate.mjs | 6 +++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/demo/smoke_space_tab_reorder.mjs b/demo/smoke_space_tab_reorder.mjs index 25940792..a871e316 100644 --- a/demo/smoke_space_tab_reorder.mjs +++ b/demo/smoke_space_tab_reorder.mjs @@ -192,6 +192,29 @@ await settle(); await page.waitForTimeout(550); out.outsideReleaseEndedDrag = await page.evaluate(() => window.__card._tabDrag === null); out.outsideReleaseDidNotWrite = await writeCount() === writesBeforeOutside; + +// Exercise the window-level release fallback independently. Real mouse input +// normally grants pointer capture, which would route pointerup back to the +// source tab and let a missing window listener pass this regression. +const fallbackIds = await ids(); +const writesBeforeFallback = await writeCount(); +await holdDrag(fallbackIds.at(-1), fallbackIds[0]); +out.outsideFallbackReleasedCapture = await page.evaluate(() => { + const c = window.__card; + const drag = c._tabDrag; + const source = [...c.renderRoot.querySelectorAll('[data-hp="space-tab"]')] + .find((tab) => tab.dataset.id === drag?.id); + if (!source || !drag || !source.hasPointerCapture(drag.pointerId)) return false; + source.releasePointerCapture(drag.pointerId); + return !source.hasPointerCapture(drag.pointerId); +}); +await page.mouse.move(stagePoint.x, stagePoint.y, { steps: 3 }); +await page.mouse.up(); +await settle(); +await page.waitForTimeout(550); +out.outsideFallbackReleaseEndedDrag = await page.evaluate(() => window.__card._tabDrag === null); +out.outsideFallbackReleaseDidNotWrite = await writeCount() === writesBeforeFallback; + const activeBeforeRecovery = await page.evaluate(() => window.__card._space); const recoveryTarget = (await ids()).find((id) => id !== activeBeforeRecovery); const recoveryPoint = await tabPoint(recoveryTarget); diff --git a/scripts/mutation-gate.mjs b/scripts/mutation-gate.mjs index 178bd973..af64032d 100644 --- a/scripts/mutation-gate.mjs +++ b/scripts/mutation-gate.mjs @@ -3330,9 +3330,9 @@ const MUTANT_DEFINITIONS = [ because: 'Plan architecture ink is visual chrome; leaving the wall outline at raw SVG units ' + 'makes it five times thinner on a 1 cm grid (#239)', patches: [{ - file: 'src/houseplan-card.ts', - find: ' stroke="${stroke}" stroke-width="${gridVisualUnits(0.6, this._cellCm)}"', - replace: ' stroke="${stroke}" stroke-width="0.6"', + file: 'src/styles/plan.styles.ts', + find: ' stroke-width: calc(0.6px * var(--hp-cell-visual-scale, 1));', + replace: ' stroke-width: 0.6px;', }], }, {