From f10a69ad19e1bc853529c6f18e00119420e7d186 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Thu, 22 Oct 2026 21:15:10 -0400 Subject: [PATCH] ci(windows-smoke): visibility and hotkey checks need an interactive desktop The windows runner can't show a hidden window or inject keys (no interactive desktop: even a direct show() leaves it hidden). Check that first; the deep link must still reach the page and un-minimise, but window visibility and the global-hotkey round trip are n/a on such a runner. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5 --- scripts/windows-smoke.mjs | 41 +++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/scripts/windows-smoke.mjs b/scripts/windows-smoke.mjs index 552eb45..c071157 100644 --- a/scripts/windows-smoke.mjs +++ b/scripts/windows-smoke.mjs @@ -201,6 +201,25 @@ await page.evaluate(() => { window.__deeplinks = []; window.addEventListener('lotus-deeplink', (e) => window.__deeplinks.push(e.detail)); }); +// Can this machine show a hidden window at all? A runner without an +// interactive desktop (e.g. act_runner as a Windows service, session 0) can't, +// and can't inject keys either. Then visibility and hotkeys are reported n/a +// instead of failing for a reason that isn't the app's. +let interactive = false; +try { + await win('hide'); + await new Promise((r) => setTimeout(r, 1000)); + await win('show'); + await new Promise((r) => setTimeout(r, 1000)); + interactive = await win('is_visible'); +} catch { + interactive = false; +} +record( + 'interactive desktop (windows can be shown, keys injected)', + interactive ? 'pass' : 'info', + interactive ? 'yes' : 'no: visibility and hotkey checks are n/a on this runner', +); for (const [state, put] of [ ['hidden to the tray', 'hide'], ['minimised', 'minimize'], @@ -218,29 +237,19 @@ for (const [state, put] of [ ); const visible = await win('is_visible'); const minimised = await win('is_minimized'); - const ok = away && got && visible && !minimised; + const delivered = away && got && !minimised; + const ok = delivered && (visible || !interactive); record( name, ok ? 'pass' : 'fail', - `${state} first: ${away}; event: ${!!got}; visible after: ${visible}; minimised after: ${minimised}`, + `${state} first: ${away}; event: ${!!got}; minimised after: ${minimised}; visible after: ${visible}${ + interactive ? '' : ' (not checked: no interactive desktop)' + }`, ); } catch (e) { record(name, 'fail', String(e).slice(0, 200)); } } -// Control for #8: can this machine show a hidden window at all? (A runner -// without an interactive desktop can't, and that isn't the app's fault.) -try { - await win('hide'); - await new Promise((r) => setTimeout(r, 1000)); - await win('show'); - await new Promise((r) => setTimeout(r, 1000)); - const shown = await win('is_visible'); - record('control: a hidden window can be shown again', shown ? 'pass' : 'info', `visible after show(): ${shown}`); -} catch (e) { - record('control: a hidden window can be shown again', 'info', String(e).slice(0, 160)); -} - // 9. System-wide voice hotkeys (#2): register PTT on F9, press and release F9 // through Windows (keybd_event, as a game in front would see it), expect a // pressed and a released `lotus-global-hotkey`; after clearing the bindings @@ -264,6 +273,8 @@ try { ); if (!supported) { record('global hotkeys reach the page', 'fail', 'global_hotkeys_supported = false on Windows'); + } else if (!interactive) { + record('global hotkeys reach the page', 'n/a', 'no interactive desktop: injected keys never reach GetAsyncKeyState'); } else { await page.evaluate(async () => { window.__hotkeys = [];