@rehearsal-labs/retest 0.2.0 → 0.3.0
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/README.md +6 -5
- package/dist/api/source-location.d.ts.map +1 -1
- package/dist/api/source-location.js +3 -1
- package/dist/browser/builds.d.ts +35 -6
- package/dist/browser/builds.d.ts.map +1 -1
- package/dist/browser/builds.js +115 -16
- package/dist/browser/cdp/transport.d.ts.map +1 -1
- package/dist/browser/cdp/transport.js +4 -4
- package/dist/browser/chromium-process.d.ts +23 -0
- package/dist/browser/chromium-process.d.ts.map +1 -1
- package/dist/browser/chromium-process.js +78 -13
- package/dist/browser/electron.d.ts +1 -1
- package/dist/browser/electron.d.ts.map +1 -1
- package/dist/browser/electron.js +6 -3
- package/dist/browser/executables.d.ts +16 -1
- package/dist/browser/executables.d.ts.map +1 -1
- package/dist/browser/executables.js +50 -18
- package/dist/browser/firefox/accessible-names.d.ts +5 -4
- package/dist/browser/firefox/accessible-names.d.ts.map +1 -1
- package/dist/browser/firefox/accessible-names.js +11 -6
- package/dist/browser/firefox/bridge.js +3 -2
- package/dist/browser/firefox/executable.d.ts +14 -14
- package/dist/browser/firefox/executable.d.ts.map +1 -1
- package/dist/browser/firefox/executable.js +29 -21
- package/dist/browser/firefox/launch.js +1 -1
- package/dist/browser/firefox/navigation.d.ts +5 -2
- package/dist/browser/firefox/navigation.d.ts.map +1 -1
- package/dist/browser/firefox/navigation.js +48 -14
- package/dist/browser/firefox/orphans.d.ts.map +1 -1
- package/dist/browser/firefox/orphans.js +34 -2
- package/dist/browser/firefox/page.d.ts.map +1 -1
- package/dist/browser/firefox/page.js +113 -19
- package/dist/browser/firefox/process.d.ts +20 -1
- package/dist/browser/firefox/process.d.ts.map +1 -1
- package/dist/browser/firefox/process.js +124 -22
- package/dist/browser/firefox/profile.d.ts +5 -0
- package/dist/browser/firefox/profile.d.ts.map +1 -1
- package/dist/browser/firefox/profile.js +17 -1
- package/dist/browser/firefox/storage.d.ts.map +1 -1
- package/dist/browser/firefox/storage.js +4 -2
- package/dist/browser/firefox/subscriptions.d.ts +26 -0
- package/dist/browser/firefox/subscriptions.d.ts.map +1 -0
- package/dist/browser/firefox/subscriptions.js +10 -0
- package/dist/browser/launch.d.ts +6 -0
- package/dist/browser/launch.d.ts.map +1 -1
- package/dist/browser/launch.js +14 -1
- package/dist/cli/commands/doctor.js +3 -3
- package/dist/cli/commands/inspect.js +3 -2
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +26 -13
- package/dist/cli/commands/licences.d.ts +22 -0
- package/dist/cli/commands/licences.d.ts.map +1 -1
- package/dist/cli/commands/licences.js +62 -20
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/doctor/checks.js +4 -1
- package/dist/cli/inspect/diagnostics.js +3 -3
- package/dist/cli/inspect/test-timeline.js +10 -10
- package/dist/cli/install/doctor-rows.d.ts.map +1 -1
- package/dist/cli/install/doctor-rows.js +5 -4
- package/dist/cli/install/file-changes.d.ts +44 -0
- package/dist/cli/install/file-changes.d.ts.map +1 -0
- package/dist/cli/install/file-changes.js +81 -0
- package/dist/cli/install/install-archive.d.ts +3 -1
- package/dist/cli/install/install-archive.d.ts.map +1 -1
- package/dist/cli/install/install-archive.js +80 -33
- package/dist/cli/install/lock.d.ts.map +1 -1
- package/dist/cli/install/lock.js +108 -21
- package/dist/cli/install/media-doctor.d.ts.map +1 -1
- package/dist/cli/install/media-doctor.js +2 -1
- package/dist/cli/install/media-install.d.ts.map +1 -1
- package/dist/cli/install/media-install.js +38 -19
- package/dist/cli/install/media-pins.d.ts +7 -1
- package/dist/cli/install/media-pins.d.ts.map +1 -1
- package/dist/cli/install/media-pins.js +23 -12
- package/dist/cli/install/media-record.d.ts.map +1 -1
- package/dist/cli/install/media-record.js +10 -9
- package/dist/cli/install/media-report.d.ts +3 -1
- package/dist/cli/install/media-report.d.ts.map +1 -1
- package/dist/cli/install/media-report.js +7 -5
- package/dist/cli/install/media-tools.d.ts.map +1 -1
- package/dist/cli/install/media-tools.js +6 -4
- package/dist/cli/install/process-start.d.ts +3 -2
- package/dist/cli/install/process-start.d.ts.map +1 -1
- package/dist/cli/install/process-start.js +4 -0
- package/dist/cli/install/report.d.ts.map +1 -1
- package/dist/cli/install/report.js +11 -7
- package/dist/cli/install/supervisor-install.d.ts +33 -0
- package/dist/cli/install/supervisor-install.d.ts.map +1 -0
- package/dist/cli/install/supervisor-install.js +158 -0
- package/dist/cli/install/supervisor-locate.d.ts +47 -0
- package/dist/cli/install/supervisor-locate.d.ts.map +1 -0
- package/dist/cli/install/supervisor-locate.js +113 -0
- package/dist/cli/install/supervisor-pins.d.ts +21 -0
- package/dist/cli/install/supervisor-pins.d.ts.map +1 -0
- package/dist/cli/install/supervisor-pins.js +28 -0
- package/dist/cli/install/supervisor-record.d.ts +31 -0
- package/dist/cli/install/supervisor-record.d.ts.map +1 -0
- package/dist/cli/install/supervisor-record.js +104 -0
- package/dist/cli/install/supervisor-report.d.ts +11 -0
- package/dist/cli/install/supervisor-report.d.ts.map +1 -0
- package/dist/cli/install/supervisor-report.js +33 -0
- package/dist/cli/install/supervisor-tools.d.ts +43 -0
- package/dist/cli/install/supervisor-tools.d.ts.map +1 -0
- package/dist/cli/install/supervisor-tools.js +114 -0
- package/dist/cli/install/unpack.d.ts +23 -3
- package/dist/cli/install/unpack.d.ts.map +1 -1
- package/dist/cli/install/unpack.js +124 -10
- package/dist/cli/install/zip-member.d.ts +15 -0
- package/dist/cli/install/zip-member.d.ts.map +1 -0
- package/dist/cli/install/zip-member.js +77 -0
- package/dist/cli/interrupt.d.ts +1 -1
- package/dist/cli/interrupt.d.ts.map +1 -1
- package/dist/cli/interrupt.js +15 -10
- package/dist/cli/terminal.d.ts +9 -1
- package/dist/cli/terminal.d.ts.map +1 -1
- package/dist/cli/terminal.js +14 -0
- package/dist/config/define.d.ts +2 -2
- package/dist/config/define.js +2 -2
- package/dist/diagnostics/firefox-collector.d.ts +11 -10
- package/dist/diagnostics/firefox-collector.d.ts.map +1 -1
- package/dist/diagnostics/firefox-collector.js +16 -11
- package/dist/media/client.d.ts +2 -1
- package/dist/media/client.d.ts.map +1 -1
- package/dist/media/client.js +16 -5
- package/dist/media/host.d.ts +32 -0
- package/dist/media/host.d.ts.map +1 -0
- package/dist/media/host.js +50 -0
- package/dist/media/locate.d.ts.map +1 -1
- package/dist/media/locate.js +4 -3
- package/dist/native/processes.d.ts.map +1 -1
- package/dist/native/processes.js +7 -3
- package/dist/protocol/files.d.ts +1 -1
- package/dist/protocol/files.d.ts.map +1 -1
- package/dist/protocol/files.js +10 -5
- package/dist/reporters/commands.d.ts +12 -3
- package/dist/reporters/commands.d.ts.map +1 -1
- package/dist/reporters/commands.js +29 -11
- package/dist/reporters/human-card.js +1 -1
- package/dist/reporters/human.d.ts +3 -1
- package/dist/reporters/human.d.ts.map +1 -1
- package/dist/reporters/human.js +8 -8
- package/dist/reporters/style.d.ts +21 -2
- package/dist/reporters/style.d.ts.map +1 -1
- package/dist/reporters/style.js +11 -2
- package/dist/runner/app-server.d.ts +27 -7
- package/dist/runner/app-server.d.ts.map +1 -1
- package/dist/runner/app-server.js +74 -24
- package/dist/runner/child.js +6 -2
- package/dist/runner/media-leftovers.d.ts +7 -3
- package/dist/runner/media-leftovers.d.ts.map +1 -1
- package/dist/runner/media-leftovers.js +27 -6
- package/dist/runner/resources.d.ts +8 -0
- package/dist/runner/resources.d.ts.map +1 -1
- package/dist/runner/resources.js +12 -1
- package/dist/runner/run-session.d.ts.map +1 -1
- package/dist/runner/run-session.js +9 -4
- package/dist/runner/run.d.ts.map +1 -1
- package/dist/runner/run.js +2 -1
- package/dist/runner/target-drivers.d.ts +5 -2
- package/dist/runner/target-drivers.d.ts.map +1 -1
- package/dist/runner/target-drivers.js +10 -1
- package/dist/runner/test-file-process.d.ts +8 -0
- package/dist/runner/test-file-process.d.ts.map +1 -1
- package/dist/runner/test-file-process.js +26 -3
- package/dist/runner/test-pages.d.ts.map +1 -1
- package/dist/runner/test-pages.js +5 -2
- package/dist/shared/environment.d.ts +17 -0
- package/dist/shared/environment.d.ts.map +1 -0
- package/dist/shared/environment.js +27 -0
- package/dist/shared/metadata-process-worker.js +15 -7
- package/dist/shared/metadata-process.d.ts +5 -0
- package/dist/shared/metadata-process.d.ts.map +1 -1
- package/dist/shared/metadata-process.js +36 -6
- package/dist/shared/posix-path.d.ts +12 -0
- package/dist/shared/posix-path.d.ts.map +1 -1
- package/dist/shared/posix-path.js +16 -0
- package/dist/shared/private-file.d.ts +38 -0
- package/dist/shared/private-file.d.ts.map +1 -0
- package/dist/shared/private-file.js +132 -0
- package/dist/shared/process-ownership.d.ts +52 -2
- package/dist/shared/process-ownership.d.ts.map +1 -1
- package/dist/shared/process-ownership.js +104 -11
- package/dist/shared/process-supervisor.d.ts +309 -0
- package/dist/shared/process-supervisor.d.ts.map +1 -0
- package/dist/shared/process-supervisor.js +737 -0
- package/dist/shared/process-system.d.ts +113 -0
- package/dist/shared/process-system.d.ts.map +1 -0
- package/dist/shared/process-system.js +254 -0
- package/dist/shared/regular-file.d.ts +2 -2
- package/dist/shared/regular-file.d.ts.map +1 -1
- package/dist/shared/regular-file.js +19 -2
- package/dist/store/artifacts.d.ts +5 -4
- package/dist/store/artifacts.d.ts.map +1 -1
- package/dist/store/artifacts.js +18 -5
- package/dist/store/run-store.d.ts +5 -2
- package/dist/store/run-store.d.ts.map +1 -1
- package/dist/store/run-store.js +48 -4
- package/media/Cargo.lock +16 -0
- package/media/Cargo.toml +16 -1
- package/media/src/encoder.rs +56 -12
- package/media/src/frame.rs +7 -1
- package/media/src/main.rs +20 -2
- package/media/src/place.rs +230 -11
- package/media/src/process_ownership_windows.rs +1058 -0
- package/media/src/recording.rs +15 -7
- package/media/src/replies.rs +55 -0
- package/media/src/server.rs +72 -2
- package/media/src/store.rs +71 -2
- package/package.json +9 -4
- package/src/cli/install/media-notices.txt +465 -1
- package/supervisor/Cargo.lock +25 -0
- package/supervisor/Cargo.toml +22 -0
- package/supervisor/NOTICES +464 -0
- package/supervisor/build.rs +44 -0
- package/supervisor/src/command.rs +612 -0
- package/supervisor/src/jobs.rs +1650 -0
- package/supervisor/src/main.rs +71 -0
- package/supervisor/src/reply.rs +367 -0
|
@@ -2,15 +2,17 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { once } from 'node:events';
|
|
3
3
|
import { rmSync } from 'node:fs';
|
|
4
4
|
import { mkdir, open, rm } from 'node:fs/promises';
|
|
5
|
-
import { dirname } from 'node:path';
|
|
5
|
+
import { basename, dirname } from 'node:path';
|
|
6
6
|
import { Readable, Writable } from 'node:stream';
|
|
7
7
|
import { setTimeout as sleep } from 'node:timers/promises';
|
|
8
8
|
import { Deadline } from "../protocol/deadline.js";
|
|
9
9
|
import { maxTimeout } from "../protocol/timeouts.js";
|
|
10
10
|
import { errorMessage } from "../protocol/failures.js";
|
|
11
|
+
import { withoutVariables } from "../shared/environment.js";
|
|
11
12
|
import { errorCode } from "../shared/error-code.js";
|
|
12
13
|
import { onlyUnreaped, procStats } from "../shared/unreaped-group.js";
|
|
13
14
|
import { OwnedProcessGroup, unverifiedMembersProblem } from "../shared/process-ownership.js";
|
|
15
|
+
import { holdLaunch, launchesHeldByJob, prepareOwnedLaunch } from "../shared/process-system.js";
|
|
14
16
|
import { closeGraceMs, LaunchError } from "./contract.js";
|
|
15
17
|
import { writeRedactedLog } from "./redacted-log.js";
|
|
16
18
|
const pollMs = 25;
|
|
@@ -252,6 +254,22 @@ export function stillThereMessage(groupId, stats, timeoutMs = closeGraceMs) {
|
|
|
252
254
|
* @example signalGroup(browser.pid, 0) // true while any browser process is still there
|
|
253
255
|
*/
|
|
254
256
|
export function signalGroup(pgid, signal) {
|
|
257
|
+
// Windows has no process group to send signal 0 to: a launch held here is asked through its job, and one held by
|
|
258
|
+
// another process only by its own pid.
|
|
259
|
+
if (signal === 0 && launchesHeldByJob) {
|
|
260
|
+
const owner = ownedGroups.get(pgid);
|
|
261
|
+
if (owner !== undefined)
|
|
262
|
+
return owner.remains();
|
|
263
|
+
try {
|
|
264
|
+
process.kill(pgid, 0);
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
if (errorCode(error) === 'ESRCH')
|
|
269
|
+
return false;
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
255
273
|
if (signal !== 0) {
|
|
256
274
|
const owner = ownedGroups.get(pgid);
|
|
257
275
|
if (owner === undefined)
|
|
@@ -289,18 +307,33 @@ async function spawnInGroup(options) {
|
|
|
289
307
|
const log = await openLog(options.logFile);
|
|
290
308
|
let logHandedOn = false;
|
|
291
309
|
try {
|
|
292
|
-
const hidden = new Set(options.hiddenVariables);
|
|
293
310
|
// Output to redact comes through Retest; any other goes straight to the log.
|
|
294
311
|
const outputMode = redact === undefined && redactStream === undefined ? log.fd : 'pipe';
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
312
|
+
try {
|
|
313
|
+
prepareOwnedLaunch();
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
throw new LaunchError(`Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
317
|
+
}
|
|
318
|
+
let child;
|
|
319
|
+
try {
|
|
320
|
+
child = spawn(options.executable, options.args, {
|
|
321
|
+
env: withoutVariables(process.env, options.hiddenVariables),
|
|
322
|
+
detached: true,
|
|
323
|
+
stdio: ['ignore', outputMode, outputMode, 'pipe', 'pipe'],
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
// Windows refuses a program whose access list denies this user running it at the spawn itself, with EPERM; the
|
|
328
|
+
// check before the launch cannot see that there, as it sees a mode on macOS and Linux.
|
|
329
|
+
const refused = errorCode(error) === 'EPERM' || errorCode(error) === 'EACCES';
|
|
330
|
+
throw new LaunchError(refused ? `${options.executable} is not executable. Allow it to run, or pass another browser.` : `Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
331
|
+
}
|
|
300
332
|
await once(child, 'spawn').catch((error) => {
|
|
301
333
|
throw new LaunchError(`Cannot start ${options.executable}: ${errorMessage(error)}`, { cause: error });
|
|
302
334
|
});
|
|
303
|
-
|
|
335
|
+
// Every process of the browser carries its profile's folder in its command line.
|
|
336
|
+
const ownership = holdLaunch(child, options.profile === undefined ? {} : { marker: basename(options.profile) });
|
|
304
337
|
const ownershipProblems = ownership.capture();
|
|
305
338
|
const [, , , writable, readable] = child.stdio;
|
|
306
339
|
if (!(writable instanceof Writable) || !(readable instanceof Readable)) {
|
|
@@ -366,7 +399,7 @@ async function spawnInGroup(options) {
|
|
|
366
399
|
* readers and flush accepted bytes and queued writes within that same writing bound. This does not claim remote
|
|
367
400
|
* EOF or collect bytes an inherited writer sends later. An output without this support still fails and is canceled.
|
|
368
401
|
*/
|
|
369
|
-
async function outputWithin(output, timeoutMs, confirmedGone) {
|
|
402
|
+
export async function outputWithin(output, timeoutMs, confirmedGone) {
|
|
370
403
|
const first = await settledWithin(output.closed, timeoutMs);
|
|
371
404
|
if (first !== undefined)
|
|
372
405
|
return first;
|
|
@@ -426,21 +459,53 @@ async function groupEnds(ownership, grace, { ref = true, deadline = grace } = {}
|
|
|
426
459
|
}
|
|
427
460
|
return true;
|
|
428
461
|
}
|
|
462
|
+
/** How long an exit hook on Windows asks again to remove a folder whose processes it confirmed gone. */
|
|
463
|
+
export const exitRemovalMs = 2 * closeGraceMs;
|
|
429
464
|
// Runs while the Retest process exits, when a failure can neither be awaited nor reported.
|
|
430
465
|
function killAtExit(ownership, profile) {
|
|
431
466
|
try {
|
|
432
467
|
const deadline = new Deadline(closeGraceMs);
|
|
433
468
|
ownership.signalNow('SIGKILL', deadline);
|
|
434
|
-
if (profile
|
|
469
|
+
if (profile === undefined || !groupEndsNow(ownership, deadline))
|
|
470
|
+
return;
|
|
471
|
+
// On Windows the end and its confirmation are runs of retest-supervisor, which a slow host can spend most of the
|
|
472
|
+
// bound on, and the folder refuses removal for up to a second after its processes left their job, as a scanner
|
|
473
|
+
// holds what they wrote; the removal gets a bound of its own, so a profile whose processes are confirmed gone is
|
|
474
|
+
// removed.
|
|
475
|
+
if (launchesHeldByJob)
|
|
476
|
+
removeOnceFree(profile, new Deadline(exitRemovalMs));
|
|
477
|
+
else
|
|
435
478
|
rmSync(profile, { recursive: true, force: true, maxRetries: 3 });
|
|
436
479
|
}
|
|
437
480
|
catch {
|
|
438
481
|
// Throwing here would replace the exit code Retest chose.
|
|
439
482
|
}
|
|
440
483
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
484
|
+
/**
|
|
485
|
+
* Removes a folder from an exit hook on Windows, where a folder whose files processes just ended were using refuses
|
|
486
|
+
* removal for a moment after they left their job, and the synchronous removal does not wait: it is asked again, a poll
|
|
487
|
+
* apart, until the deadline.
|
|
488
|
+
*/
|
|
489
|
+
export function removeOnceFree(folder, deadline) {
|
|
490
|
+
const pause = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
491
|
+
for (;;) {
|
|
492
|
+
try {
|
|
493
|
+
rmSync(folder, { recursive: true, force: true });
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
const code = errorCode(error);
|
|
498
|
+
if ((code !== 'EPERM' && code !== 'EBUSY' && code !== 'ENOTEMPTY') || deadline.expired)
|
|
499
|
+
throw error;
|
|
500
|
+
Atomics.wait(pause, 0, 0, Math.min(pollMs, deadline.remainingMs));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Whether a group is gone, for an exit hook, which cannot await. Processes just sent SIGKILL are still exiting when they
|
|
506
|
+
* are first read, so the group is read again, a poll apart, until it is gone or the deadline passes.
|
|
507
|
+
*/
|
|
508
|
+
export function groupEndsNow(ownership, deadline) {
|
|
444
509
|
const pause = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
445
510
|
while (ownership.remains(deadline)) {
|
|
446
511
|
if (deadline.expired)
|
|
@@ -16,7 +16,7 @@ import { LaunchError } from './contract.ts';
|
|
|
16
16
|
import { type RouteRemoval } from './routes.ts';
|
|
17
17
|
/** How to launch an Electron app. Every path is absolute. */
|
|
18
18
|
export type ElectronLaunchOptions = {
|
|
19
|
-
/** The Electron binary, inside Electron.app on macOS. */
|
|
19
|
+
/** The Electron binary, inside Electron.app on macOS, and electron.exe on Windows. */
|
|
20
20
|
readonly executablePath: string;
|
|
21
21
|
/** The app's folder, which holds its package.json, or its entry file. */
|
|
22
22
|
readonly appPath: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"electron.d.ts","sourceRoot":"","sources":["../../src/browser/electron.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,cAAc,EACd,cAAc,EACd,WAAW,EACX,cAAc,EACd,SAAS,EACT,kBAAkB,EAClB,UAAU,EACX,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAQhE,OAAO,EAAE,QAAQ,EAA6B,MAAM,yBAAyB,CAAA;AAM7E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAKnD,OAAO,EAAgB,WAAW,EAAE,MAAM,eAAe,CAAA;AAQzD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAU9D,6DAA6D;AAC7D,MAAM,MAAM,qBAAqB,GAAG;IAClC,
|
|
1
|
+
{"version":3,"file":"electron.d.ts","sourceRoot":"","sources":["../../src/browser/electron.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/electron.js
CHANGED
|
@@ -33,7 +33,8 @@ const launchTimeoutMs = 30_000;
|
|
|
33
33
|
const runAsNode = 'ELECTRON_RUN_AS_NODE';
|
|
34
34
|
// Electron's own logging, which would print the windows' console lines and more into the app's output unredacted.
|
|
35
35
|
const loggingVariables = ['ELECTRON_ENABLE_LOGGING', 'ELECTRON_LOG_FILE', 'ELECTRON_DEBUG_NOTIFICATIONS', 'ELECTRON_LOG_ASAR_READS', 'ELECTRON_ENABLE_STACK_DUMPING'];
|
|
36
|
-
|
|
36
|
+
// Electron's own build names its binary Electron inside Electron.app on macOS, and electron.exe on Windows.
|
|
37
|
+
const giveBinary = process.platform === 'win32' ? "Give the Electron binary: electron.exe in Electron's own build." : 'Give the Electron binary, inside Electron.app on macOS: Electron.app/Contents/MacOS/Electron.';
|
|
37
38
|
const targetInfoSchema = s.object({ targetId: s.string(), type: s.string(), browserContextId: s.optional(s.string()) });
|
|
38
39
|
const targetsSchema = s.object({ targetInfos: s.array(targetInfoSchema) });
|
|
39
40
|
const targetCreatedSchema = s.object({ targetInfo: targetInfoSchema });
|
|
@@ -365,8 +366,10 @@ class ElectronApp {
|
|
|
365
366
|
async #close(timeoutMs) {
|
|
366
367
|
this.#closeRequested = true;
|
|
367
368
|
const graceMs = Math.max(0, Math.min(closeGraceMs, timeoutMs - closeGraceMs));
|
|
368
|
-
// The app's helpers are read before its pipe closes, without holding the thread
|
|
369
|
-
|
|
369
|
+
// The app's helpers are read before its pipe closes, without holding the thread. The caller's cleanup deadline
|
|
370
|
+
// bounds the confirmation of the app's end, as it does Chrome's; a short one keeps `stop`'s own allowance.
|
|
371
|
+
const deadline = new Deadline(timeoutMs);
|
|
372
|
+
const ownershipDeadline = deadline.budgetMs < graceMs + 2 * closeGraceMs ? new Deadline(graceMs + 2 * closeGraceMs) : deadline;
|
|
370
373
|
await this.#process.recordDescendantsNow(ownershipDeadline);
|
|
371
374
|
const problems = [];
|
|
372
375
|
try {
|
|
@@ -24,15 +24,30 @@ export type ResolvedExecutable = {
|
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
26
|
* Finds the browser a target launches: the path it names, `RETEST_CHROMIUM` for `chromium`, or the standard
|
|
27
|
-
* install locations of Chrome and Edge on macOS and
|
|
27
|
+
* install locations of Chrome and Edge on macOS, Linux and Windows. Reads the machine only through `host`.
|
|
28
28
|
*
|
|
29
29
|
* @example resolveExecutable({ product: 'chrome', channel: 'beta' }, systemHost())
|
|
30
30
|
*/
|
|
31
31
|
export declare function resolveExecutable(request: ExecutableRequest, host: ExecutableHost): ResolvedExecutable;
|
|
32
|
+
/**
|
|
33
|
+
* Where Firefox installs on this kind of machine, for a Firefox target that names no executable and has no pinned
|
|
34
|
+
* build: the app in /Applications on macOS, and Mozilla's folder under each Windows root. Nothing is looked for on
|
|
35
|
+
* Linux, where Retest does not run Firefox.
|
|
36
|
+
*
|
|
37
|
+
* @example systemFirefoxPaths({ platform: 'darwin', env: {}, exists: existsSync }) // ['/Applications/Firefox.app/Contents/MacOS/firefox']
|
|
38
|
+
*/
|
|
39
|
+
export declare function systemFirefoxPaths(host: ExecutableHost): string[];
|
|
32
40
|
/**
|
|
33
41
|
* The machine Retest runs on, for `resolveExecutable`.
|
|
34
42
|
*
|
|
35
43
|
* @example resolveExecutable({ product: 'chromium' }, systemHost())
|
|
36
44
|
*/
|
|
37
45
|
export declare function systemHost(): ExecutableHost;
|
|
46
|
+
/**
|
|
47
|
+
* Where an installed program is looked for on Windows: its path under each root folder this machine names, in the
|
|
48
|
+
* order every user's install comes before one person's.
|
|
49
|
+
*
|
|
50
|
+
* @example windowsPaths('Mozilla Firefox\\firefox.exe', host) // ['C:\\Program Files\\Mozilla Firefox\\firefox.exe', …]
|
|
51
|
+
*/
|
|
52
|
+
export declare function windowsPaths(inside: string, host: ExecutableHost): string[];
|
|
38
53
|
//# sourceMappingURL=executables.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executables.d.ts","sourceRoot":"","sources":["../../src/browser/executables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"executables.d.ts","sourceRoot":"","sources":["../../src/browser/executables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAA;AAMtD,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAA;AAE3D,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;AAEjE,oHAAoH;AACpH,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9G,uDAAuD;AACvD,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IACzB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAA;IACjD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B,CAAA;AAED,wFAAwF;AACxF,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AA4B9G;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,GAAG,kBAAkB,CAatG;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAIjE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,cAAc,CAE3C;AAyBD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAM3E"}
|
|
@@ -1,37 +1,45 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import {
|
|
2
|
+
import { posix, win32 } from 'node:path';
|
|
3
|
+
import { listWords } from "../shared/list-words.js";
|
|
4
|
+
import { environmentVariable } from "./builds.js";
|
|
3
5
|
const chromiumVariable = 'RETEST_CHROMIUM';
|
|
4
6
|
const installs = {
|
|
5
7
|
chrome: {
|
|
6
|
-
stable: { name: 'Google Chrome', mac: 'Google Chrome', linux: ['/opt/google/chrome/chrome', '/usr/bin/google-chrome-stable', '/usr/bin/google-chrome'] },
|
|
7
|
-
beta: { name: 'Google Chrome Beta', mac: 'Google Chrome Beta', linux: ['/opt/google/chrome-beta/chrome', '/usr/bin/google-chrome-beta'] },
|
|
8
|
-
dev: { name: 'Google Chrome Dev', mac: 'Google Chrome Dev', linux: ['/opt/google/chrome-unstable/chrome', '/usr/bin/google-chrome-unstable'] },
|
|
9
|
-
|
|
8
|
+
stable: { name: 'Google Chrome', mac: 'Google Chrome', linux: ['/opt/google/chrome/chrome', '/usr/bin/google-chrome-stable', '/usr/bin/google-chrome'], windows: 'Google\\Chrome\\Application\\chrome.exe' },
|
|
9
|
+
beta: { name: 'Google Chrome Beta', mac: 'Google Chrome Beta', linux: ['/opt/google/chrome-beta/chrome', '/usr/bin/google-chrome-beta'], windows: 'Google\\Chrome Beta\\Application\\chrome.exe' },
|
|
10
|
+
dev: { name: 'Google Chrome Dev', mac: 'Google Chrome Dev', linux: ['/opt/google/chrome-unstable/chrome', '/usr/bin/google-chrome-unstable'], windows: 'Google\\Chrome Dev\\Application\\chrome.exe' },
|
|
11
|
+
// Canary installs side by side with the others, in the folder Google names SxS.
|
|
12
|
+
canary: { name: 'Google Chrome Canary', mac: 'Google Chrome Canary', linux: ['/opt/google/chrome-canary/chrome', '/usr/bin/google-chrome-canary'], windows: 'Google\\Chrome SxS\\Application\\chrome.exe' },
|
|
10
13
|
},
|
|
11
14
|
edge: {
|
|
12
|
-
stable: { name: 'Microsoft Edge', mac: 'Microsoft Edge', linux: ['/opt/microsoft/msedge/msedge', '/usr/bin/microsoft-edge-stable', '/usr/bin/microsoft-edge'] },
|
|
13
|
-
beta: { name: 'Microsoft Edge Beta', mac: 'Microsoft Edge Beta', linux: ['/opt/microsoft/msedge-beta/msedge', '/usr/bin/microsoft-edge-beta'] },
|
|
14
|
-
dev: { name: 'Microsoft Edge Dev', mac: 'Microsoft Edge Dev', linux: ['/opt/microsoft/msedge-dev/msedge', '/usr/bin/microsoft-edge-dev'] },
|
|
15
|
+
stable: { name: 'Microsoft Edge', mac: 'Microsoft Edge', linux: ['/opt/microsoft/msedge/msedge', '/usr/bin/microsoft-edge-stable', '/usr/bin/microsoft-edge'], windows: 'Microsoft\\Edge\\Application\\msedge.exe' },
|
|
16
|
+
beta: { name: 'Microsoft Edge Beta', mac: 'Microsoft Edge Beta', linux: ['/opt/microsoft/msedge-beta/msedge', '/usr/bin/microsoft-edge-beta'], windows: 'Microsoft\\Edge Beta\\Application\\msedge.exe' },
|
|
17
|
+
dev: { name: 'Microsoft Edge Dev', mac: 'Microsoft Edge Dev', linux: ['/opt/microsoft/msedge-dev/msedge', '/usr/bin/microsoft-edge-dev'], windows: 'Microsoft\\Edge Dev\\Application\\msedge.exe' },
|
|
15
18
|
// Microsoft publishes no Canary build of Edge for Linux.
|
|
16
|
-
canary: { name: 'Microsoft Edge Canary', mac: 'Microsoft Edge Canary', linux: [] },
|
|
19
|
+
canary: { name: 'Microsoft Edge Canary', mac: 'Microsoft Edge Canary', linux: [], windows: 'Microsoft\\Edge SxS\\Application\\msedge.exe' },
|
|
17
20
|
},
|
|
18
21
|
};
|
|
22
|
+
// A browser installs for every user under Program Files, its 32-bit twin on 64-bit Windows, or for one person under
|
|
23
|
+
// their local application data, which needs no administrator.
|
|
24
|
+
const windowsRoots = ['ProgramFiles', 'ProgramFiles(x86)', 'LOCALAPPDATA'];
|
|
19
25
|
/**
|
|
20
26
|
* Finds the browser a target launches: the path it names, `RETEST_CHROMIUM` for `chromium`, or the standard
|
|
21
|
-
* install locations of Chrome and Edge on macOS and
|
|
27
|
+
* install locations of Chrome and Edge on macOS, Linux and Windows. Reads the machine only through `host`.
|
|
22
28
|
*
|
|
23
29
|
* @example resolveExecutable({ product: 'chrome', channel: 'beta' }, systemHost())
|
|
24
30
|
*/
|
|
25
31
|
export function resolveExecutable(request, host) {
|
|
26
|
-
if (host.platform !== 'darwin' && host.platform !== 'linux') {
|
|
27
|
-
return notFound('unsupported', `Retest runs browsers on macOS and
|
|
32
|
+
if (host.platform !== 'darwin' && host.platform !== 'linux' && host.platform !== 'win32') {
|
|
33
|
+
return notFound('unsupported', `Retest runs browsers on macOS, Linux and Windows, not on ${host.platform}.`, []);
|
|
28
34
|
}
|
|
29
35
|
if (request.executablePath !== undefined)
|
|
30
36
|
return atPath(request.executablePath, 'executablePath', host);
|
|
31
37
|
if (request.product === 'chromium')
|
|
32
38
|
return chromium(request, host);
|
|
33
39
|
const install = installs[request.product][request.channel ?? 'stable'];
|
|
34
|
-
const tried = host.platform === 'darwin' ? macPaths(install.mac, host) : [...install.linux];
|
|
40
|
+
const tried = host.platform === 'darwin' ? macPaths(install.mac, host) : host.platform === 'win32' ? windowsPaths(install.windows, host) : [...install.linux];
|
|
41
|
+
if (tried.length === 0 && host.platform === 'win32')
|
|
42
|
+
return notFound('setup_failed', `Retest has no folder to look for ${install.name} in: none of ${listWords(windowsRoots, 'and')} names an absolute folder.`, []);
|
|
35
43
|
if (tried.length === 0)
|
|
36
44
|
return notFound('setup_failed', `${install.name} is not made for Linux. Choose another channel.`, []);
|
|
37
45
|
const found = tried.find((path) => host.exists(path));
|
|
@@ -39,6 +47,20 @@ export function resolveExecutable(request, host) {
|
|
|
39
47
|
return { ok: true, path: found };
|
|
40
48
|
return notFound('setup_failed', `${install.name} is not installed. Retest looked in ${tried.join(', ')}. Install it, or choose another target.`, tried);
|
|
41
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Where Firefox installs on this kind of machine, for a Firefox target that names no executable and has no pinned
|
|
52
|
+
* build: the app in /Applications on macOS, and Mozilla's folder under each Windows root. Nothing is looked for on
|
|
53
|
+
* Linux, where Retest does not run Firefox.
|
|
54
|
+
*
|
|
55
|
+
* @example systemFirefoxPaths({ platform: 'darwin', env: {}, exists: existsSync }) // ['/Applications/Firefox.app/Contents/MacOS/firefox']
|
|
56
|
+
*/
|
|
57
|
+
export function systemFirefoxPaths(host) {
|
|
58
|
+
if (host.platform === 'darwin')
|
|
59
|
+
return ['/Applications/Firefox.app/Contents/MacOS/firefox'];
|
|
60
|
+
if (host.platform === 'win32')
|
|
61
|
+
return windowsPaths('Mozilla Firefox\\firefox.exe', host);
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
42
64
|
/**
|
|
43
65
|
* The machine Retest runs on, for `resolveExecutable`.
|
|
44
66
|
*
|
|
@@ -64,13 +86,23 @@ function atPath(path, source, host) {
|
|
|
64
86
|
}
|
|
65
87
|
// Chrome and Edge install into /Applications, or into the Applications folder of a person without admin rights.
|
|
66
88
|
function macPaths(bundle, host) {
|
|
67
|
-
const inside = join(`${bundle}.app`, 'Contents', 'MacOS', bundle);
|
|
89
|
+
const inside = posix.join(`${bundle}.app`, 'Contents', 'MacOS', bundle);
|
|
68
90
|
const home = host.env['HOME'];
|
|
69
|
-
return [join('/Applications', inside), ...(home === undefined || home === '' ? [] : [join(home, 'Applications', inside)])];
|
|
91
|
+
return [posix.join('/Applications', inside), ...(home === undefined || home === '' ? [] : [posix.join(home, 'Applications', inside)])];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Where an installed program is looked for on Windows: its path under each root folder this machine names, in the
|
|
95
|
+
* order every user's install comes before one person's.
|
|
96
|
+
*
|
|
97
|
+
* @example windowsPaths('Mozilla Firefox\\firefox.exe', host) // ['C:\\Program Files\\Mozilla Firefox\\firefox.exe', …]
|
|
98
|
+
*/
|
|
99
|
+
export function windowsPaths(inside, host) {
|
|
100
|
+
const roots = windowsRoots.flatMap((name) => {
|
|
101
|
+
const root = environmentVariable(host.env, name, 'win32');
|
|
102
|
+
return root === undefined || !win32.isAbsolute(root) ? [] : [root];
|
|
103
|
+
});
|
|
104
|
+
return [...new Set(roots.map((root) => win32.join(root, inside)))];
|
|
70
105
|
}
|
|
71
106
|
function notFound(failureClass, message, tried) {
|
|
72
107
|
return { ok: false, failure: { class: failureClass, message }, tried };
|
|
73
108
|
}
|
|
74
|
-
function platformName(platform) {
|
|
75
|
-
return platform === 'win32' ? 'Windows' : platform;
|
|
76
|
-
}
|
|
@@ -45,10 +45,11 @@ export declare function roleWants(locator: LocatorRecipe): Map<AriaRole, RoleWan
|
|
|
45
45
|
*/
|
|
46
46
|
export declare function roleWantsOf(locators: readonly LocatorRecipe[]): Map<AriaRole, RoleWants>;
|
|
47
47
|
/**
|
|
48
|
-
* The refusal of a lookup that asks for a table cell by name
|
|
49
|
-
*
|
|
50
|
-
* Firefox
|
|
51
|
-
*
|
|
48
|
+
* The refusal of a lookup that asks for a table cell by name. Chrome names a cell from its text; Firefox 133 gave a
|
|
49
|
+
* cell no name, so such a lookup found nothing on Firefox that Chrome finds, and a check that the cell is gone passed.
|
|
50
|
+
* Firefox 158 names the team table's cells from their text, but cell names have not been compared with Chrome's
|
|
51
|
+
* across the role pages, so the lookup stays refused. Column and row headers, grid cells and tooltips Firefox names,
|
|
52
|
+
* and they are looked up as on Chrome.
|
|
52
53
|
*
|
|
53
54
|
* @example unnamedCellRefusal({ by: 'role', role: 'cell', name: 'Ada' })?.class // 'unsupported'
|
|
54
55
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessible-names.d.ts","sourceRoot":"","sources":["../../../src/browser/firefox/accessible-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,kBAAkB,CAAA;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAS9D;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;CAAE,CAAA;AAE5F,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjF,+GAA+G;AAC/G,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7D;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAA;AAWpF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAyBxF;AAED
|
|
1
|
+
{"version":3,"file":"accessible-names.d.ts","sourceRoot":"","sources":["../../../src/browser/firefox/accessible-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,kBAAkB,CAAA;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAS9D;;;;GAIG;AACH,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;CAAE,CAAA;AAE5F,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjF,+GAA+G;AAC/G,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE7D;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAA;AAWpF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAyBxF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,GAAG,SAAS,CAUzE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAInE;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAQ3H;AAQD,eAAO,MAAM,qBAAqB,EAAE,MA6ClC,CAAA;AAiFF;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAcnC,CAAA;AAqDF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAoFnC,CAAA"}
|
|
@@ -59,10 +59,11 @@ export function roleWantsOf(locators) {
|
|
|
59
59
|
return wants;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
* The refusal of a lookup that asks for a table cell by name
|
|
63
|
-
*
|
|
64
|
-
* Firefox
|
|
65
|
-
*
|
|
62
|
+
* The refusal of a lookup that asks for a table cell by name. Chrome names a cell from its text; Firefox 133 gave a
|
|
63
|
+
* cell no name, so such a lookup found nothing on Firefox that Chrome finds, and a check that the cell is gone passed.
|
|
64
|
+
* Firefox 158 names the team table's cells from their text, but cell names have not been compared with Chrome's
|
|
65
|
+
* across the role pages, so the lookup stays refused. Column and row headers, grid cells and tooltips Firefox names,
|
|
66
|
+
* and they are looked up as on Chrome.
|
|
66
67
|
*
|
|
67
68
|
* @example unnamedCellRefusal({ by: 'role', role: 'cell', name: 'Ada' })?.class // 'unsupported'
|
|
68
69
|
*/
|
|
@@ -76,7 +77,7 @@ export function lookupRefusal(locator) {
|
|
|
76
77
|
return refusal(locator, step.role, `Firefox's accessibility locator gives a different set or name for ${step.role} than Chrome does`);
|
|
77
78
|
return {
|
|
78
79
|
class: 'unsupported',
|
|
79
|
-
message: `Could not look up ${describeLocator(locator)}:
|
|
80
|
+
message: `Could not look up ${describeLocator(locator)}: on Firefox, Retest does not look up a cell by its name, since it has not checked that Firefox names cells as Chrome does. Find it with getByText() or getByTestId(), or by its position with nth().`,
|
|
80
81
|
details: { role: 'cell' },
|
|
81
82
|
};
|
|
82
83
|
}
|
|
@@ -144,7 +145,11 @@ export const markupRefusalFunction = String.raw `function markupRefusal(role, na
|
|
|
144
145
|
};
|
|
145
146
|
if (['table', 'cell', 'row', 'columnheader', 'rowheader'].includes(role) && elements.some((element) => visible(element) && element.localName === 'table' && !dataTable(element))) return 'native tables can be layout tables in Chrome and data tables in Firefox';
|
|
146
147
|
if (['row', 'columnheader', 'rowheader'].includes(role) && elements.some((element) => visible(element) && element.getAttribute('role') === role && element.parentElement?.closest('[role="grid"], [role="treegrid"], [role="table"]') === null)) return 'a row or header outside a table or grid has different accessibility membership';
|
|
147
|
-
|
|
148
|
+
// Firefox 158 counts an option that no listbox holds, directly in a combobox among them, and a tree item or list
|
|
149
|
+
// item outside its tree or list, where Chrome counts none.
|
|
150
|
+
if (role === 'option' && elements.some((element) => visible(element) && element.getAttribute('role') === 'option' && element.parentElement?.closest('[role="listbox"]') === null)) return 'an option outside a listbox has different accessibility membership';
|
|
151
|
+
if (role === 'treeitem' && elements.some((element) => visible(element) && element.getAttribute('role') === 'treeitem' && element.parentElement?.closest('[role="tree"], [role="treegrid"]') === null)) return 'a tree item outside a tree has different accessibility membership';
|
|
152
|
+
if (role === 'listitem' && elements.some((element) => visible(element) && element.getAttribute('role') === 'listitem' && element.parentElement?.closest('[role="list"], ul, ol, menu') === null)) return 'a list item outside a list has different accessibility membership';
|
|
148
153
|
if (role === 'tab' && elements.some((element) => visible(element) && element.getAttribute('role') === 'tab' && element.parentElement?.closest('[role="tablist"]') === null)) return 'a tab outside a tablist has different accessibility membership';
|
|
149
154
|
if (['menuitem', 'menuitemcheckbox', 'menuitemradio'].includes(role) && elements.some((element) => visible(element) && element.getAttribute('role') === role && element.parentElement?.closest('[role="menu"], [role="menubar"]') === null)) return 'a menu item outside a menu has different accessibility membership';
|
|
150
155
|
if (role === 'heading' && elements.some((element) => visible(element) && element.isContentEditable)) return 'an editable heading can be named differently';
|
|
@@ -375,8 +375,9 @@ function protocolMessage(method, error) {
|
|
|
375
375
|
// A call whose document went while it ran is answered with an error about the window's actor going away.
|
|
376
376
|
if (inWorld && error.error === 'unknown error' && /destroyed|AbortError|discarded|unloaded/i.test(error.protocolMessage ?? ''))
|
|
377
377
|
return destroyedMessage;
|
|
378
|
-
// Firefox names why it refused a navigation, such as a blocked port
|
|
379
|
-
|
|
378
|
+
// Firefox names why it refused or gave up a navigation, such as a blocked port or a response with no content, in a
|
|
379
|
+
// message of its own words alone: a word on Firefox 133, an NS name such as `NS_BINDING_ABORTED` on Firefox 158.
|
|
380
|
+
const refused = method === 'browsingContext.navigate' && error.error === 'unknown error' ? /^Error: ([A-Za-z_]+)$/.exec(error.protocolMessage ?? '')?.[1] : undefined;
|
|
380
381
|
if (refused !== undefined)
|
|
381
382
|
return `unknown error: ${refused}`;
|
|
382
383
|
return error.error;
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { LoadedFirefoxTarget } from '../../config/loaded.ts';
|
|
2
2
|
import type { Failure } from '../../protocol/failures.ts';
|
|
3
|
-
/** Where Firefox installs on macOS, which a target without an executable path, and no installed pinned build, uses. */
|
|
4
|
-
export declare const defaultFirefoxPath = "/Applications/Firefox.app/Contents/MacOS/firefox";
|
|
5
3
|
/** The Firefox build a binary's files state: its version and build id, from the app's `application.ini`. */
|
|
6
4
|
export type FirefoxRelease = {
|
|
7
5
|
version: string;
|
|
@@ -11,29 +9,30 @@ export type FirefoxRelease = {
|
|
|
11
9
|
* The Firefox release the driver is tested with, from the pinned build: the facts the driver encodes (fields its
|
|
12
10
|
* accessibility locator leaves out, role names, what its BiDi lacks) are this release's.
|
|
13
11
|
*
|
|
14
|
-
* @example testedFirefox() // { version: '
|
|
12
|
+
* @example testedFirefox() // { version: '158.0.1', buildId: '20261019185856' }
|
|
15
13
|
*/
|
|
16
14
|
export declare function testedFirefox(): FirefoxRelease;
|
|
17
15
|
/**
|
|
18
16
|
* What a Firefox's own files say against the tested release: undefined when it is the tested release, and otherwise a
|
|
19
17
|
* sentence naming both, for `doctor` and a run's record to say of a Firefox a target named itself.
|
|
20
18
|
*
|
|
21
|
-
* @example untestedFirefox({ version: '150.0', buildId: '20260901000000' }) // 'Firefox 150.0 build 20260901000000 is not the tested Firefox
|
|
19
|
+
* @example untestedFirefox({ version: '150.0', buildId: '20260901000000' }) // 'Firefox 150.0 build 20260901000000 is not the tested Firefox 158.0.1 build 20261019185856.'
|
|
22
20
|
*/
|
|
23
21
|
export declare function untestedFirefox(release: FirefoxRelease | undefined, tested?: FirefoxRelease): string | undefined;
|
|
24
22
|
/**
|
|
25
|
-
* Whether this machine is one Retest runs Firefox on: macOS on Apple silicon
|
|
26
|
-
*
|
|
23
|
+
* Whether this machine is one Retest runs Firefox on: macOS on Apple silicon or Windows x64, the platforms Firefox is
|
|
24
|
+
* pinned for. Any other is refused by name rather than tried.
|
|
27
25
|
*
|
|
28
|
-
* @example firefoxPlatformProblem('linux', 'x64') // 'Retest runs Firefox on macOS on Apple silicon, and this machine is linux x64.'
|
|
26
|
+
* @example firefoxPlatformProblem('linux', 'x64') // 'Retest runs Firefox on macOS on Apple silicon and on Windows x64, and this machine is linux x64.'
|
|
29
27
|
*/
|
|
30
28
|
export declare function firefoxPlatformProblem(platform?: NodeJS.Platform, arch?: string): string | undefined;
|
|
31
29
|
/**
|
|
32
30
|
* The Firefox a target launches: the path it names, at whatever version it is (its real version and build are what the
|
|
33
|
-
* run records); else the pinned build in this user's Retest cache; else Firefox where
|
|
34
|
-
* files say it is the tested release, since the driver encodes that
|
|
35
|
-
* on an engine nobody exercised. Nothing is downloaded. A machine
|
|
36
|
-
* another release, or no Firefox at all fails setup by name,
|
|
31
|
+
* run records); else the pinned build in this user's Retest cache; else Firefox where the system installs it, the
|
|
32
|
+
* first of its folders that holds one, only when its files say it is the tested release, since the driver encodes that
|
|
33
|
+
* release's facts and another would run every test on an engine nobody exercised. Nothing is downloaded. A machine
|
|
34
|
+
* Retest does not run Firefox on, a system Firefox of another release, or no Firefox at all fails setup by name,
|
|
35
|
+
* saying what it found and the ways forward.
|
|
37
36
|
*
|
|
38
37
|
* @example await findFirefoxExecutable({ name: 'firefox', browser: 'firefox', headless: true }, 'web', process.env)
|
|
39
38
|
*/
|
|
@@ -48,9 +47,10 @@ export declare function findFirefoxExecutable(target: LoadedFirefoxTarget, app:
|
|
|
48
47
|
}>;
|
|
49
48
|
/**
|
|
50
49
|
* The version and build a Firefox binary's app states in its `application.ini`, read from the file without starting
|
|
51
|
-
* anything, or undefined when the binary is not inside an app whose file says.
|
|
50
|
+
* anything, or undefined when the binary is not inside an app whose file says. On macOS the file is in the app
|
|
51
|
+
* bundle's resources; on Windows it is beside firefox.exe.
|
|
52
52
|
*
|
|
53
|
-
* @example await readFirefoxRelease('/Applications/Firefox.app/Contents/MacOS/firefox') // { version: '
|
|
53
|
+
* @example await readFirefoxRelease('/Applications/Firefox.app/Contents/MacOS/firefox') // { version: '158.0.1', buildId: '20261019185856' }
|
|
54
54
|
*/
|
|
55
|
-
export declare function readFirefoxRelease(executablePath: string): Promise<FirefoxRelease | undefined>;
|
|
55
|
+
export declare function readFirefoxRelease(executablePath: string, platform?: NodeJS.Platform): Promise<FirefoxRelease | undefined>;
|
|
56
56
|
//# sourceMappingURL=executable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executable.d.ts","sourceRoot":"","sources":["../../../src/browser/firefox/executable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"executable.d.ts","sourceRoot":"","sources":["../../../src/browser/firefox/executable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAA;AASzD,4GAA4G;AAC5G,MAAM,MAAM,cAAc,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAA;AAE7E;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,cAAc,CAI9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,EAAE,MAAM,GAAE,cAAgC,GAAG,MAAM,GAAG,SAAS,CAGjI;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAAE,IAAI,GAAE,MAAqB,GAAG,MAAM,GAAG,SAAS,CAIpI;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACjD,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACpC,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAyBvE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CASlJ"}
|