style(ui): format shortcut and parameter components

This commit is contained in:
Sameh Khamis committed 2026-09-12 20:39:47 -07:00
1 parent 7a5f615d55
commit c9be877f9c
5 files changed
+262 -72

No files matched your search

+6 -1
View File
@@ -129,5 +129,10 @@
"src/ui/panelMeasurement.js",
"src/ui/panelRailGeometry.js",
"src/ui/panelRails.test.mjs",
"src/panelStackLayout.js"
"src/panelStackLayout.js",
"src/ui/applicationShortcuts.js",
"src/ui/styleParameters.js",
"src/ui/visualInput.js",
"src/ui/visualInput.test.mjs",
"scripts/qa-visual-input.mjs"
]
+122 -39
View File
@@ -5,7 +5,12 @@ import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', ...(process.platform === 'darwin' ? ['--use-angle=metal', '--enable-gpu'] : ['--use-gl=angle', '--use-angle=swiftshader'])],
args: [
'--no-sandbox',
...(process.platform === 'darwin'
? ['--use-angle=metal', '--enable-gpu']
: ['--use-gl=angle', '--use-angle=swiftshader']),
],
});
const page = await browser.newPage();
const errors = [];
@@ -20,64 +25,129 @@ try {
const url = new URL(process.env.QA_BASE_URL || 'http://127.0.0.1:4173');
url.searchParams.set('welcome', '0');
await page.goto(url.href, { waitUntil: 'domcontentloaded' });
await page.waitForFunction(() => window.__godsEyeView?.styleManager?._applicationShortcuts, { timeout: 60_000 });
await page.waitForFunction(() => {
const cover = document.getElementById('loading-screen');
return cover?.classList.contains('hidden') && Number(getComputedStyle(cover).opacity) === 0;
}, { timeout: 60_000 });
await page.waitForFunction(
() => window.__godsEyeView?.styleManager?._applicationShortcuts,
{ timeout: 60_000 },
);
await page.waitForFunction(
() => {
const cover = document.getElementById('loading-screen');
return (
cover?.classList.contains('hidden') &&
Number(getComputedStyle(cover).opacity) === 0
);
},
{ timeout: 60_000 },
);
await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
manager.setStyle('normal');
document.activeElement?.blur();
});
await page.keyboard.press('2');
check('native number shortcut selects CRT', await page.evaluate(() => window.__godsEyeView.styleManager.activeStyle === 'retro'));
check(
'native number shortcut selects CRT',
await page.evaluate(
() => window.__godsEyeView.styleManager.activeStyle === 'retro',
),
);
const initial = await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
manager.setPanelCollapsed('pp-toggles', false, { persist: false, syncShare: false });
manager.setPanelCollapsed('pp-toggles', false, {
persist: false,
syncShare: false,
});
manager._sliderPanel.classList.remove('collapsed');
const slider = manager._sliderContainer.querySelector('input');
window.__qaOldSlider = slider;
const name = 'pixelation';
window.__qaParameter = { name, before: manager.stages.retro.uniforms[name] };
window.__qaParameter = {
name,
before: manager.stages.retro.uniforms[name],
};
slider.focus();
return { before: Number(slider.value), step: Number(slider.step), label: slider.getAttribute('aria-label') };
return {
before: Number(slider.value),
step: Number(slider.step),
label: slider.getAttribute('aria-label'),
};
});
check('generated range has an accessible label and a numeric step', initial.label === 'Pixelation' && initial.step > 0);
check(
'generated range has an accessible label and a numeric step',
initial.label === 'Pixelation' && initial.step > 0,
);
await page.keyboard.press('ArrowRight');
const changed = await page.evaluate(() => {
const slider = window.__qaOldSlider;
const manager = window.__godsEyeView.styleManager;
return { value: Number(slider.value), readout: slider.nextElementSibling.textContent, uniform: manager.stages.retro.uniforms[window.__qaParameter.name] };
return {
value: Number(slider.value),
readout: slider.nextElementSibling.textContent,
uniform: manager.stages.retro.uniforms[window.__qaParameter.name],
};
});
check('native range input changes the shader and formatted readout', changed.value > initial.before && changed.uniform === changed.value && Number(changed.readout) === changed.value);
check(
'native range input changes the shader and formatted readout',
changed.value > initial.before &&
changed.uniform === changed.value &&
Number(changed.readout) === changed.value,
);
await page.keyboard.press('3');
check('focused range retains native input instead of changing style', await page.evaluate(() => window.__godsEyeView.styleManager.activeStyle === 'retro'));
check('replacing a style revokes its detached slider', await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
const before = manager.stages.retro.uniforms[window.__qaParameter.name];
manager.setStyle('thermal');
window.__qaOldSlider.value = '0';
window.__qaOldSlider.dispatchEvent(new Event('input', { bubbles: true }));
return manager.stages.retro.uniforms[window.__qaParameter.name] === before;
}));
check('normal style clears rows; reopening restores current shader values', await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
manager.setStyle('normal');
const cleared = manager._sliderContainer.children.length === 0;
manager.setStyle('retro');
return cleared && Number(manager._sliderContainer.querySelector('input').value) === manager.stages.retro.uniforms[window.__qaParameter.name];
}));
check(
'focused range retains native input instead of changing style',
await page.evaluate(
() => window.__godsEyeView.styleManager.activeStyle === 'retro',
),
);
check(
'replacing a style revokes its detached slider',
await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
const before = manager.stages.retro.uniforms[window.__qaParameter.name];
manager.setStyle('thermal');
window.__qaOldSlider.value = '0';
window.__qaOldSlider.dispatchEvent(new Event('input', { bubbles: true }));
return (
manager.stages.retro.uniforms[window.__qaParameter.name] === before
);
}),
);
check(
'normal style clears rows; reopening restores current shader values',
await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
manager.setStyle('normal');
const cleared = manager._sliderContainer.children.length === 0;
manager.setStyle('retro');
return (
cleared &&
Number(manager._sliderContainer.querySelector('input').value) ===
manager.stages.retro.uniforms[window.__qaParameter.name]
);
}),
);
const hudBefore = await page.evaluate(() => {
document.getElementById('hud-layout-select').focus();
return window.__godsEyeView.styleManager.hud.visible;
});
await page.keyboard.press('h');
check('HUD select keeps its native typing and selection', await page.evaluate((visible) => document.activeElement?.id === 'hud-layout-select' && window.__godsEyeView.styleManager.hud.visible === visible, hudBefore));
check(
'HUD select keeps its native typing and selection',
await page.evaluate(
(visible) =>
document.activeElement?.id === 'hud-layout-select' &&
window.__godsEyeView.styleManager.hud.visible === visible,
hudBefore,
),
);
fs.mkdirSync('qa-shots/visual-input', { recursive: true });
await page.screenshot({ path: 'qa-shots/visual-input/desktop.png' });
await page.setViewport({ width: 620, height: 900 });
await page.waitForFunction(() => document.getElementById('left-panel-stack')?.dataset.layoutMode === 'mobile');
await page.waitForFunction(
() =>
document.getElementById('left-panel-stack')?.dataset.layoutMode ===
'mobile',
);
await page.screenshot({ path: 'qa-shots/visual-input/narrow.png' });
await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
@@ -87,14 +157,27 @@ try {
document.activeElement?.blur();
});
await page.keyboard.press('3');
check('destroyed application shortcuts cannot change the selected style', await page.evaluate(() => window.__godsEyeView.styleManager.activeStyle === 'retro'));
check('destroyed parameter controls cannot write through a retained element', await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
const before = manager.stages.retro.uniforms[window.__qaParameter.name];
window.__qaCurrentSlider.value = '0';
window.__qaCurrentSlider.dispatchEvent(new Event('input', { bubbles: true }));
return manager._sliderContainer.children.length === 0 && manager.stages.retro.uniforms[window.__qaParameter.name] === before;
}));
check(
'destroyed application shortcuts cannot change the selected style',
await page.evaluate(
() => window.__godsEyeView.styleManager.activeStyle === 'retro',
),
);
check(
'destroyed parameter controls cannot write through a retained element',
await page.evaluate(() => {
const manager = window.__godsEyeView.styleManager;
const before = manager.stages.retro.uniforms[window.__qaParameter.name];
window.__qaCurrentSlider.value = '0';
window.__qaCurrentSlider.dispatchEvent(
new Event('input', { bubbles: true }),
);
return (
manager._sliderContainer.children.length === 0 &&
manager.stages.retro.uniforms[window.__qaParameter.name] === before
);
}),
);
check('runtime has no uncaught browser errors', errors.length === 0);
} finally {
await browser.close();