CI green on a loaded shared machine: browser suites (now also glyph-ligatures and feature-fit, through the shared launch helper) in one dedicated shard started first at concurrency 2; timeouts scaled by load ÷ cores (tests/helpers/load.ts, max(1-, 5-min average), capped at 5x, logged) for browser tests, waits, launch/close, the other shards' default and the desktop boot check; one retry for a browser test that timed out while the factor was above 2, listed as 'retried under load' in the CI summary, never for an assertion failure; the six-type App Privacy walk no longer dumps every step (the --debug-dump check walks two types), wait timeouts print per-line times; play-edit-lock checks reads in flight instead of wall time; tests/load-retry.test.ts

This commit is contained in:
CRTkafa 2026-10-14 05:21:15 +08:00
parent 21fa91afd1
commit 918146d4a6
13 changed files with 261 additions and 96 deletions

View file

@ -18,7 +18,7 @@ import { parseArgs } from '../cli/lib/args';
import { type ShipConfig, validateExtras } from '../cli/lib/config';
import { AGE_RATING_API, consoleAnswers, consoleResult, fillValue, FORM_IDS, type FormId, formMeta } from '../cli/lib/console-answers';
import { consoleReached, CREATE_APP_OPENERS, createAppAllowed, formDef, FORM_OPENERS, forbiddenControl, hasToken, isSignInText, isSignInUrl, navAllowed, navPlan, playDeveloperId, switchAllowed } from '../cli/lib/console-forms';
import { AFTER_ALL_MS, AFTER_EACH_MS, launchTestBrowser, logLines, TEST_TICK_MS, TEST_WAITS, testScope } from './helpers/browser';
import { AFTER_ALL_MS, AFTER_EACH_MS, launchTestBrowser, logLines, scaled, TEST_TICK_MS, TEST_WAITS, testScope, WaitTimeout } from './helpers/browser';
const config: ShipConfig = {
app: { name: 'Example Game', profile: 'game', privacyPolicyUrl: 'https://example.com/privacy', supportUrl: 'https://example.com/support', website: 'https://example.com', contactEmail: 'support@example.com' },
@ -175,11 +175,11 @@ if (!browser) console.warn(`console-fill browser tests skipped: no Chromium inst
/** The contexts and engine runs of the current test, closed / awaited right after it (afterEach below). */
const scope = testScope(() => browser);
/** Browser tests: a few seconds each on an idle machine; the timeout leaves room for a loaded one. */
const BROWSER_TEST_MS = 30_000;
const BROWSER_TEST_MS = scaled(30_000);
/** SLOW tests (engine "not here" timeouts, Chromium relaunches): ~5-10 s idle. */
const SLOW_TEST_MS = 90_000;
const SLOW_TEST_MS = scaled(90_000);
/** Engine waits that are expected to SUCCEED: they return as soon as the element is there, so a long cap costs nothing. */
const FOUND_MS = 15_000;
const FOUND_MS = scaled(15_000);
const FIX = join(import.meta.dir, 'fixtures', 'console');
/** Console URLs of the navigation plans -> modeled pages (bases: asc = <base>asc, play = <base>play). */
@ -542,7 +542,7 @@ const tmpAccounts = () => { const d = mkdtempSync(join(tmpdir(), 'storebound-acc
* navTimeoutMs is how long a step that IS there may take to show up (headroom for a loaded machine); a step that is
* NOT there ends earlier, once its loaded page stays unchanged for TEST_WAITS.quietMs (tests/helpers/browser.ts).
*/
const fast = (log: ReturnType<typeof logLines>) => ({ say: log.say, tickMs: TEST_TICK_MS, navTimeoutMs: 5000, signInWaitMs: 30_000, accountsFile: tmpAccounts(), env: {} });
const fast = (log: ReturnType<typeof logLines>) => ({ say: log.say, tickMs: TEST_TICK_MS, navTimeoutMs: scaled(5000), signInWaitMs: 30_000, accountsFile: tmpAccounts(), env: {} });
const FILLED = (lines: string[]) => lines.some(m => /^New App: filled \d+/.test(m));
describe.skipIf(!browser)('sign-in and watching (headless, modeled pages on the real console hosts, routed locally)', () => {
@ -1004,10 +1004,10 @@ const playOgb = (u: URL): string | null => {
return u.pathname === '/console' || u.pathname === '/console/u/0/developers' ? 'play-chooser-ogb.html' : null;
};
const frameOn = (page: any, host: string): boolean => page.frames().some((f: any) => { try { return new URL(f.url()).hostname === host; } catch { return false; } });
/** Test helper: waits until `pred` holds (at most 10 s). */
/** Test helper: waits until `pred` holds (at most 10 s, scaled by the load). */
async function until(pred: () => boolean): Promise<void> {
const end = Date.now() + 10_000;
while (!pred()) { if (Date.now() > end) throw new Error('until: timed out'); await Bun.sleep(50); }
const end = Date.now() + scaled(10_000);
while (!pred()) { if (Date.now() > end) throw new WaitTimeout('until: timed out'); await Bun.sleep(50); }
}
describe.skipIf(!browser)('sign-in detection: only the top-level URL, the main frame\'s form or an Apple sign-in frame', () => {