Merge pull request 'ci(windows-smoke): deep links while hidden/minimised, global hotkeys (#8, #2)' (#43) from ci/smoke-deeplink into main
Build Lotus Chat Desktop / prepare (push) Successful in 2s
Build Lotus Chat Desktop / build-windows (push) Successful in 29m19s
Build Lotus Chat Desktop / build-linux (push) Successful in 31m47s
Build Lotus Chat Desktop / build-arch (push) Successful in 17s
Build Lotus Chat Desktop / update-manifest (push) Successful in 3s
Build Lotus Chat Desktop / checksums (push) Successful in 13s
Build Lotus Chat Desktop / prepare (push) Successful in 2s
Build Lotus Chat Desktop / build-windows (push) Successful in 29m19s
Build Lotus Chat Desktop / build-linux (push) Successful in 31m47s
Build Lotus Chat Desktop / build-arch (push) Successful in 17s
Build Lotus Chat Desktop / update-manifest (push) Successful in 3s
Build Lotus Chat Desktop / checksums (push) Successful in 13s
This commit was merged in pull request #43.
This commit is contained in:
+129
-1
@@ -3,7 +3,8 @@
|
|||||||
// The app is started with WebView2's DevTools port open
|
// The app is started with WebView2's DevTools port open
|
||||||
// (WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9222) and this
|
// (WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9222) and this
|
||||||
// script drives its real page over CDP with playwright-core. No login: every
|
// script drives its real page over CDP with playwright-core. No login: every
|
||||||
// check runs on the login screen or through the app's own Tauri commands.
|
// check runs on the login screen or through the app's own Tauri commands
|
||||||
|
// (including a `matrix:` deep link while hidden/minimised, #8).
|
||||||
//
|
//
|
||||||
// node scripts/windows-smoke.mjs <outDir>
|
// node scripts/windows-smoke.mjs <outDir>
|
||||||
//
|
//
|
||||||
@@ -184,6 +185,133 @@ if (!page.url().startsWith(FOREIGN)) {
|
|||||||
}
|
}
|
||||||
foreign.close();
|
foreign.close();
|
||||||
await page.goto(APP).catch(() => undefined);
|
await page.goto(APP).catch(() => undefined);
|
||||||
|
await until(async () => /Login|Homeserver/.test(await page.locator('body').innerText()), 60_000);
|
||||||
|
|
||||||
|
// 8. A `matrix:` link opened from Windows while the window is hidden to the
|
||||||
|
// tray, then while minimised, must bring the window back AND reach the page
|
||||||
|
// as `lotus-deeplink` (#8). It goes the real route: Windows' protocol handler
|
||||||
|
// starts a second cinny.exe, and single-instance forwards the URL to this one.
|
||||||
|
// (Turning the URL into a room navigation is the web app's job, signed in.)
|
||||||
|
const win = (cmd) =>
|
||||||
|
page.evaluate(
|
||||||
|
([c]) => window.__TAURI_INTERNALS__.invoke(`plugin:window|${c}`, { label: 'main' }),
|
||||||
|
[cmd],
|
||||||
|
);
|
||||||
|
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'],
|
||||||
|
]) {
|
||||||
|
const name = `deep link while ${state} reveals the window and reaches the page`;
|
||||||
|
const url = `matrix:r/lotus-smoke-${put}:example.org`;
|
||||||
|
try {
|
||||||
|
await win(put);
|
||||||
|
await new Promise((r) => setTimeout(r, 1500));
|
||||||
|
const away = put === 'hide' ? !(await win('is_visible')) : await win('is_minimized');
|
||||||
|
execSync(`cmd /c start "" "${url}"`);
|
||||||
|
const got = await until(
|
||||||
|
() => page.evaluate((u) => window.__deeplinks.includes(u), url),
|
||||||
|
20_000,
|
||||||
|
);
|
||||||
|
const visible = await win('is_visible');
|
||||||
|
const minimised = await win('is_minimized');
|
||||||
|
const delivered = away && got && !minimised;
|
||||||
|
const ok = delivered && (visible || !interactive);
|
||||||
|
record(
|
||||||
|
name,
|
||||||
|
ok ? 'pass' : 'fail',
|
||||||
|
`${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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
// the same key must produce nothing (the poll stopped).
|
||||||
|
const pressScript = `${OUT}/press-f9.ps1`;
|
||||||
|
writeFileSync(
|
||||||
|
pressScript,
|
||||||
|
[
|
||||||
|
'Add-Type -Name K -Namespace W -MemberDefinition @"',
|
||||||
|
'[DllImport("user32.dll")] public static extern void keybd_event(byte v, byte s, uint f, System.UIntPtr e);',
|
||||||
|
'"@',
|
||||||
|
'[W.K]::keybd_event(0x78, 0, 0, [System.UIntPtr]::Zero)',
|
||||||
|
'Start-Sleep -Milliseconds 300',
|
||||||
|
'[W.K]::keybd_event(0x78, 0, 2, [System.UIntPtr]::Zero)',
|
||||||
|
].join('\r\n'),
|
||||||
|
);
|
||||||
|
const pressF9 = () => execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${pressScript}"`);
|
||||||
|
try {
|
||||||
|
const supported = await page.evaluate(() =>
|
||||||
|
window.__TAURI_INTERNALS__.invoke('global_hotkeys_supported'),
|
||||||
|
);
|
||||||
|
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 = [];
|
||||||
|
window.addEventListener('lotus-global-hotkey', (e) => window.__hotkeys.push(e.detail));
|
||||||
|
await window.__TAURI_INTERNALS__.invoke('set_global_hotkeys', {
|
||||||
|
bindings: [{ id: 'ptt', code: 'F9' }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
await new Promise((r) => setTimeout(r, 500));
|
||||||
|
pressF9();
|
||||||
|
const seen = await until(
|
||||||
|
() =>
|
||||||
|
page.evaluate(() => {
|
||||||
|
const h = window.__hotkeys.map((e) => `${e.id}:${e.state}`);
|
||||||
|
return h.includes('ptt:pressed') && h.includes('ptt:released') ? h : undefined;
|
||||||
|
}),
|
||||||
|
5_000,
|
||||||
|
250,
|
||||||
|
);
|
||||||
|
await page.evaluate(() =>
|
||||||
|
window.__TAURI_INTERNALS__.invoke('set_global_hotkeys', { bindings: [] }),
|
||||||
|
);
|
||||||
|
const before = await page.evaluate(() => window.__hotkeys.length);
|
||||||
|
pressF9();
|
||||||
|
await new Promise((r) => setTimeout(r, 1500));
|
||||||
|
const after = await page.evaluate(() => window.__hotkeys.length);
|
||||||
|
record(
|
||||||
|
'global hotkeys reach the page, and stop when cleared',
|
||||||
|
seen && after === before ? 'pass' : 'fail',
|
||||||
|
`events: ${JSON.stringify(seen ?? (await page.evaluate(() => window.__hotkeys)))}; after clearing: ${after - before} more`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const msg = String(e).slice(0, 200);
|
||||||
|
record('global hotkeys reach the page', /not found/i.test(msg) ? 'n/a' : 'fail', msg);
|
||||||
|
}
|
||||||
|
|
||||||
await page.screenshot({ path: `${OUT}/02-end.png` }).catch(() => undefined);
|
await page.screenshot({ path: `${OUT}/02-end.png` }).catch(() => undefined);
|
||||||
|
|
||||||
writeFileSync(`${OUT}/results.json`, JSON.stringify(results, null, 2));
|
writeFileSync(`${OUT}/results.json`, JSON.stringify(results, null, 2));
|
||||||
|
|||||||
Reference in New Issue
Block a user