ccqa 1.45.0 → 1.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/ccqa.mjs +57 -9
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/bin/ccqa.mjs
CHANGED
|
@@ -7167,6 +7167,7 @@ async function startBrowserCoverage(opts) {
|
|
|
7167
7167
|
var Engine = class {
|
|
7168
7168
|
client;
|
|
7169
7169
|
connectFn;
|
|
7170
|
+
/** Last known address of the browser; see `refreshWsUrl`. */
|
|
7170
7171
|
wsUrl;
|
|
7171
7172
|
reconnects = 0;
|
|
7172
7173
|
reconnectInFlight = false;
|
|
@@ -7285,6 +7286,22 @@ var Engine = class {
|
|
|
7285
7286
|
this.stopped = true;
|
|
7286
7287
|
this.clearTimer();
|
|
7287
7288
|
}
|
|
7289
|
+
/**
|
|
7290
|
+
* Answers why the address could not be refreshed, so the retry that follows
|
|
7291
|
+
* says whether it is dialling a stale address or a dead browser. Told apart
|
|
7292
|
+
* because one is a driver to fix and the other is a browser to wait for, and
|
|
7293
|
+
* a silent stale address is the shape of the bug this exists to prevent.
|
|
7294
|
+
*/
|
|
7295
|
+
async refreshWsUrl() {
|
|
7296
|
+
const ask = this.opts.currentCdpUrl;
|
|
7297
|
+
if (ask === void 0) return void 0;
|
|
7298
|
+
try {
|
|
7299
|
+
this.wsUrl = await browserWebSocketUrl(await ask());
|
|
7300
|
+
return;
|
|
7301
|
+
} catch (error) {
|
|
7302
|
+
return message(error);
|
|
7303
|
+
}
|
|
7304
|
+
}
|
|
7288
7305
|
async reconnect(initialReason) {
|
|
7289
7306
|
if (this.reconnectInFlight) return;
|
|
7290
7307
|
this.reconnectInFlight = true;
|
|
@@ -7300,11 +7317,12 @@ var Engine = class {
|
|
|
7300
7317
|
this.opts.warn(`browser coverage transport dropped (${reason}); reconnecting in ${delay}ms (${this.reconnects}/${MAX_RECONNECTS})`);
|
|
7301
7318
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
7302
7319
|
if (this.stopped) return;
|
|
7320
|
+
const stale = await this.refreshWsUrl();
|
|
7303
7321
|
let fresh;
|
|
7304
7322
|
try {
|
|
7305
7323
|
fresh = await this.connectFn(this.wsUrl);
|
|
7306
7324
|
} catch (error) {
|
|
7307
|
-
reason = `reconnect failed: ${message(error)}`;
|
|
7325
|
+
reason = stale ? `reconnect failed: ${message(error)} (address may be stale: ${stale})` : `reconnect failed: ${message(error)}`;
|
|
7308
7326
|
continue;
|
|
7309
7327
|
}
|
|
7310
7328
|
if (this.stopped) {
|
|
@@ -7319,6 +7337,7 @@ var Engine = class {
|
|
|
7319
7337
|
reason = `reconnect failed: ${message(error)}`;
|
|
7320
7338
|
continue;
|
|
7321
7339
|
}
|
|
7340
|
+
this.reconnects = 0;
|
|
7322
7341
|
if (this.stopped) {
|
|
7323
7342
|
this.clearTimer();
|
|
7324
7343
|
fresh.close();
|
|
@@ -7749,9 +7768,10 @@ var CoverageSession = class CoverageSession {
|
|
|
7749
7768
|
* destinations, the roots — lives here, so the caller only supplies where
|
|
7750
7769
|
* the browser is.
|
|
7751
7770
|
*/
|
|
7752
|
-
armBrowser(ref,
|
|
7771
|
+
armBrowser(ref, browser, coverageDir) {
|
|
7753
7772
|
return startBrowserCoverage({
|
|
7754
|
-
cdpUrl,
|
|
7773
|
+
cdpUrl: browser.cdpUrl,
|
|
7774
|
+
currentCdpUrl: browser.currentCdpUrl?.bind(browser),
|
|
7755
7775
|
specId: specIdFor(this.runId, ref),
|
|
7756
7776
|
origins: this.origins,
|
|
7757
7777
|
assetOrigins: this.assetOrigins,
|
|
@@ -8257,7 +8277,7 @@ async function runOneSpec$1(ref, opts, blocks) {
|
|
|
8257
8277
|
});
|
|
8258
8278
|
const acquired = browserHandle;
|
|
8259
8279
|
opts.teardown?.onFinalize(() => acquired.dispose());
|
|
8260
|
-
browserEngine = await measurement.collector.armBrowser(ref, browserHandle
|
|
8280
|
+
browserEngine = await measurement.collector.armBrowser(ref, browserHandle, coverageDir);
|
|
8261
8281
|
if (browserHandle.amendCommand) command = browserHandle.amendCommand(command);
|
|
8262
8282
|
Object.assign(childEnv, browserHandle.env);
|
|
8263
8283
|
} catch (err) {
|
|
@@ -13884,6 +13904,37 @@ async function acquireAgentBrowserEndpoint(ctx) {
|
|
|
13884
13904
|
"about:blank"
|
|
13885
13905
|
]);
|
|
13886
13906
|
if (warm.status !== 0) throw new Error(`could not start the session's browser: ${warm.stderr || warm.stdout}`);
|
|
13907
|
+
return {
|
|
13908
|
+
cdpUrl: askCdpUrl(session),
|
|
13909
|
+
currentCdpUrl: () => askCdpUrlSoon(session),
|
|
13910
|
+
dispose: async () => {}
|
|
13911
|
+
};
|
|
13912
|
+
}
|
|
13913
|
+
/**
|
|
13914
|
+
* The same question on a short leash. Its caller is racing its own backoff
|
|
13915
|
+
* between reconnect attempts, so an answer that arrives after the budget is
|
|
13916
|
+
* spent is worth less than no answer: `spawnAB` would sit through a 30s EAGAIN
|
|
13917
|
+
* retry and a 35s hard timeout, which is the whole reconnect window several
|
|
13918
|
+
* times over.
|
|
13919
|
+
*/
|
|
13920
|
+
const CDP_URL_TIMEOUT_MS = 2e3;
|
|
13921
|
+
async function askCdpUrlSoon(session) {
|
|
13922
|
+
const { promisify } = await import("node:util");
|
|
13923
|
+
const { execFile } = await import("node:child_process");
|
|
13924
|
+
const { stdout } = await promisify(execFile)(resolveAgentBrowserBin$1(), [
|
|
13925
|
+
"--session",
|
|
13926
|
+
session,
|
|
13927
|
+
"get",
|
|
13928
|
+
"cdp-url"
|
|
13929
|
+
], {
|
|
13930
|
+
timeout: CDP_URL_TIMEOUT_MS,
|
|
13931
|
+
encoding: "utf8"
|
|
13932
|
+
});
|
|
13933
|
+
const cdpUrl = stdout.trim().split("\n").pop()?.trim() ?? "";
|
|
13934
|
+
if (!/^wss?:\/\//.test(cdpUrl)) throw new Error(`agent-browser answered no cdp-url for session ${session}`);
|
|
13935
|
+
return cdpUrl;
|
|
13936
|
+
}
|
|
13937
|
+
function askCdpUrl(session) {
|
|
13887
13938
|
const answer = spawnAB([
|
|
13888
13939
|
"--session",
|
|
13889
13940
|
session,
|
|
@@ -13892,10 +13943,7 @@ async function acquireAgentBrowserEndpoint(ctx) {
|
|
|
13892
13943
|
]);
|
|
13893
13944
|
const cdpUrl = answer.stdout.trim().split("\n").pop()?.trim() ?? "";
|
|
13894
13945
|
if (answer.status !== 0 || !/^wss?:\/\//.test(cdpUrl)) throw new Error(`agent-browser did not answer \`get cdp-url\` for session ${session}: ${answer.stderr || answer.stdout}`);
|
|
13895
|
-
return
|
|
13896
|
-
cdpUrl,
|
|
13897
|
-
dispose: async () => {}
|
|
13898
|
-
};
|
|
13946
|
+
return cdpUrl;
|
|
13899
13947
|
}
|
|
13900
13948
|
//#endregion
|
|
13901
13949
|
//#region src/diagnose/snapshot.ts
|
|
@@ -14279,7 +14327,7 @@ async function runOneSpec(args) {
|
|
|
14279
14327
|
browserEngine = await opts.coverage.armBrowser({
|
|
14280
14328
|
featureName,
|
|
14281
14329
|
specName
|
|
14282
|
-
}, handle
|
|
14330
|
+
}, handle, coverageDir);
|
|
14283
14331
|
} catch (err) {
|
|
14284
14332
|
coverageBroken = errMessage(err);
|
|
14285
14333
|
warn(`coverage: could not attach to the live browser (${coverageBroken})`);
|
package/dist/package.json
CHANGED