diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-12 20:48:41 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-12 20:48:41 -0500 |
| commit | e66c60c5a7f66be08d017cefac80e557ced0c957 (patch) | |
| tree | cb798585a4a0096be116e8ddd365c589c037ec08 /tests/gallery-probes/probe-fams.mjs | |
| parent | f2cd7b4a97a28f1df58d3258f17d01b6f142e5a2 (diff) | |
| download | archsetup-e66c60c5a7f66be08d017cefac80e557ced0c957.tar.gz archsetup-e66c60c5a7f66be08d017cefac80e557ced0c957.zip | |
test(gallery): commit the CDP behavioral probes
The full-regression and screen-family probes lived in session scratch; the widgets.js extraction uses them as its per-batch no-regression gate, so they become repo tooling.
Diffstat (limited to 'tests/gallery-probes/probe-fams.mjs')
| -rw-r--r-- | tests/gallery-probes/probe-fams.mjs | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/gallery-probes/probe-fams.mjs b/tests/gallery-probes/probe-fams.mjs new file mode 100644 index 0000000..08ac709 --- /dev/null +++ b/tests/gallery-probes/probe-fams.mjs @@ -0,0 +1,63 @@ +// Verify screen-family chips: presence, default fallbacks intact, live recolor on click. +import { spawn } from 'node:child_process'; +import { writeFileSync } from 'node:fs'; +const PORT = 9335; +const URL = 'file:///home/cjennings/code/archsetup/docs/prototypes/panel-widget-gallery.html'; +const chrome = spawn('google-chrome-stable', ['--headless=new', `--remote-debugging-port=${PORT}`, '--no-first-run', '--window-size=1600,1200', URL], { stdio: 'ignore' }); +const sleep = ms => new Promise(r => setTimeout(r, ms)); +let ws, id = 0; const pending = new Map(); const events = []; +for (let i = 0; i < 40; i++) { try { const l = await (await fetch(`http://127.0.0.1:${PORT}/json`)).json(); const p = l.find(t => t.type === 'page' && t.url.startsWith('file')); if (p) { ws = new WebSocket(p.webSocketDebuggerUrl); break; } } catch {} await sleep(250); } +await new Promise(r => ws.onopen = r); +ws.onmessage = m => { const d = JSON.parse(m.data); if (d.id && pending.has(d.id)) { pending.get(d.id)(d); pending.delete(d.id); } else if (d.method) events.push(d); }; +const send = (method, params = {}) => new Promise(res => { const i = ++id; pending.set(i, res); ws.send(JSON.stringify({ id: i, method, params })); }); +const evl = async e => { const r = await send('Runtime.evaluate', { expression: e, returnByValue: true }); if (r.result.exceptionDetails) throw new Error(JSON.stringify(r.result.exceptionDetails)); return r.result.result.value; }; +const fails = []; +const ok = (n, c, d = '') => { console.log(`${c ? 'PASS' : 'FAIL'} ${n}${d ? ' — ' + d : ''}`); if (!c) fails.push(n); }; +await send('Runtime.enable'); await sleep(1500); + +ok('no exceptions on load', events.filter(e => e.method === 'Runtime.exceptionThrown').length === 0); +ok('5 chip rows', await evl(`document.querySelectorAll('.famchips').length`) === 5); + +// default fallback: dmx ink computes to gold-hi rgb(255,190,84) +const dmxFill0 = await evl(`getComputedStyle(document.querySelector('#dmx text')).fill`); +ok('R10 default ink = gold-hi', dmxFill0 === 'rgb(255, 190, 84)', dmxFill0); + +// click green chip on R10 -> ink becomes phos rgb(127,224,160) +await evl(`document.querySelector('#dmx').closest('.card').querySelector('.fc[title="green"]').click()`); +const dmxFill1 = await evl(`getComputedStyle(document.querySelector('#dmx text')).fill`); +ok('R10 green chip recolors ink', dmxFill1 === 'rgb(127, 224, 160)', dmxFill1); + +// radar: default sweep line = gold-hi; click green -> phos +const swSel = `document.querySelector('#radar').closest('.card')`; +const line0 = await evl(`getComputedStyle(document.querySelectorAll('#radar line')[0]).stroke`); +await evl(`${swSel}.querySelector('.fc[title="green"]').click()`); +const line1 = await evl(`getComputedStyle(document.querySelectorAll('#radar line')[0]).stroke`); +ok('R31 green chip recolors furniture', line0 !== line1 && line1 === 'rgb(88, 184, 126)', `${line0} -> ${line1}`); + +// scope (CSS widget): trace stroke changes on amber chip +const tr0 = await evl(`getComputedStyle(document.querySelector('.scope polyline')).stroke`); +await evl(`document.querySelector('.scope').closest('.card').querySelector('.fc[title="amber"]').click()`); +const tr1 = await evl(`getComputedStyle(document.querySelector('.scope polyline')).stroke`); +ok('N11 amber chip recolors trace', tr0 !== tr1 && tr1 === 'rgb(255, 190, 84)', `${tr0} -> ${tr1}`); + +// R19: drag still works after family switch (click vfd, then check setWregion writes var-based fills) +await evl(`document.querySelector('#wregion').closest('.card').querySelector('.fc[title="vfd"]').click()`); +await evl(`setWregion(30,70)`); +const barFill = await evl(`(()=>{const b=document.querySelectorAll('#wregion rect')[10];return b.getAttribute('fill');})()`); +ok('R19 dynamic fills use vars', barFill.startsWith('var(--scr-'), barFill); + +// R17: face gradient stop resolves to amber face after chip +await evl(`document.querySelector('#rcrt').closest('.card').querySelector('.fc[title="amber"]').click()`); +const face = await evl(`getComputedStyle(document.querySelector('#rcrtFace stop')).stopColor`); +ok('R17 amber chip retints face', face === 'rgb(216, 203, 166)', face); + +ok('no exceptions after chip clicks', events.filter(e => e.method === 'Runtime.exceptionThrown').length === 0); + +// screenshot the recolored screens region (scroll R31 into view) +await evl(`document.querySelector('#radar').scrollIntoView({block:'center'})`); +await sleep(400); +const shot = await send('Page.captureScreenshot', { format: 'png' }); +writeFileSync('fams.png', Buffer.from(shot.result.data, 'base64')); +console.log('shot: fams.png'); +chrome.kill(); +process.exit(fails.length ? 1 : 0); |
