Merge pull request 'test(windows-smoke): check the local server by connecting when sockets can't be listed' (#52) from fix/smoke-listen-check into main
Build Lotus Chat Desktop / prepare (push) Successful in 4s
Build Lotus Chat Desktop / build-linux (push) Successful in 14m31s
Build Lotus Chat Desktop / build-arch (push) Successful in 36s
Build Lotus Chat Desktop / checksums (push) Successful in 35s
Build Lotus Chat Desktop / build-windows (push) Successful in 34m48s
Build Lotus Chat Desktop / update-manifest (push) Successful in 5s

This commit was merged in pull request #52.
This commit is contained in:
2026-11-09 23:09:19 -05:00
+44 -4
View File
@@ -13,6 +13,8 @@
import { writeFileSync, mkdirSync } from 'node:fs';
import { execSync } from 'node:child_process';
import { createServer } from 'node:http';
import { connect } from 'node:net';
import { networkInterfaces } from 'node:os';
import { chromium } from 'playwright-core';
const OUT = process.argv[2] || 'smoke-out';
@@ -38,6 +40,19 @@ const until = async (fn, ms, step = 500) => {
}
};
// TCP connect probe: 'open', 'refused', 'timeout' or the socket error code.
const probe = (host, port, ms = 2000) =>
new Promise((resolve) => {
const socket = connect({ host, port });
const done = (result) => {
socket.destroy();
resolve(result);
};
socket.setTimeout(ms, () => done('timeout'));
socket.once('connect', () => done('open'));
socket.once('error', (e) => done(e.code === 'ECONNREFUSED' ? 'refused' : e.code || 'error'));
});
// 1. Connect to the running app's WebView2.
const browser = await until(() => chromium.connectOverCDP('http://127.0.0.1:9222'), 60_000, 1000);
if (!browser) {
@@ -61,15 +76,40 @@ record('boots to the login screen', booted ? 'pass' : 'fail');
await page.screenshot({ path: `${OUT}/01-login.png` });
// 3. The local server's address (cinny #43 binds 127.0.0.1 explicitly).
let listen = '';
try {
const listen = execSync(
listen = execSync(
'powershell -NoProfile -Command "(Get-NetTCPConnection -LocalPort 44548 -State Listen).LocalAddress -join \',\'"',
{ stdio: ['ignore', 'pipe', 'ignore'] },
)
.toString()
.trim();
record('local server listening', listen ? 'pass' : 'fail', listen);
} catch (e) {
record('local server listening', 'fail', String(e).slice(0, 120));
} catch {
listen = '';
}
if (listen) {
record('local server listening', 'pass', listen);
} else {
// Some runner sessions can't list sockets at all (Get-NetTCPConnection and
// netstat both come back empty, even for the DevTools port this script is
// connected to). Check what #43 is about directly instead: the server
// answers on loopback and is not reachable on the machine's LAN addresses.
const loopback = await probe('127.0.0.1', 44548);
const lan = Object.values(networkInterfaces())
.flat()
.filter((a) => a && a.family === 'IPv4' && !a.internal)
.map((a) => a.address);
const exposed = [];
for (const ip of lan) {
if ((await probe(ip, 44548)) === 'open') exposed.push(ip);
}
record(
'local server listening',
loopback === 'open' && exposed.length === 0 ? 'pass' : 'fail',
`socket list unavailable; 127.0.0.1: ${loopback}; LAN ${lan.join(', ') || 'none'}: ${
exposed.length ? `OPEN on ${exposed.join(', ')}` : 'not reachable'
}`,
);
}
const cfg = await page.evaluate(() => fetch('/config.json').then((r) => r.json()));