diff options
Diffstat (limited to 'tests/gallery-probes/probe.mjs')
| -rw-r--r-- | tests/gallery-probes/probe.mjs | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/tests/gallery-probes/probe.mjs b/tests/gallery-probes/probe.mjs index 3db09a5..5f56f46 100644 --- a/tests/gallery-probes/probe.mjs +++ b/tests/gallery-probes/probe.mjs @@ -52,6 +52,36 @@ async function drag(x1, y1, x2, y2) { await send('Input.dispatchMouseEvent', { type: 'mouseReleased', x: x2, y: y2, button: 'left', clickCount: 1 }); } +// The page sets `html{scroll-behavior:smooth}`, so a plain scrollIntoView +// animates and a rect read mid-flight is stale by the time the drag dispatches. +// The press then lands off the widget and the check reports a widget bug. Scroll +// instantly instead: the probe has no reason to animate, and this removes the +// race rather than waiting it out. +const scrollTo = expr => + evl(`(${expr}).scrollIntoView({block:'center', behavior:'instant'}); ''`); + +// Belt and braces after the instant scroll: a zoom or column relayout can still +// move things for a frame or two, so read the geometry until it stops moving. +// Takes any numeric tuple (a full rect, or a centre point) and requires a stable +// value twice in a row AND a y inside the viewport, because two matching samples +// taken before a relayout starts would otherwise look settled. +async function settledGeom(expr, { tries = 40, gap = 25 } = {}) { + const height = await evl(`window.innerHeight`); + let prev = null; + for (let i = 0; i < tries; i++) { + const now = await evl(expr); + const onscreen = now[1] >= 0 && now[1] < height; + if (prev && onscreen && now.every((v, j) => Math.abs(v - prev[j]) < 0.5)) return now; + prev = now; + await sleep(gap); + } + return prev; +} + +// A press that misses reports as a dead widget, so name the real failure. +const hits = (x, y, sel) => + evl(`!!document.elementFromPoint(${x}, ${y})?.closest('${sel}')`); + const fails = []; const ok = (name, cond, detail = '') => { console.log(`${cond ? 'PASS' : 'FAIL'} ${name}${detail ? ' — ' + detail : ''}`); if (!cond) fails.push(name); }; @@ -195,19 +225,21 @@ try { // not 1/row: at one-per-row the card is wide enough that its controls fall // outside the 1600px probe window and the dispatched mouse events miss. await evl(`document.querySelector('.szbar .dupre-key[data-cols="2"]').click()`); - await evl(`document.querySelectorAll('.card')[2].scrollIntoView({block:'center'}); ''`); - await sleep(200); - const fr = await evl(`(()=>{const c=document.querySelectorAll('.card')[2];const f=c.querySelector('.dupre-fader');const r=f.getBoundingClientRect();return [r.left,r.top,r.width,r.height];})()`); + await scrollTo(`document.querySelectorAll('.card')[2]`); + const fr = await settledGeom(`(()=>{const c=document.querySelectorAll('.card')[2];const f=c.querySelector('.dupre-fader');const r=f.getBoundingClientRect();return [r.left,r.top,r.width,r.height];})()`); + const fx = fr[0] + fr[2] * 0.2, fy = fr[1] + fr[3] / 2; + ok('fader press lands on the fader', await hits(fx, fy, '.dupre-fader'), `at ${Math.round(fx)},${Math.round(fy)}`); const before = await evl(`document.getElementById('rd-03').textContent`); - await drag(fr[0] + fr[2] * 0.2, fr[1] + fr[3] / 2, fr[0] + fr[2] * 0.9, fr[1] + fr[3] / 2); + await drag(fx, fy, fr[0] + fr[2] * 0.9, fy); await sleep(150); const after = await evl(`document.getElementById('rd-03').textContent`); ok('fader drag tracks at 2/row', before !== after && after !== '—', `'${before}' -> '${after}'`); // 4. behavioral, zoomed: toggle click on card 01 - await evl(`document.querySelectorAll('.card')[0].scrollIntoView({block:'center'}); ''`); - await sleep(200); - const sw = await evl(`(()=>{const c=document.querySelectorAll('.card')[0];const s=c.querySelector('.switch')||c.querySelector('.stagew > *');const r=s.getBoundingClientRect();return [r.left+r.width/2,r.top+r.height/2];})()`); + await scrollTo(`document.querySelectorAll('.card')[0]`); + const sw = await settledGeom(`(()=>{const c=document.querySelectorAll('.card')[0];const s=c.querySelector('.switch')||c.querySelector('.stagew > *');const r=s.getBoundingClientRect();return [r.left+r.width/2,r.top+r.height/2];})()`); + ok('toggle press lands on the switch', await hits(sw[0], sw[1], '.card'), + `at ${Math.round(sw[0])},${Math.round(sw[1])}`); const t0 = await evl(`document.getElementById('rd-01').textContent`); await send('Input.dispatchMouseEvent', { type: 'mousePressed', x: sw[0], y: sw[1], button: 'left', clickCount: 1 }); await send('Input.dispatchMouseEvent', { type: 'mouseReleased', x: sw[0], y: sw[1], button: 'left', clickCount: 1 }); |
