From 318b1bb4c2c4e8bdc1f29158629d8637146636de Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 14 Jun 2026 21:54:30 -0500 Subject: fix(theme-studio): make broken browser gates fail instead of silently passing run-tests.sh scored each browser gate by grepping the dumped DOM for the gate name and taking the first match. A gate that throws before setting its verdict left its own inlined source as the first match, and that source, "GATENAME '+(ok?'PASS':'FAIL')", contains the literal PASS, so the run reported green for a gate that never produced a verdict. The matcher now requires a resolved "GATENAME PASS" or "GATENAME FAIL". That exposed two gates that had been throwing unnoticed. baseedittest still referenced fam after the variable was renamed to column, so it ReferenceError'd. columntest read getComputedStyle on a palette chip captured before a re-render detached it, so the match returned null and threw. baseedittest now uses column, and columntest re-queries the live chip by its selection index. --- scripts/theme-studio/browser-gates.js | 12 ++++++++---- scripts/theme-studio/run-tests.sh | 2 +- scripts/theme-studio/theme-studio.html | 12 ++++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) (limited to 'scripts/theme-studio') diff --git a/scripts/theme-studio/browser-gates.js b/scripts/theme-studio/browser-gates.js index 41b459b63..fb828eaf8 100644 --- a/scripts/theme-studio/browser-gates.js +++ b/scripts/theme-studio/browser-gates.js @@ -488,11 +488,15 @@ if(location.hash==='#columntest'||location.hash==='#familytest'){let ok=true;con if(redChip){ const redName=redChip.querySelector('.nm');selectedIdx=null;redName.click(); A(selectedIdx!==null&&PALETTE[selectedIdx][1]==='red','single-clicking a tile name selects the whole tile'); - const chipHex=chip=>rgb2hex(...getComputedStyle(chip).backgroundColor.match(/\d+/g).slice(0,3).map(Number)); + // Re-query the chip from the live DOM each time: selecting re-renders the + // palette, so a node captured earlier is detached and getComputedStyle on it + // returns "" (match -> null). Look it up by the current selection index. + const liveChip=()=>document.querySelector('#pals .pchip[data-palette-index="'+selectedIdx+'"]'); + const chipHex=chip=>{const m=chip&&getComputedStyle(chip).backgroundColor.match(/\d+/g);return m?rgb2hex(...m.slice(0,3).map(Number)):null;}; openPicker();setHex('#00ff00'); - A(chipHex(redChip)==='#00ff00','picker edits preview on the selected palette chip'); + A(chipHex(liveChip())==='#00ff00','picker edits preview on the selected palette chip'); closePicker(); - A(chipHex(redChip)==='#c0402a'&&PALETTE[selectedIdx][0]==='#c0402a','closing picker restores selected chip without mutating palette'); + A(chipHex(liveChip())==='#c0402a'&&PALETTE[selectedIdx][0]==='#c0402a','closing picker restores selected chip without mutating palette'); A(redName.readOnly===true&&!redName.classList.contains('editing'),'single-clicking a tile name does not enter name edit mode'); redName.dispatchEvent(new MouseEvent('dblclick',{bubbles:true,cancelable:true})); A(redName.readOnly===false&&redName.classList.contains('editing'),'double-clicking a tile name enters edit mode'); @@ -602,7 +606,7 @@ if(location.hash==='#baseedittest'){let ok=true;const notes=[];const A=(c,n)=>{i updateColor(); const column=columnsFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).columns[0]; A(column&&column.members.some(m=>m.hex.toLowerCase()==='#3a8a8a'),'column base recolored to the new hex'); - A(fam&&fam.members.length===5,'count preserved (±2 → 5 members), got '+(fam&&fam.members.length)); + A(column&&column.members.length===5,'count preserved (±2 → 5 members), got '+(column&&column.members.length)); A(!new Set(PALETTE.map(p=>p[0].toLowerCase())).has('#67809c'),'old base removed from palette'); A(UIMAP['region'].bg.toLowerCase()==='#3a8a8a','a reference to the base followed to the new base hex'); // ground edit: select bg, change hex, MAP.bg follows diff --git a/scripts/theme-studio/run-tests.sh b/scripts/theme-studio/run-tests.sh index 2a6d332ac..2733b28df 100755 --- a/scripts/theme-studio/run-tests.sh +++ b/scripts/theme-studio/run-tests.sh @@ -70,7 +70,7 @@ else upper="$(echo "$t" | tr '[:lower:]' '[:upper:]')" res="$(timeout --kill-after=5 30 "$CHROME" --headless --no-sandbox --disable-gpu --user-data-dir="$PROF" \ --virtual-time-budget=8000 --dump-dom "file://$HERE/theme-studio.html#$t" 2>/dev/null \ - | grep -o "${upper}[^<]*" | head -1)" + | grep -oE "${upper} (PASS|FAIL)[^<]*" | head -1)" case "$res" in *PASS*) pass_msg "#$t" ;; *FAIL*) fail_msg "#$t -> $res" ;; diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html index 3df7609bb..5fb563863 100644 --- a/scripts/theme-studio/theme-studio.html +++ b/scripts/theme-studio/theme-studio.html @@ -2963,11 +2963,15 @@ if(location.hash==='#columntest'||location.hash==='#familytest'){let ok=true;con if(redChip){ const redName=redChip.querySelector('.nm');selectedIdx=null;redName.click(); A(selectedIdx!==null&&PALETTE[selectedIdx][1]==='red','single-clicking a tile name selects the whole tile'); - const chipHex=chip=>rgb2hex(...getComputedStyle(chip).backgroundColor.match(/\d+/g).slice(0,3).map(Number)); + // Re-query the chip from the live DOM each time: selecting re-renders the + // palette, so a node captured earlier is detached and getComputedStyle on it + // returns "" (match -> null). Look it up by the current selection index. + const liveChip=()=>document.querySelector('#pals .pchip[data-palette-index="'+selectedIdx+'"]'); + const chipHex=chip=>{const m=chip&&getComputedStyle(chip).backgroundColor.match(/\d+/g);return m?rgb2hex(...m.slice(0,3).map(Number)):null;}; openPicker();setHex('#00ff00'); - A(chipHex(redChip)==='#00ff00','picker edits preview on the selected palette chip'); + A(chipHex(liveChip())==='#00ff00','picker edits preview on the selected palette chip'); closePicker(); - A(chipHex(redChip)==='#c0402a'&&PALETTE[selectedIdx][0]==='#c0402a','closing picker restores selected chip without mutating palette'); + A(chipHex(liveChip())==='#c0402a'&&PALETTE[selectedIdx][0]==='#c0402a','closing picker restores selected chip without mutating palette'); A(redName.readOnly===true&&!redName.classList.contains('editing'),'single-clicking a tile name does not enter name edit mode'); redName.dispatchEvent(new MouseEvent('dblclick',{bubbles:true,cancelable:true})); A(redName.readOnly===false&&redName.classList.contains('editing'),'double-clicking a tile name enters edit mode'); @@ -3077,7 +3081,7 @@ if(location.hash==='#baseedittest'){let ok=true;const notes=[];const A=(c,n)=>{i updateColor(); const column=columnsFromPalette(PALETTE,{bg:MAP['bg'],fg:MAP['p']}).columns[0]; A(column&&column.members.some(m=>m.hex.toLowerCase()==='#3a8a8a'),'column base recolored to the new hex'); - A(fam&&fam.members.length===5,'count preserved (±2 → 5 members), got '+(fam&&fam.members.length)); + A(column&&column.members.length===5,'count preserved (±2 → 5 members), got '+(column&&column.members.length)); A(!new Set(PALETTE.map(p=>p[0].toLowerCase())).has('#67809c'),'old base removed from palette'); A(UIMAP['region'].bg.toLowerCase()==='#3a8a8a','a reference to the base followed to the new base hex'); // ground edit: select bg, change hex, MAP.bg follows -- cgit v1.2.3