@qawolf/cli 1.7.2 → 1.7.3
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/cli.js +366 -257
- package/package.json +1 -2
package/dist/cli.js
CHANGED
|
@@ -8514,7 +8514,7 @@ var require_BufferList = __commonJS((exports, module) => {
|
|
|
8514
8514
|
this.head = this.tail = null;
|
|
8515
8515
|
this.length = 0;
|
|
8516
8516
|
};
|
|
8517
|
-
BufferList.prototype.join = function
|
|
8517
|
+
BufferList.prototype.join = function join35(s3) {
|
|
8518
8518
|
if (this.length === 0)
|
|
8519
8519
|
return "";
|
|
8520
8520
|
var p3 = this.head;
|
|
@@ -23070,7 +23070,7 @@ var require_BufferList2 = __commonJS((exports, module) => {
|
|
|
23070
23070
|
this.head = this.tail = null;
|
|
23071
23071
|
this.length = 0;
|
|
23072
23072
|
};
|
|
23073
|
-
BufferList.prototype.join = function
|
|
23073
|
+
BufferList.prototype.join = function join35(s3) {
|
|
23074
23074
|
if (this.length === 0)
|
|
23075
23075
|
return "";
|
|
23076
23076
|
var p3 = this.head;
|
|
@@ -155283,7 +155283,8 @@ var doctorMessages = {
|
|
|
155283
155283
|
playwright: {
|
|
155284
155284
|
notFound: (path) => toolNotInstalled("Playwright", path),
|
|
155285
155285
|
launchFailed: "Could not launch Playwright. Try reinstalling the qawolf CLI.",
|
|
155286
|
-
versionUnparseable: "Could not parse playwright version output"
|
|
155286
|
+
versionUnparseable: "Could not parse playwright version output",
|
|
155287
|
+
versionMismatch: (installed, pinned) => `Playwright ${installed} is installed but the flow runtime requires ${pinned}; local runs will fail to launch browsers. Run \`qawolf install\` to repair the runtime dependencies.`
|
|
155287
155288
|
},
|
|
155288
155289
|
appium: {
|
|
155289
155290
|
notFound: (path) => toolNotInstalled("Appium", path),
|
|
@@ -155395,11 +155396,20 @@ var initMessages = {
|
|
|
155395
155396
|
outro: "Run `qawolf auth login`, then `qawolf flows pull`, then `qawolf flows run`.",
|
|
155396
155397
|
createPackageJsonPrompt: "Create package.json (required to run flows)?",
|
|
155397
155398
|
skippedCreatingPackageJson: "Skipped package.json",
|
|
155398
|
-
|
|
155399
|
+
skippedUpdatingPackageJson: "Skipped updating package.json",
|
|
155399
155400
|
createdPackageJson: "Created package.json",
|
|
155400
|
-
packageJsonInvalidJson: "package.json
|
|
155401
|
-
|
|
155402
|
-
|
|
155401
|
+
packageJsonInvalidJson: "`package.json` contains invalid JSON. Correct the JSON syntax, then run `qawolf init` again.",
|
|
155402
|
+
packageJsonNotAnObject: "`package.json` must contain a JSON object. Update it, then run `qawolf init` again.",
|
|
155403
|
+
packageJsonMalformedSection: (field) => `The \`${field}\` field in \`package.json\` must be a JSON object. Update it, then run \`qawolf init\` again.`,
|
|
155404
|
+
packageJsonHasTestE2e: "package.json already has `test:e2e` — leaving it as is",
|
|
155405
|
+
packageJsonUpToDate: "package.json already configured — nothing to update",
|
|
155406
|
+
typeChanged: (from) => `Changed "type" from "${from}" to "module" — .js files in this package now load as ES modules.`,
|
|
155407
|
+
pkgChanges: {
|
|
155408
|
+
script: "add `test:e2e` script",
|
|
155409
|
+
type: 'set "type": "module"',
|
|
155410
|
+
flowsDep: "add @qawolf/flows dependency"
|
|
155411
|
+
},
|
|
155412
|
+
updatePackageJsonPrompt: (changes) => `Update package.json (${changes.join(", ")})?`,
|
|
155403
155413
|
updatedPackageJson: "Updated package.json",
|
|
155404
155414
|
overwritePrompt: (relPath) => `Overwrite ${relPath}?`,
|
|
155405
155415
|
skippedFile: (relPath) => `Skipped ${relPath}`,
|
|
@@ -174616,7 +174626,7 @@ function startUpdateCheck(deps) {
|
|
|
174616
174626
|
// package.json
|
|
174617
174627
|
var package_default = {
|
|
174618
174628
|
name: "@qawolf/cli",
|
|
174619
|
-
version: "1.7.
|
|
174629
|
+
version: "1.7.3",
|
|
174620
174630
|
description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
174621
174631
|
keywords: [
|
|
174622
174632
|
"automation",
|
|
@@ -174676,7 +174686,6 @@ var package_default = {
|
|
|
174676
174686
|
"@clack/prompts": "1.5.1",
|
|
174677
174687
|
"@napi-rs/keyring": "1.3.0",
|
|
174678
174688
|
"@oxc-node/core": "0.1.0",
|
|
174679
|
-
"@playwright/test": "1.62.0",
|
|
174680
174689
|
"@qawolf/api-contracts": "0.22.0",
|
|
174681
174690
|
"@qawolf/emails": "1.1.1",
|
|
174682
174691
|
"@qawolf/flow-targets": "1.0.0",
|
|
@@ -174770,7 +174779,7 @@ function withContext(signals, fn) {
|
|
|
174770
174779
|
try {
|
|
174771
174780
|
const result = await fn(ctx);
|
|
174772
174781
|
if (result !== undefined) {
|
|
174773
|
-
ctx.ui.error(result.error);
|
|
174782
|
+
ctx.ui.error(result.error, result.errorBody);
|
|
174774
174783
|
process.exitCode = result.exitCode ?? 1;
|
|
174775
174784
|
}
|
|
174776
174785
|
} catch (err) {
|
|
@@ -174803,7 +174812,7 @@ function withAuthContext(signals, fn, deps = {}) {
|
|
|
174803
174812
|
apiKeySource: resolved.source
|
|
174804
174813
|
});
|
|
174805
174814
|
if (result !== undefined) {
|
|
174806
|
-
ctx.ui.error(result.error);
|
|
174815
|
+
ctx.ui.error(result.error, result.errorBody);
|
|
174807
174816
|
process.exitCode = result.exitCode ?? 1;
|
|
174808
174817
|
}
|
|
174809
174818
|
} catch (err) {
|
|
@@ -175047,9 +175056,6 @@ function nodeModulesBinCandidates(envDir, name, platform) {
|
|
|
175047
175056
|
function appiumCliCandidates(envDir, platform) {
|
|
175048
175057
|
return nodeModulesBinCandidates(envDir, "appium", platform);
|
|
175049
175058
|
}
|
|
175050
|
-
function playwrightCliCandidates(envDir, platform) {
|
|
175051
|
-
return nodeModulesBinCandidates(envDir, "playwright", platform);
|
|
175052
|
-
}
|
|
175053
175059
|
|
|
175054
175060
|
// src/domains/doctor/checks/androidAppium.ts
|
|
175055
175061
|
function firstLine(result) {
|
|
@@ -175412,19 +175418,48 @@ async function checkNpmRegistry(deps) {
|
|
|
175412
175418
|
return { name: "npm-registry", status: "pass" };
|
|
175413
175419
|
}
|
|
175414
175420
|
|
|
175421
|
+
// src/core/playwrightCli.ts
|
|
175422
|
+
import { join as join13 } from "node:path";
|
|
175423
|
+
function playwrightCliJsPath(envDir) {
|
|
175424
|
+
return join13(envDir, "node_modules", "playwright", "cli.js");
|
|
175425
|
+
}
|
|
175426
|
+
function playwrightCliInvocation(args) {
|
|
175427
|
+
return {
|
|
175428
|
+
cmd: args.execPath,
|
|
175429
|
+
args: [playwrightCliJsPath(args.envDir), ...args.cliArgs],
|
|
175430
|
+
env: { BUN_BE_BUN: "1" }
|
|
175431
|
+
};
|
|
175432
|
+
}
|
|
175433
|
+
|
|
175434
|
+
// src/generated/dependencyVersions.ts
|
|
175435
|
+
var flowsVersion = "0.1.4";
|
|
175436
|
+
var playwrightVersion = "1.62.0";
|
|
175437
|
+
var emailsVersion = "1.1.1";
|
|
175438
|
+
var testkitVersion = "1.1.1";
|
|
175439
|
+
var appiumVersion = "2.11.3";
|
|
175440
|
+
var appiumXcuitestDriverVersion = "9.10.5";
|
|
175441
|
+
var appiumUiautomator2DriverVersion = "3.7.0";
|
|
175442
|
+
var expectWebdriverioVersion = "5.6.5";
|
|
175443
|
+
|
|
175415
175444
|
// src/domains/doctor/checks/playwright.ts
|
|
175416
175445
|
async function checkPlaywright(deps) {
|
|
175417
|
-
const
|
|
175418
|
-
const
|
|
175419
|
-
if (
|
|
175446
|
+
const { envDir } = deps;
|
|
175447
|
+
const cliJsPath = envDir === undefined ? undefined : playwrightCliJsPath(envDir);
|
|
175448
|
+
if (envDir === undefined || cliJsPath === undefined || !deps.checkExists(cliJsPath)) {
|
|
175420
175449
|
return {
|
|
175421
175450
|
name: "playwright",
|
|
175422
175451
|
status: "fail",
|
|
175423
|
-
detail: doctorMessages.playwright.notFound(
|
|
175452
|
+
detail: doctorMessages.playwright.notFound(cliJsPath)
|
|
175424
175453
|
};
|
|
175425
175454
|
}
|
|
175426
|
-
const
|
|
175427
|
-
|
|
175455
|
+
const invocation = playwrightCliInvocation({
|
|
175456
|
+
envDir,
|
|
175457
|
+
execPath: deps.execPath,
|
|
175458
|
+
cliArgs: ["--version"]
|
|
175459
|
+
});
|
|
175460
|
+
const result = await deps.spawn(invocation.cmd, invocation.args, {
|
|
175461
|
+
platform: deps.platform,
|
|
175462
|
+
env: invocation.env
|
|
175428
175463
|
});
|
|
175429
175464
|
if (result.exitCode < 0) {
|
|
175430
175465
|
return {
|
|
@@ -175446,6 +175481,14 @@ async function checkPlaywright(deps) {
|
|
|
175446
175481
|
detail: doctorMessages.playwright.versionUnparseable
|
|
175447
175482
|
};
|
|
175448
175483
|
}
|
|
175484
|
+
if (version2 !== playwrightVersion) {
|
|
175485
|
+
return {
|
|
175486
|
+
name: "playwright",
|
|
175487
|
+
status: "fail",
|
|
175488
|
+
version: version2,
|
|
175489
|
+
detail: doctorMessages.playwright.versionMismatch(version2, playwrightVersion)
|
|
175490
|
+
};
|
|
175491
|
+
}
|
|
175449
175492
|
return { name: "playwright", status: "pass", version: version2 };
|
|
175450
175493
|
}
|
|
175451
175494
|
|
|
@@ -175466,6 +175509,7 @@ async function runChecks(deps) {
|
|
|
175466
175509
|
}),
|
|
175467
175510
|
checkPlaywright({
|
|
175468
175511
|
spawn: deps.spawn,
|
|
175512
|
+
execPath: deps.execPath,
|
|
175469
175513
|
envDir: deps.envDir,
|
|
175470
175514
|
platform: deps.platform,
|
|
175471
175515
|
checkExists: deps.checkExists
|
|
@@ -175525,11 +175569,11 @@ function renderResults(ui, results) {
|
|
|
175525
175569
|
}
|
|
175526
175570
|
|
|
175527
175571
|
// src/domains/flows/ensureDeps.ts
|
|
175528
|
-
import { dirname as dirname4, join as
|
|
175572
|
+
import { dirname as dirname4, join as join14 } from "node:path";
|
|
175529
175573
|
function findEnvDir(flowPath, fs2) {
|
|
175530
175574
|
let dir = dirname4(flowPath);
|
|
175531
175575
|
while (true) {
|
|
175532
|
-
if (fs2.existsSync(
|
|
175576
|
+
if (fs2.existsSync(join14(dir, "package.json")))
|
|
175533
175577
|
return dir;
|
|
175534
175578
|
const parent = dirname4(dir);
|
|
175535
175579
|
if (parent === dir)
|
|
@@ -175555,7 +175599,7 @@ function resolveProjectDirSafe(files, fs2) {
|
|
|
175555
175599
|
}
|
|
175556
175600
|
|
|
175557
175601
|
// src/domains/flows/expand.ts
|
|
175558
|
-
import { join as
|
|
175602
|
+
import { join as join15, resolve as resolve3 } from "node:path";
|
|
175559
175603
|
|
|
175560
175604
|
// node_modules/tinyglobby/dist/index.mjs
|
|
175561
175605
|
import { readdir, readdirSync, realpath, realpathSync, stat, statSync } from "fs";
|
|
@@ -176446,11 +176490,11 @@ function makePeekFlowMeta(fs2) {
|
|
|
176446
176490
|
};
|
|
176447
176491
|
}
|
|
176448
176492
|
async function resolveGlobRoots(cwd, fs2) {
|
|
176449
|
-
const qawolfPath =
|
|
176493
|
+
const qawolfPath = join15(cwd, ".qawolf");
|
|
176450
176494
|
let envDirs = [];
|
|
176451
176495
|
try {
|
|
176452
176496
|
const entries = await fs2.readdirWithTypes(qawolfPath);
|
|
176453
|
-
envDirs = entries.filter((e) => e.isDirectory()).map((e) =>
|
|
176497
|
+
envDirs = entries.filter((e) => e.isDirectory()).map((e) => join15(qawolfPath, e.name));
|
|
176454
176498
|
} catch {}
|
|
176455
176499
|
return [cwd, ...envDirs];
|
|
176456
176500
|
}
|
|
@@ -176475,21 +176519,11 @@ async function expandPatterns(patterns, cwd, logger, fs2) {
|
|
|
176475
176519
|
}
|
|
176476
176520
|
|
|
176477
176521
|
// src/domains/runtimeEnv/clearRuntimeEnv.ts
|
|
176478
|
-
import { join as
|
|
176522
|
+
import { join as join17 } from "node:path";
|
|
176479
176523
|
|
|
176480
176524
|
// src/domains/runtimeEnv/managedEnvDir.ts
|
|
176481
176525
|
import { createHash } from "node:crypto";
|
|
176482
|
-
import { join as
|
|
176483
|
-
|
|
176484
|
-
// src/generated/dependencyVersions.ts
|
|
176485
|
-
var flowsVersion = "0.1.4";
|
|
176486
|
-
var playwrightVersion = "1.62.0";
|
|
176487
|
-
var emailsVersion = "1.1.1";
|
|
176488
|
-
var testkitVersion = "1.1.1";
|
|
176489
|
-
var appiumVersion = "2.11.3";
|
|
176490
|
-
var appiumXcuitestDriverVersion = "9.10.5";
|
|
176491
|
-
var appiumUiautomator2DriverVersion = "3.7.0";
|
|
176492
|
-
var expectWebdriverioVersion = "5.6.5";
|
|
176526
|
+
import { join as join16, resolve as resolve4 } from "node:path";
|
|
176493
176527
|
|
|
176494
176528
|
// src/domains/runtimeEnv/pinnedPackages.ts
|
|
176495
176529
|
var pinnedPackages = [
|
|
@@ -176522,19 +176556,19 @@ function managedEnvBaseDir() {
|
|
|
176522
176556
|
const override = process.env["QAWOLF_RUNTIME_DIR"]?.trim();
|
|
176523
176557
|
if (override)
|
|
176524
176558
|
return resolve4(override);
|
|
176525
|
-
return
|
|
176559
|
+
return join16(getDataDir(), "runtime");
|
|
176526
176560
|
}
|
|
176527
176561
|
function runStagingRoot() {
|
|
176528
176562
|
return `${managedEnvBaseDir()}-runs`;
|
|
176529
176563
|
}
|
|
176530
176564
|
function managedEnvDir() {
|
|
176531
|
-
return
|
|
176565
|
+
return join16(managedEnvBaseDir(), managedEnvHash());
|
|
176532
176566
|
}
|
|
176533
176567
|
async function scaffoldManagedEnv(dir, fs2) {
|
|
176534
176568
|
await fs2.mkdir(dir, { recursive: true });
|
|
176535
176569
|
const dependencies = Object.fromEntries(pinnedPackages.map(({ name, version: version2 }) => [name, version2]));
|
|
176536
|
-
await fs2.writeFile(
|
|
176537
|
-
await fs2.writeFile(
|
|
176570
|
+
await fs2.writeFile(join16(dir, "package.json"), JSON.stringify({ name: "qawolf-runtime", private: true, dependencies }, undefined, 2));
|
|
176571
|
+
await fs2.writeFile(join16(dir, ".npmrc"), `@qawolf:registry=https://registry.npmjs.org/
|
|
176538
176572
|
`);
|
|
176539
176573
|
}
|
|
176540
176574
|
|
|
@@ -176556,14 +176590,14 @@ async function isManagedRuntimeBase(dir, fs2) {
|
|
|
176556
176590
|
for (const entry of entries) {
|
|
176557
176591
|
if (!entry.isDirectory())
|
|
176558
176592
|
return false;
|
|
176559
|
-
if (!await hasRuntimeSentinel(
|
|
176593
|
+
if (!await hasRuntimeSentinel(join17(dir, entry.name), fs2))
|
|
176560
176594
|
return false;
|
|
176561
176595
|
}
|
|
176562
176596
|
return true;
|
|
176563
176597
|
}
|
|
176564
176598
|
async function hasRuntimeSentinel(hashDir, fs2) {
|
|
176565
176599
|
try {
|
|
176566
|
-
const pkg = JSON.parse(await fs2.readFile(
|
|
176600
|
+
const pkg = JSON.parse(await fs2.readFile(join17(hashDir, "package.json")));
|
|
176567
176601
|
return pkg.name === runtimeSentinel;
|
|
176568
176602
|
} catch {
|
|
176569
176603
|
return false;
|
|
@@ -176637,10 +176671,10 @@ function spawnNpmInstall(cwd, spawn2 = spawn) {
|
|
|
176637
176671
|
}
|
|
176638
176672
|
|
|
176639
176673
|
// src/domains/runtimeEnv/resolvePinned.ts
|
|
176640
|
-
import { join as
|
|
176674
|
+
import { join as join18 } from "node:path";
|
|
176641
176675
|
function readInstalledVersion(dir, pkgName, fs2) {
|
|
176642
176676
|
try {
|
|
176643
|
-
const pkgPath =
|
|
176677
|
+
const pkgPath = join18(dir, "node_modules", ...pkgName.split("/"), "package.json");
|
|
176644
176678
|
const raw = JSON.parse(fs2.readFileSync(pkgPath));
|
|
176645
176679
|
const { version: version2 } = raw;
|
|
176646
176680
|
return typeof version2 === "string" ? version2 : undefined;
|
|
@@ -176649,8 +176683,18 @@ function readInstalledVersion(dir, pkgName, fs2) {
|
|
|
176649
176683
|
}
|
|
176650
176684
|
}
|
|
176651
176685
|
var shims = [
|
|
176652
|
-
{
|
|
176653
|
-
|
|
176686
|
+
{
|
|
176687
|
+
name: "playwright",
|
|
176688
|
+
display: "node_modules/playwright/cli.js",
|
|
176689
|
+
candidates: (dir, _platform) => [
|
|
176690
|
+
playwrightCliJsPath(dir)
|
|
176691
|
+
]
|
|
176692
|
+
},
|
|
176693
|
+
{
|
|
176694
|
+
name: "appium",
|
|
176695
|
+
display: "node_modules/.bin/appium",
|
|
176696
|
+
candidates: appiumCliCandidates
|
|
176697
|
+
}
|
|
176654
176698
|
];
|
|
176655
176699
|
function pinnedResolutionFailures(dir, fs2, platform) {
|
|
176656
176700
|
const failures = [];
|
|
@@ -176660,16 +176704,16 @@ function pinnedResolutionFailures(dir, fs2, platform) {
|
|
|
176660
176704
|
failures.push({ kind: "package", name, pinned: version2, installed });
|
|
176661
176705
|
}
|
|
176662
176706
|
}
|
|
176663
|
-
for (const { name, candidates } of shims) {
|
|
176707
|
+
for (const { name, display, candidates } of shims) {
|
|
176664
176708
|
if (!candidates(dir, platform).some((p2) => fs2.existsSync(p2))) {
|
|
176665
|
-
failures.push({ kind: "shim", name });
|
|
176709
|
+
failures.push({ kind: "shim", name, display });
|
|
176666
176710
|
}
|
|
176667
176711
|
}
|
|
176668
176712
|
return failures;
|
|
176669
176713
|
}
|
|
176670
176714
|
function describePinnedFailure(failure) {
|
|
176671
176715
|
if (failure.kind === "shim") {
|
|
176672
|
-
return
|
|
176716
|
+
return `${failure.display} (missing)`;
|
|
176673
176717
|
}
|
|
176674
176718
|
return failure.installed === undefined ? `${failure.name} (missing, pinned ${failure.pinned})` : `${failure.name} ${failure.installed} (pinned ${failure.pinned})`;
|
|
176675
176719
|
}
|
|
@@ -176678,10 +176722,10 @@ function allPinnedResolved(dir, fs2, platform) {
|
|
|
176678
176722
|
}
|
|
176679
176723
|
|
|
176680
176724
|
// src/domains/runtimeEnv/shimDeps.ts
|
|
176681
|
-
import { join as
|
|
176725
|
+
import { join as join20 } from "node:path";
|
|
176682
176726
|
|
|
176683
176727
|
// src/shell/resolveExport.ts
|
|
176684
|
-
import { join as
|
|
176728
|
+
import { join as join19 } from "node:path";
|
|
176685
176729
|
function pickPath(entry, preference) {
|
|
176686
176730
|
if (typeof entry === "string")
|
|
176687
176731
|
return entry;
|
|
@@ -176713,28 +176757,28 @@ function resolveFromEnvDir(envDir, specifier, preference = "esm", fs2 = makeDefa
|
|
|
176713
176757
|
const pkgName = parts.slice(0, pkgPartCount).join("/");
|
|
176714
176758
|
const rest = parts.slice(pkgPartCount);
|
|
176715
176759
|
const subpath = rest.length > 0 ? "./" + rest.join("/") : ".";
|
|
176716
|
-
const pkgDir =
|
|
176760
|
+
const pkgDir = join19(envDir, "node_modules", ...pkgName.split("/"));
|
|
176717
176761
|
let pkg;
|
|
176718
176762
|
try {
|
|
176719
|
-
pkg = JSON.parse(fs2.readFileSync(
|
|
176763
|
+
pkg = JSON.parse(fs2.readFileSync(join19(pkgDir, "package.json")));
|
|
176720
176764
|
} catch (err) {
|
|
176721
176765
|
if (isNoEntError(err))
|
|
176722
|
-
throw new Error(`Package '${pkgName}' not found in ${
|
|
176766
|
+
throw new Error(`Package '${pkgName}' not found in ${join19(envDir, "node_modules")}`, { cause: err });
|
|
176723
176767
|
throw err;
|
|
176724
176768
|
}
|
|
176725
176769
|
const exportsMap = normalizeExports(pkg.exports);
|
|
176726
176770
|
const entry = exportsMap?.[subpath];
|
|
176727
176771
|
const relative3 = pickPath(entry, preference) ?? (subpath === "." ? pkg.module ?? pkg.main : undefined);
|
|
176728
176772
|
if (!relative3) {
|
|
176729
|
-
throw new Error(`No entry for "${subpath}" in exports of ${
|
|
176773
|
+
throw new Error(`No entry for "${subpath}" in exports of ${join19(pkgDir, "package.json")}`);
|
|
176730
176774
|
}
|
|
176731
|
-
return
|
|
176775
|
+
return join19(pkgDir, relative3);
|
|
176732
176776
|
}
|
|
176733
176777
|
|
|
176734
176778
|
// src/domains/runtimeEnv/shimDeps.ts
|
|
176735
176779
|
function readShimMarker(shimDir, fs2) {
|
|
176736
176780
|
try {
|
|
176737
|
-
const pkg = JSON.parse(fs2.readFileSync(
|
|
176781
|
+
const pkg = JSON.parse(fs2.readFileSync(join20(shimDir, "package.json")));
|
|
176738
176782
|
if (pkg._qawolf_format) {
|
|
176739
176783
|
return {
|
|
176740
176784
|
_qawolf_version: pkg._qawolf_version ?? "",
|
|
@@ -176750,11 +176794,11 @@ function resolveBunBuild(bunBuild) {
|
|
|
176750
176794
|
return bunBuild === false ? undefined : { build: bunBuild };
|
|
176751
176795
|
}
|
|
176752
176796
|
async function removeStaleShims(flowsDir, flowsDeps, fs2) {
|
|
176753
|
-
const shimsDir =
|
|
176797
|
+
const shimsDir = join20(flowsDir, "node_modules");
|
|
176754
176798
|
if (!fs2.existsSync(shimsDir))
|
|
176755
176799
|
return;
|
|
176756
176800
|
for (const dep of flowsDeps) {
|
|
176757
|
-
const shimDepDir =
|
|
176801
|
+
const shimDepDir = join20(shimsDir, ...dep.split("/"));
|
|
176758
176802
|
if (readShimMarker(shimDepDir, fs2)) {
|
|
176759
176803
|
await fs2.rm(shimDepDir, { recursive: true, force: true });
|
|
176760
176804
|
}
|
|
@@ -176763,17 +176807,17 @@ async function removeStaleShims(flowsDir, flowsDeps, fs2) {
|
|
|
176763
176807
|
async function buildDepShim(args) {
|
|
176764
176808
|
const { envDir, flowsDir, dep, fs: fs2, build: build2 } = args;
|
|
176765
176809
|
const depParts = dep.split("/");
|
|
176766
|
-
const depDir =
|
|
176810
|
+
const depDir = join20(envDir, "node_modules", ...depParts);
|
|
176767
176811
|
if (!fs2.existsSync(depDir))
|
|
176768
176812
|
return;
|
|
176769
176813
|
let depVersion;
|
|
176770
176814
|
try {
|
|
176771
|
-
const pkg = JSON.parse(fs2.readFileSync(
|
|
176815
|
+
const pkg = JSON.parse(fs2.readFileSync(join20(depDir, "package.json")));
|
|
176772
176816
|
depVersion = pkg.version ?? "unknown";
|
|
176773
176817
|
} catch {
|
|
176774
176818
|
depVersion = "unknown";
|
|
176775
176819
|
}
|
|
176776
|
-
const shimDir =
|
|
176820
|
+
const shimDir = join20(flowsDir, "node_modules", ...depParts);
|
|
176777
176821
|
if (fs2.existsSync(shimDir)) {
|
|
176778
176822
|
const marker = readShimMarker(shimDir, fs2);
|
|
176779
176823
|
if (!marker)
|
|
@@ -176800,20 +176844,20 @@ async function buildDepShim(args) {
|
|
|
176800
176844
|
}
|
|
176801
176845
|
const shimCode = await output.text();
|
|
176802
176846
|
await fs2.mkdir(shimDir, { recursive: true });
|
|
176803
|
-
await fs2.writeFile(
|
|
176847
|
+
await fs2.writeFile(join20(shimDir, "package.json"), JSON.stringify({
|
|
176804
176848
|
name: dep,
|
|
176805
176849
|
_qawolf_version: depVersion,
|
|
176806
176850
|
_qawolf_format: "bun-build-v1"
|
|
176807
176851
|
}));
|
|
176808
|
-
await fs2.writeFile(
|
|
176852
|
+
await fs2.writeFile(join20(shimDir, "index.js"), shimCode);
|
|
176809
176853
|
}
|
|
176810
176854
|
async function shimFlowsDeps(envDir, fs2 = makeDefaultFs(), bunBuild) {
|
|
176811
|
-
const flowsDir =
|
|
176855
|
+
const flowsDir = join20(envDir, "node_modules", "@qawolf", "flows");
|
|
176812
176856
|
if (!fs2.existsSync(flowsDir))
|
|
176813
176857
|
return;
|
|
176814
176858
|
let flowsDeps;
|
|
176815
176859
|
try {
|
|
176816
|
-
const flowsPkg = JSON.parse(fs2.readFileSync(
|
|
176860
|
+
const flowsPkg = JSON.parse(fs2.readFileSync(join20(flowsDir, "package.json")));
|
|
176817
176861
|
flowsDeps = Object.keys(flowsPkg.dependencies ?? {});
|
|
176818
176862
|
} catch {
|
|
176819
176863
|
return;
|
|
@@ -176937,6 +176981,7 @@ async function handleDoctor(ctx, opts) {
|
|
|
176937
176981
|
apiKey: resolved?.key,
|
|
176938
176982
|
fetch: globalThis.fetch,
|
|
176939
176983
|
spawn: defaultSpawn,
|
|
176984
|
+
execPath: process.execPath,
|
|
176940
176985
|
apiBaseUrl: ctx.apiBaseUrl,
|
|
176941
176986
|
enginesNode: package_default.engines.node,
|
|
176942
176987
|
processVersion: process.version,
|
|
@@ -177079,11 +177124,11 @@ async function flowsListRemote(ctx, pattern, options) {
|
|
|
177079
177124
|
}
|
|
177080
177125
|
|
|
177081
177126
|
// src/domains/flows/pull/handler.ts
|
|
177082
|
-
import { dirname as dirname7, join as
|
|
177127
|
+
import { dirname as dirname7, join as join25, resolve as resolve8 } from "node:path";
|
|
177083
177128
|
|
|
177084
177129
|
// src/shell/manifest/io.ts
|
|
177085
177130
|
import { createHash as createHash2 } from "node:crypto";
|
|
177086
|
-
import { join as
|
|
177131
|
+
import { join as join21 } from "node:path";
|
|
177087
177132
|
var manifestFilename = ".manifest.json";
|
|
177088
177133
|
var flowEntrySchema = exports_external.object({
|
|
177089
177134
|
path: exports_external.string(),
|
|
@@ -177102,7 +177147,7 @@ var manifestSchema = exports_external.object({
|
|
|
177102
177147
|
async function readManifest(envDir, fs2 = makeDefaultFs()) {
|
|
177103
177148
|
let raw;
|
|
177104
177149
|
try {
|
|
177105
|
-
raw = await fs2.readFile(
|
|
177150
|
+
raw = await fs2.readFile(join21(envDir, manifestFilename));
|
|
177106
177151
|
} catch (err) {
|
|
177107
177152
|
if (isNoEntError(err))
|
|
177108
177153
|
return "missing";
|
|
@@ -177130,7 +177175,7 @@ async function readManifest(envDir, fs2 = makeDefaultFs()) {
|
|
|
177130
177175
|
}
|
|
177131
177176
|
async function writeManifest(envDir, manifest, fs2 = makeDefaultFs()) {
|
|
177132
177177
|
const body = JSON.stringify(manifest, undefined, 2);
|
|
177133
|
-
await fs2.writeFile(
|
|
177178
|
+
await fs2.writeFile(join21(envDir, manifestFilename), `${body}
|
|
177134
177179
|
`);
|
|
177135
177180
|
}
|
|
177136
177181
|
function hashFile(absPath, fs2 = makeDefaultFs()) {
|
|
@@ -177265,7 +177310,7 @@ async function checkSafety(args) {
|
|
|
177265
177310
|
}
|
|
177266
177311
|
|
|
177267
177312
|
// src/domains/flows/pull/bundle.ts
|
|
177268
|
-
import { join as
|
|
177313
|
+
import { join as join22, relative as relative4 } from "node:path";
|
|
177269
177314
|
async function flattenSingleWrapper(dir, fs2 = makeDefaultFs()) {
|
|
177270
177315
|
const entries = await fs2.readdir(dir);
|
|
177271
177316
|
if (entries.length !== 1)
|
|
@@ -177273,12 +177318,12 @@ async function flattenSingleWrapper(dir, fs2 = makeDefaultFs()) {
|
|
|
177273
177318
|
const innerName = entries[0];
|
|
177274
177319
|
if (!innerName)
|
|
177275
177320
|
return;
|
|
177276
|
-
const inner =
|
|
177321
|
+
const inner = join22(dir, innerName);
|
|
177277
177322
|
const innerStat = await fs2.stat(inner);
|
|
177278
177323
|
if (!innerStat.isDirectory())
|
|
177279
177324
|
return;
|
|
177280
177325
|
for (const e of await fs2.readdir(inner)) {
|
|
177281
|
-
await fs2.rename(
|
|
177326
|
+
await fs2.rename(join22(inner, e), join22(dir, e));
|
|
177282
177327
|
}
|
|
177283
177328
|
const leftovers = await fs2.readdir(inner);
|
|
177284
177329
|
if (leftovers.length > 0) {
|
|
@@ -177297,7 +177342,7 @@ async function buildManifest(args, fs2 = makeDefaultFs()) {
|
|
|
177297
177342
|
const flowPaths = await walkForFlows(args.bundleDir, fs2);
|
|
177298
177343
|
const flows = await Promise.all(flowPaths.map(async (rel) => ({
|
|
177299
177344
|
path: rel,
|
|
177300
|
-
contentHash: await hashFile(
|
|
177345
|
+
contentHash: await hashFile(join22(args.bundleDir, rel), fs2)
|
|
177301
177346
|
})));
|
|
177302
177347
|
return {
|
|
177303
177348
|
envId: args.envId,
|
|
@@ -177318,7 +177363,7 @@ async function walkForFlows(root, fs2) {
|
|
|
177318
177363
|
async function walk(current, root, out, fs2) {
|
|
177319
177364
|
const entries = await fs2.readdirWithTypes(current);
|
|
177320
177365
|
for (const e of entries) {
|
|
177321
|
-
const abs =
|
|
177366
|
+
const abs = join22(current, e.name);
|
|
177322
177367
|
if (e.isDirectory()) {
|
|
177323
177368
|
await walk(abs, root, out, fs2);
|
|
177324
177369
|
} else if (e.isFile() && flowExtensions.some((ext) => e.name.endsWith(ext))) {
|
|
@@ -177331,11 +177376,11 @@ async function sampleQawolfCommittedAt(bundleDir, fs2 = makeDefaultFs()) {
|
|
|
177331
177376
|
const sample = flowPaths[0];
|
|
177332
177377
|
if (!sample)
|
|
177333
177378
|
return;
|
|
177334
|
-
return (await fs2.stat(
|
|
177379
|
+
return (await fs2.stat(join22(bundleDir, sample))).mtime.toISOString();
|
|
177335
177380
|
}
|
|
177336
177381
|
|
|
177337
177382
|
// src/domains/flows/pull/applyTeamStorageRewrite.ts
|
|
177338
|
-
import { join as
|
|
177383
|
+
import { join as join23, relative as relative5 } from "node:path";
|
|
177339
177384
|
|
|
177340
177385
|
// src/domains/flows/pull/rewriteTeamStorage.ts
|
|
177341
177386
|
var runnerMountPrefix = "/home/wolf/team-storage/";
|
|
@@ -177371,7 +177416,7 @@ function isFlowFile(name) {
|
|
|
177371
177416
|
async function walk2(dir, out, fs2) {
|
|
177372
177417
|
const entries = await fs2.readdirWithTypes(dir);
|
|
177373
177418
|
for (const e of entries) {
|
|
177374
|
-
const abs =
|
|
177419
|
+
const abs = join23(dir, e.name);
|
|
177375
177420
|
if (e.isDirectory()) {
|
|
177376
177421
|
await walk2(abs, out, fs2);
|
|
177377
177422
|
} else if (e.isFile() && isSourceFile(e.name)) {
|
|
@@ -177399,7 +177444,7 @@ async function applyTeamStorageRewrite(rootDir, fs2 = makeDefaultFs()) {
|
|
|
177399
177444
|
}
|
|
177400
177445
|
|
|
177401
177446
|
// src/domains/flows/pull/envVars.ts
|
|
177402
|
-
import { join as
|
|
177447
|
+
import { join as join24 } from "node:path";
|
|
177403
177448
|
|
|
177404
177449
|
// src/core/dotenv.ts
|
|
177405
177450
|
var bareKeyPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
@@ -177464,7 +177509,7 @@ function unquote(escaped) {
|
|
|
177464
177509
|
async function writeEnvFile(envDir, vars, fs2 = makeDefaultFs()) {
|
|
177465
177510
|
if (Object.keys(vars).length === 0)
|
|
177466
177511
|
return;
|
|
177467
|
-
await fs2.writeFile(
|
|
177512
|
+
await fs2.writeFile(join24(envDir, ".env"), serializeDotenv(vars), {
|
|
177468
177513
|
mode: 384
|
|
177469
177514
|
});
|
|
177470
177515
|
}
|
|
@@ -180837,8 +180882,8 @@ async function handleFlowsPull(ctx, opts, deps) {
|
|
|
180837
180882
|
ctx.ui.error(validation.error);
|
|
180838
180883
|
return { error: validation.error };
|
|
180839
180884
|
}
|
|
180840
|
-
const destAbs = resolve8(opts.out ??
|
|
180841
|
-
const assetsAbs =
|
|
180885
|
+
const destAbs = resolve8(opts.out ?? join25(".qawolf", opts.env));
|
|
180886
|
+
const assetsAbs = join25(dirname7(destAbs), "assets");
|
|
180842
180887
|
await resolvedDeps.fs.mkdir(assetsAbs, { recursive: true });
|
|
180843
180888
|
const yes = opts.yes ?? false;
|
|
180844
180889
|
let archive;
|
|
@@ -180904,7 +180949,7 @@ async function handleFlowsPull(ctx, opts, deps) {
|
|
|
180904
180949
|
assetDownloadedCount: assetResult.downloadedCount,
|
|
180905
180950
|
assetReusedCount: assetResult.reusedCount,
|
|
180906
180951
|
assetSkippedCount: assetResult.skippedCount,
|
|
180907
|
-
manifestPath:
|
|
180952
|
+
manifestPath: join25(result.envDir, manifestFilename)
|
|
180908
180953
|
}, "");
|
|
180909
180954
|
}
|
|
180910
180955
|
} finally {
|
|
@@ -181090,6 +181135,72 @@ function buildPatternArgs(pattern) {
|
|
|
181090
181135
|
return pattern ? [pattern] : [];
|
|
181091
181136
|
}
|
|
181092
181137
|
|
|
181138
|
+
// src/shell/reporter/createCompositeReporter.ts
|
|
181139
|
+
function callEach(reporters, pick2, event) {
|
|
181140
|
+
for (const r2 of reporters) {
|
|
181141
|
+
try {
|
|
181142
|
+
pick2(r2)?.(event);
|
|
181143
|
+
} catch (err) {
|
|
181144
|
+
process.stderr.write(`[reporter error] ${String(err)}
|
|
181145
|
+
`);
|
|
181146
|
+
}
|
|
181147
|
+
}
|
|
181148
|
+
}
|
|
181149
|
+
function createCompositeReporter(reporters) {
|
|
181150
|
+
return {
|
|
181151
|
+
onFlowStart: (e) => callEach(reporters, (r2) => r2.onFlowStart, e),
|
|
181152
|
+
onFlowPass: (e) => callEach(reporters, (r2) => r2.onFlowPass, e),
|
|
181153
|
+
onFlowFail: (e) => callEach(reporters, (r2) => r2.onFlowFail, e),
|
|
181154
|
+
onTestStart: (e) => callEach(reporters, (r2) => r2.onTestStart, e),
|
|
181155
|
+
onTestResult: (e) => callEach(reporters, (r2) => r2.onTestResult, e),
|
|
181156
|
+
onScreenshot: (e) => callEach(reporters, (r2) => r2.onScreenshot, e),
|
|
181157
|
+
onRunComplete: (e) => callEach(reporters, (r2) => r2.onRunComplete, e)
|
|
181158
|
+
};
|
|
181159
|
+
}
|
|
181160
|
+
|
|
181161
|
+
// src/shell/reporter/formatErrorWithCause.ts
|
|
181162
|
+
function filterStack(stack) {
|
|
181163
|
+
const cwd = process.cwd();
|
|
181164
|
+
return stack.split(`
|
|
181165
|
+
`).filter((line) => {
|
|
181166
|
+
if (!/^\s+at /.test(line))
|
|
181167
|
+
return true;
|
|
181168
|
+
return !line.includes("node_modules") && !line.includes("dist/cli.js");
|
|
181169
|
+
}).map((line) => {
|
|
181170
|
+
if (!/^\s+at /.test(line))
|
|
181171
|
+
return line;
|
|
181172
|
+
return line.replace(`file://${cwd}/`, "").replace(`${cwd}/`, "");
|
|
181173
|
+
}).join(`
|
|
181174
|
+
`);
|
|
181175
|
+
}
|
|
181176
|
+
function renderCause(cause) {
|
|
181177
|
+
if (cause instanceof Error)
|
|
181178
|
+
return filterStack(cause.stack ?? cause.message);
|
|
181179
|
+
if (typeof cause === "object" && cause !== null) {
|
|
181180
|
+
const obj = cause;
|
|
181181
|
+
if (typeof obj["message"] === "string")
|
|
181182
|
+
return obj["message"];
|
|
181183
|
+
try {
|
|
181184
|
+
return JSON.stringify(cause);
|
|
181185
|
+
} catch {
|
|
181186
|
+
return String(cause);
|
|
181187
|
+
}
|
|
181188
|
+
}
|
|
181189
|
+
return String(cause);
|
|
181190
|
+
}
|
|
181191
|
+
function formatErrorWithCause(err) {
|
|
181192
|
+
const parts = [String(err)];
|
|
181193
|
+
let cause = err.cause;
|
|
181194
|
+
while (cause !== undefined && cause !== null) {
|
|
181195
|
+
parts.push(`Caused by: ${renderCause(cause)}`);
|
|
181196
|
+
if (!(cause instanceof Error))
|
|
181197
|
+
break;
|
|
181198
|
+
cause = cause.cause;
|
|
181199
|
+
}
|
|
181200
|
+
return parts.join(`
|
|
181201
|
+
`);
|
|
181202
|
+
}
|
|
181203
|
+
|
|
181093
181204
|
// src/domains/runner/runAndroidFlowUtils.ts
|
|
181094
181205
|
import { parseExecutionTarget as parseExecutionTarget3 } from "@qawolf/flow-targets";
|
|
181095
181206
|
|
|
@@ -181437,9 +181548,16 @@ async function flowsRun(ctx, files, flags, deps) {
|
|
|
181437
181548
|
return { error: runnerMessages.androidWorkersUnsupported, exitCode: 2 };
|
|
181438
181549
|
}
|
|
181439
181550
|
const { webOptions, androidOptions } = buildRunOptions(flags);
|
|
181551
|
+
const failureDetails = [];
|
|
181552
|
+
const reporter = ctx.outputMode === "json" ? createCompositeReporter([
|
|
181553
|
+
deps.reporter,
|
|
181554
|
+
{
|
|
181555
|
+
onFlowFail: ({ err }) => failureDetails.push(formatErrorWithCause(err))
|
|
181556
|
+
}
|
|
181557
|
+
]) : deps.reporter;
|
|
181440
181558
|
const result = await executeFlows({
|
|
181441
181559
|
ctx,
|
|
181442
|
-
deps,
|
|
181560
|
+
deps: { ...deps, reporter },
|
|
181443
181561
|
flags,
|
|
181444
181562
|
flows,
|
|
181445
181563
|
webFlows,
|
|
@@ -181467,7 +181585,13 @@ async function flowsRun(ctx, files, flags, deps) {
|
|
|
181467
181585
|
deps.reporter.onRunComplete?.({ summary });
|
|
181468
181586
|
ctx.ui.gap();
|
|
181469
181587
|
if (counts.flowsFailed > 0) {
|
|
181470
|
-
|
|
181588
|
+
const error51 = runnerMessages.flowsFailed(counts.flowsFailed);
|
|
181589
|
+
if (ctx.outputMode === "json" && failureDetails.length > 0) {
|
|
181590
|
+
return { error: error51, errorBody: failureDetails.join(`
|
|
181591
|
+
|
|
181592
|
+
`) };
|
|
181593
|
+
}
|
|
181594
|
+
return { error: error51 };
|
|
181471
181595
|
}
|
|
181472
181596
|
}
|
|
181473
181597
|
|
|
@@ -181518,15 +181642,15 @@ async function defaultRunWebFlowDeps(envDir = process.cwd(), signals) {
|
|
|
181518
181642
|
|
|
181519
181643
|
// src/domains/runtimeEnv/prepareRunDir.ts
|
|
181520
181644
|
import { createHash as createHash4 } from "node:crypto";
|
|
181521
|
-
import { join as
|
|
181645
|
+
import { join as join32, resolve as resolve9 } from "node:path";
|
|
181522
181646
|
|
|
181523
181647
|
// src/domains/runtimeEnv/execSubpathImports.ts
|
|
181524
|
-
import { join as
|
|
181648
|
+
import { join as join26 } from "node:path";
|
|
181525
181649
|
var flowSubpathImports = { "#playwright": "playwright" };
|
|
181526
181650
|
var packageJsonSchema = exports_external.looseObject({ imports: exports_external.record(exports_external.string(), exports_external.unknown()).catch({}) }).catch({ imports: {} });
|
|
181527
181651
|
async function writeExecSubpathImports(args) {
|
|
181528
181652
|
const { execDir, fs: fs3 } = args;
|
|
181529
|
-
const pkgPath =
|
|
181653
|
+
const pkgPath = join26(execDir, "package.json");
|
|
181530
181654
|
const pkg = packageJsonSchema.parse(await readPackageJson(pkgPath, fs3));
|
|
181531
181655
|
const merged = { ...pkg, imports: { ...pkg.imports, ...flowSubpathImports } };
|
|
181532
181656
|
await fs3.writeFile(pkgPath, JSON.stringify(merged, undefined, 2));
|
|
@@ -181548,10 +181672,10 @@ async function readPackageJson(pkgPath, fs3) {
|
|
|
181548
181672
|
}
|
|
181549
181673
|
|
|
181550
181674
|
// src/domains/runtimeEnv/innerHop.ts
|
|
181551
|
-
import { join as
|
|
181675
|
+
import { join as join28 } from "node:path";
|
|
181552
181676
|
|
|
181553
181677
|
// src/domains/runtimeEnv/linkPinnedPackages.ts
|
|
181554
|
-
import { dirname as dirname8, join as
|
|
181678
|
+
import { dirname as dirname8, join as join27 } from "node:path";
|
|
181555
181679
|
|
|
181556
181680
|
// src/domains/runtimeEnv/symlinkDir.ts
|
|
181557
181681
|
import { symlink } from "node:fs/promises";
|
|
@@ -181563,16 +181687,16 @@ async function createDirSymlink(source, target) {
|
|
|
181563
181687
|
// src/domains/runtimeEnv/linkPinnedPackages.ts
|
|
181564
181688
|
async function linkPinnedPackages(args) {
|
|
181565
181689
|
const { depsRoot, nodeModulesDir, fs: fs3 } = args;
|
|
181566
|
-
const managedModules =
|
|
181690
|
+
const managedModules = join27(depsRoot, "node_modules");
|
|
181567
181691
|
await fs3.mkdir(nodeModulesDir, { recursive: true });
|
|
181568
181692
|
for (const { name } of pinnedPackages) {
|
|
181569
181693
|
const segments = name.split("/");
|
|
181570
|
-
const target =
|
|
181694
|
+
const target = join27(nodeModulesDir, ...segments);
|
|
181571
181695
|
if (segments.length > 1) {
|
|
181572
181696
|
await fs3.mkdir(dirname8(target), { recursive: true });
|
|
181573
181697
|
}
|
|
181574
181698
|
await fs3.rm(target, { recursive: true, force: true });
|
|
181575
|
-
await createDirSymlink(
|
|
181699
|
+
await createDirSymlink(join27(managedModules, ...segments), target);
|
|
181576
181700
|
}
|
|
181577
181701
|
}
|
|
181578
181702
|
|
|
@@ -181581,14 +181705,14 @@ async function populateInnerHop(args) {
|
|
|
181581
181705
|
const { depsRoot, execDir, fs: fs3 } = args;
|
|
181582
181706
|
await linkPinnedPackages({
|
|
181583
181707
|
depsRoot,
|
|
181584
|
-
nodeModulesDir:
|
|
181708
|
+
nodeModulesDir: join28(execDir, "node_modules"),
|
|
181585
181709
|
fs: fs3
|
|
181586
181710
|
});
|
|
181587
181711
|
}
|
|
181588
181712
|
|
|
181589
181713
|
// src/domains/runtimeEnv/outerHop.ts
|
|
181590
181714
|
import { lstat } from "node:fs/promises";
|
|
181591
|
-
import { dirname as dirname9, join as
|
|
181715
|
+
import { dirname as dirname9, join as join29 } from "node:path";
|
|
181592
181716
|
var executorPackageNames = new Set(pinnedPackages.map((p3) => p3.name));
|
|
181593
181717
|
async function populateOuterHop(args) {
|
|
181594
181718
|
const { projectDir, runDir, fs: fs3 } = args;
|
|
@@ -181598,7 +181722,7 @@ async function populateOuterHop(args) {
|
|
|
181598
181722
|
const depNames = Object.keys(installableDeps);
|
|
181599
181723
|
const { satisfying, rejected } = await findSatisfyingNodeModulesDir(projectDir, depNames, fs3);
|
|
181600
181724
|
if (satisfying !== undefined) {
|
|
181601
|
-
await createDirSymlink(satisfying,
|
|
181725
|
+
await createDirSymlink(satisfying, join29(runDir, "node_modules"));
|
|
181602
181726
|
return { mode: "symlink", nodeModulesDir: satisfying };
|
|
181603
181727
|
}
|
|
181604
181728
|
if (depNames.length === 0)
|
|
@@ -181607,7 +181731,7 @@ async function populateOuterHop(args) {
|
|
|
181607
181731
|
await installOuterDeps(runDir, installableDeps, fs3, args.install ?? spawnNpmInstall);
|
|
181608
181732
|
await linkPinnedPackages({
|
|
181609
181733
|
depsRoot: args.depsRoot,
|
|
181610
|
-
nodeModulesDir:
|
|
181734
|
+
nodeModulesDir: join29(runDir, "node_modules"),
|
|
181611
181735
|
fs: fs3
|
|
181612
181736
|
});
|
|
181613
181737
|
return { mode: "install", depCount: depNames.length, rejected };
|
|
@@ -181616,10 +181740,10 @@ async function findSatisfyingNodeModulesDir(startDir, depNames, fs3) {
|
|
|
181616
181740
|
const rejected = [];
|
|
181617
181741
|
let dir = startDir;
|
|
181618
181742
|
while (true) {
|
|
181619
|
-
const candidate =
|
|
181743
|
+
const candidate = join29(dir, "node_modules");
|
|
181620
181744
|
const stats = await lstatSafe(candidate);
|
|
181621
181745
|
if (stats !== undefined && stats.isDirectory() && !stats.isSymbolicLink()) {
|
|
181622
|
-
const missing = depNames.filter((name) => !fs3.existsSync(
|
|
181746
|
+
const missing = depNames.filter((name) => !fs3.existsSync(join29(candidate, name, "package.json")));
|
|
181623
181747
|
if (missing.length === 0)
|
|
181624
181748
|
return { satisfying: candidate, rejected };
|
|
181625
181749
|
rejected.push({ dir: candidate, missing });
|
|
@@ -181640,7 +181764,7 @@ async function lstatSafe(path3) {
|
|
|
181640
181764
|
async function readInstallableDeps(projectDir, fs3) {
|
|
181641
181765
|
let content;
|
|
181642
181766
|
try {
|
|
181643
|
-
content = await fs3.readFile(
|
|
181767
|
+
content = await fs3.readFile(join29(projectDir, "package.json"));
|
|
181644
181768
|
} catch {
|
|
181645
181769
|
return {};
|
|
181646
181770
|
}
|
|
@@ -181658,8 +181782,8 @@ async function readInstallableDeps(projectDir, fs3) {
|
|
|
181658
181782
|
return Object.fromEntries(Object.entries(rawDeps).filter(([name]) => !executorPackageNames.has(name)).filter((entry) => typeof entry[1] === "string"));
|
|
181659
181783
|
}
|
|
181660
181784
|
async function installOuterDeps(runDir, deps, fs3, install) {
|
|
181661
|
-
await fs3.writeFile(
|
|
181662
|
-
await fs3.writeFile(
|
|
181785
|
+
await fs3.writeFile(join29(runDir, "package.json"), JSON.stringify({ name: "qawolf-run", private: true, dependencies: deps }, undefined, 2));
|
|
181786
|
+
await fs3.writeFile(join29(runDir, ".npmrc"), `@qawolf:registry=https://registry.npmjs.org/
|
|
181663
181787
|
`);
|
|
181664
181788
|
const result = await install(runDir);
|
|
181665
181789
|
if (result.exitCode !== 0) {
|
|
@@ -181669,14 +181793,14 @@ async function installOuterDeps(runDir, deps, fs3, install) {
|
|
|
181669
181793
|
|
|
181670
181794
|
// src/domains/runtimeEnv/stageFlowFiles.ts
|
|
181671
181795
|
import { createHash as createHash3 } from "node:crypto";
|
|
181672
|
-
import { basename as basename4, dirname as dirname10, join as
|
|
181796
|
+
import { basename as basename4, dirname as dirname10, join as join31, sep as sep4 } from "node:path";
|
|
181673
181797
|
|
|
181674
181798
|
// src/shell/copyDir.ts
|
|
181675
181799
|
import { cp, readdir as readdir2 } from "node:fs/promises";
|
|
181676
|
-
import { basename as basename3, join as
|
|
181800
|
+
import { basename as basename3, join as join30 } from "node:path";
|
|
181677
181801
|
async function copyDirExcluding(source, destination, excludedNames) {
|
|
181678
181802
|
const entries = await readdir2(source, { withFileTypes: true });
|
|
181679
|
-
await Promise.all(entries.filter((entry) => !excludedNames.has(entry.name)).map((entry) => cp(
|
|
181803
|
+
await Promise.all(entries.filter((entry) => !excludedNames.has(entry.name)).map((entry) => cp(join30(source, entry.name), join30(destination, entry.name), {
|
|
181680
181804
|
recursive: true,
|
|
181681
181805
|
filter: (path3) => !excludedNames.has(basename3(path3))
|
|
181682
181806
|
})));
|
|
@@ -181693,14 +181817,14 @@ async function stageFlowFiles(args) {
|
|
|
181693
181817
|
if (files.length > 1) {
|
|
181694
181818
|
return Promise.all(files.map((f3) => stageOneFile(f3, execDir, fs3)));
|
|
181695
181819
|
}
|
|
181696
|
-
await Promise.all(files.map((f3) => fs3.copyFile(f3,
|
|
181697
|
-
return files.map((f3) =>
|
|
181820
|
+
await Promise.all(files.map((f3) => fs3.copyFile(f3, join31(execDir, basename4(f3)))));
|
|
181821
|
+
return files.map((f3) => join31(execDir, basename4(f3)));
|
|
181698
181822
|
}
|
|
181699
181823
|
async function stageOneFile(file2, execDir, fs3) {
|
|
181700
181824
|
const dirHash = createHash3("sha256").update(dirname10(file2)).digest("hex").slice(0, 8);
|
|
181701
|
-
const subDir =
|
|
181825
|
+
const subDir = join31(execDir, dirHash);
|
|
181702
181826
|
await fs3.mkdir(subDir, { recursive: true });
|
|
181703
|
-
const dest =
|
|
181827
|
+
const dest = join31(subDir, basename4(file2));
|
|
181704
181828
|
await fs3.copyFile(file2, dest);
|
|
181705
181829
|
return dest;
|
|
181706
181830
|
}
|
|
@@ -181708,7 +181832,7 @@ function remapPath(file2, projectDir, execDir) {
|
|
|
181708
181832
|
if (file2 === projectDir)
|
|
181709
181833
|
return execDir;
|
|
181710
181834
|
if (file2.startsWith(projectDir + sep4)) {
|
|
181711
|
-
return
|
|
181835
|
+
return join31(execDir, file2.slice(projectDir.length + 1));
|
|
181712
181836
|
}
|
|
181713
181837
|
return;
|
|
181714
181838
|
}
|
|
@@ -181718,10 +181842,10 @@ async function prepareRunDir(args) {
|
|
|
181718
181842
|
const { files, projectDir, depsRoot, runRoot } = args;
|
|
181719
181843
|
const fs3 = args.fs ?? makeDefaultFs();
|
|
181720
181844
|
const runId = buildRunId(projectDir, files);
|
|
181721
|
-
const runDir =
|
|
181845
|
+
const runDir = join32(runRoot, runId);
|
|
181722
181846
|
await fs3.rm(runDir, { recursive: true, force: true });
|
|
181723
181847
|
await fs3.mkdir(runDir, { recursive: true });
|
|
181724
|
-
const execDir =
|
|
181848
|
+
const execDir = join32(runDir, "exec");
|
|
181725
181849
|
await fs3.mkdir(execDir, { recursive: true });
|
|
181726
181850
|
await populateInnerHop({ depsRoot, execDir, fs: fs3 });
|
|
181727
181851
|
const stagedFiles = await stageFlowFiles({ files, projectDir, execDir, fs: fs3 });
|
|
@@ -181752,17 +181876,17 @@ function buildRunId(projectDir, files) {
|
|
|
181752
181876
|
}
|
|
181753
181877
|
|
|
181754
181878
|
// src/shell/testkit.ts
|
|
181755
|
-
import { join as
|
|
181879
|
+
import { join as join33 } from "node:path";
|
|
181756
181880
|
function notAvailableLocally(name) {
|
|
181757
181881
|
throw new Error(runnerMessages.notAvailableLocally(name));
|
|
181758
181882
|
}
|
|
181759
181883
|
async function loadSdkDeps(cwd) {
|
|
181760
|
-
const testkitDir =
|
|
181884
|
+
const testkitDir = join33(cwd, "node_modules", "@qawolf", "testkit");
|
|
181761
181885
|
try {
|
|
181762
181886
|
const clientMod = await importFromPath(resolveFromEnvDir(cwd, "@qawolf/testkit/client"));
|
|
181763
181887
|
if (typeof clientMod.createTestkitClient !== "function")
|
|
181764
181888
|
throw new Error("createTestkitClient is not a function");
|
|
181765
|
-
const scopeMod = await importFromPath(
|
|
181889
|
+
const scopeMod = await importFromPath(join33(testkitDir, "dist", "clientScope.js"));
|
|
181766
181890
|
if (typeof scopeMod.configureTestkitClient !== "function")
|
|
181767
181891
|
throw new Error("configureTestkitClient is not a function");
|
|
181768
181892
|
return {
|
|
@@ -181820,9 +181944,9 @@ async function registerLazyEmailsClient(getInbox, cwd, deps) {
|
|
|
181820
181944
|
}
|
|
181821
181945
|
|
|
181822
181946
|
// src/commands/flows/envVarDeps.ts
|
|
181823
|
-
import { join as
|
|
181947
|
+
import { join as join34 } from "node:path";
|
|
181824
181948
|
function envFilePath(envDir) {
|
|
181825
|
-
return
|
|
181949
|
+
return join34(envDir, ".env");
|
|
181826
181950
|
}
|
|
181827
181951
|
async function readEnv(envDir, fs3) {
|
|
181828
181952
|
try {
|
|
@@ -182319,17 +182443,21 @@ async function findFlowStamp(flowAbsPath) {
|
|
|
182319
182443
|
|
|
182320
182444
|
// src/domains/install/browsers.ts
|
|
182321
182445
|
async function installBrowserList(ctx, browsers, deps) {
|
|
182322
|
-
const
|
|
182323
|
-
|
|
182324
|
-
|
|
182325
|
-
throw new Error(installMessages.playwrightNotFound(candidates[0] ?? deps.envDir));
|
|
182446
|
+
const cliJsPath = playwrightCliJsPath(deps.envDir);
|
|
182447
|
+
if (!deps.checkExists(cliJsPath)) {
|
|
182448
|
+
throw new Error(installMessages.playwrightNotFound(cliJsPath));
|
|
182326
182449
|
}
|
|
182327
182450
|
await ctx.ui.withProgress(browsers.map((browser) => ({
|
|
182328
182451
|
message: installMessages.installingBrowser(browser),
|
|
182329
182452
|
task: async () => {
|
|
182330
|
-
const
|
|
182331
|
-
|
|
182332
|
-
|
|
182453
|
+
const invocation = playwrightCliInvocation({
|
|
182454
|
+
envDir: deps.envDir,
|
|
182455
|
+
execPath: deps.execPath,
|
|
182456
|
+
cliArgs: buildArgs(browser, deps.platform, deps.browserDeps)
|
|
182457
|
+
});
|
|
182458
|
+
const result = await deps.spawn(invocation.cmd, invocation.args, {
|
|
182459
|
+
platform: deps.platform,
|
|
182460
|
+
env: invocation.env
|
|
182333
182461
|
});
|
|
182334
182462
|
if (result.exitCode !== 0) {
|
|
182335
182463
|
throw new Error(formatError2(browser, result));
|
|
@@ -182347,6 +182475,7 @@ async function installBrowsers(ctx, pattern, deps) {
|
|
|
182347
182475
|
}
|
|
182348
182476
|
await installBrowserList(ctx, browsers, {
|
|
182349
182477
|
spawn: deps.spawn,
|
|
182478
|
+
execPath: deps.execPath,
|
|
182350
182479
|
platform: deps.platform,
|
|
182351
182480
|
browserDeps: deps.browserDeps,
|
|
182352
182481
|
envDir: await deps.resolveDepsRoot(files),
|
|
@@ -183221,14 +183350,14 @@ async function runWebFlow({
|
|
|
183221
183350
|
|
|
183222
183351
|
// src/shell/embeddedWorkerCli.ts
|
|
183223
183352
|
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
183224
|
-
import { basename as basename6, join as
|
|
183353
|
+
import { basename as basename6, join as join35 } from "node:path";
|
|
183225
183354
|
var embeddedCliPathEnv = "QAWOLF_EMBEDDED_CLI_PATH";
|
|
183226
183355
|
function extractEmbeddedWorkerCli() {
|
|
183227
183356
|
const assetPath = process.env[embeddedCliPathEnv];
|
|
183228
183357
|
if (assetPath === undefined || assetPath === "")
|
|
183229
183358
|
return;
|
|
183230
|
-
const dir =
|
|
183231
|
-
const dest =
|
|
183359
|
+
const dir = join35(getDataDir(), "worker");
|
|
183360
|
+
const dest = join35(dir, basename6(assetPath));
|
|
183232
183361
|
if (existsSync3(dest))
|
|
183233
183362
|
return dest;
|
|
183234
183363
|
mkdirSync3(dir, { recursive: true });
|
|
@@ -183387,51 +183516,6 @@ import { dirname as dirname12 } from "node:path";
|
|
|
183387
183516
|
|
|
183388
183517
|
// src/shell/reporter/createConsoleReporter.ts
|
|
183389
183518
|
import { styleText as styleText3 } from "node:util";
|
|
183390
|
-
|
|
183391
|
-
// src/shell/reporter/formatErrorWithCause.ts
|
|
183392
|
-
function filterStack(stack) {
|
|
183393
|
-
const cwd = process.cwd();
|
|
183394
|
-
return stack.split(`
|
|
183395
|
-
`).filter((line) => {
|
|
183396
|
-
if (!/^\s+at /.test(line))
|
|
183397
|
-
return true;
|
|
183398
|
-
return !line.includes("node_modules") && !line.includes("dist/cli.js");
|
|
183399
|
-
}).map((line) => {
|
|
183400
|
-
if (!/^\s+at /.test(line))
|
|
183401
|
-
return line;
|
|
183402
|
-
return line.replace(`file://${cwd}/`, "").replace(`${cwd}/`, "");
|
|
183403
|
-
}).join(`
|
|
183404
|
-
`);
|
|
183405
|
-
}
|
|
183406
|
-
function renderCause(cause) {
|
|
183407
|
-
if (cause instanceof Error)
|
|
183408
|
-
return filterStack(cause.stack ?? cause.message);
|
|
183409
|
-
if (typeof cause === "object" && cause !== null) {
|
|
183410
|
-
const obj = cause;
|
|
183411
|
-
if (typeof obj["message"] === "string")
|
|
183412
|
-
return obj["message"];
|
|
183413
|
-
try {
|
|
183414
|
-
return JSON.stringify(cause);
|
|
183415
|
-
} catch {
|
|
183416
|
-
return String(cause);
|
|
183417
|
-
}
|
|
183418
|
-
}
|
|
183419
|
-
return String(cause);
|
|
183420
|
-
}
|
|
183421
|
-
function formatErrorWithCause(err) {
|
|
183422
|
-
const parts = [String(err)];
|
|
183423
|
-
let cause = err.cause;
|
|
183424
|
-
while (cause !== undefined && cause !== null) {
|
|
183425
|
-
parts.push(`Caused by: ${renderCause(cause)}`);
|
|
183426
|
-
if (!(cause instanceof Error))
|
|
183427
|
-
break;
|
|
183428
|
-
cause = cause.cause;
|
|
183429
|
-
}
|
|
183430
|
-
return parts.join(`
|
|
183431
|
-
`);
|
|
183432
|
-
}
|
|
183433
|
-
|
|
183434
|
-
// src/shell/reporter/createConsoleReporter.ts
|
|
183435
183519
|
function fmtDuration(ms2) {
|
|
183436
183520
|
return `(${(ms2 / 1000).toFixed(2)}s)`;
|
|
183437
183521
|
}
|
|
@@ -183510,30 +183594,8 @@ ${styleText3("dim", "─".repeat(width))}
|
|
|
183510
183594
|
}
|
|
183511
183595
|
};
|
|
183512
183596
|
}
|
|
183513
|
-
// src/shell/reporter/createCompositeReporter.ts
|
|
183514
|
-
function callEach(reporters, pick2, event) {
|
|
183515
|
-
for (const r2 of reporters) {
|
|
183516
|
-
try {
|
|
183517
|
-
pick2(r2)?.(event);
|
|
183518
|
-
} catch (err) {
|
|
183519
|
-
process.stderr.write(`[reporter error] ${String(err)}
|
|
183520
|
-
`);
|
|
183521
|
-
}
|
|
183522
|
-
}
|
|
183523
|
-
}
|
|
183524
|
-
function createCompositeReporter(reporters) {
|
|
183525
|
-
return {
|
|
183526
|
-
onFlowStart: (e) => callEach(reporters, (r2) => r2.onFlowStart, e),
|
|
183527
|
-
onFlowPass: (e) => callEach(reporters, (r2) => r2.onFlowPass, e),
|
|
183528
|
-
onFlowFail: (e) => callEach(reporters, (r2) => r2.onFlowFail, e),
|
|
183529
|
-
onTestStart: (e) => callEach(reporters, (r2) => r2.onTestStart, e),
|
|
183530
|
-
onTestResult: (e) => callEach(reporters, (r2) => r2.onTestResult, e),
|
|
183531
|
-
onScreenshot: (e) => callEach(reporters, (r2) => r2.onScreenshot, e),
|
|
183532
|
-
onRunComplete: (e) => callEach(reporters, (r2) => r2.onRunComplete, e)
|
|
183533
|
-
};
|
|
183534
|
-
}
|
|
183535
183597
|
// src/shell/reporter/createJUnitReporter.ts
|
|
183536
|
-
import { join as
|
|
183598
|
+
import { join as join36 } from "node:path";
|
|
183537
183599
|
|
|
183538
183600
|
// src/shell/reporter/junitXml.ts
|
|
183539
183601
|
function escapeXml(str) {
|
|
@@ -183572,7 +183634,7 @@ ${suites}`;
|
|
|
183572
183634
|
|
|
183573
183635
|
// src/shell/reporter/createJUnitReporter.ts
|
|
183574
183636
|
function resolveJUnitOutputPath(junit, outputDir) {
|
|
183575
|
-
return typeof junit === "string" && junit.trim() !== "" ? junit :
|
|
183637
|
+
return typeof junit === "string" && junit.trim() !== "" ? junit : join36(outputDir, "junit-report.xml");
|
|
183576
183638
|
}
|
|
183577
183639
|
function createJUnitReporter(deps) {
|
|
183578
183640
|
const flows = [];
|
|
@@ -183634,6 +183696,7 @@ function buildFlowsRunDeps(args) {
|
|
|
183634
183696
|
peekFlowMeta: makePeekFlowMeta(ctx.fs),
|
|
183635
183697
|
installBrowsers: (innerCtx, browsers) => installBrowserList(innerCtx, browsers, {
|
|
183636
183698
|
spawn: defaultSpawn,
|
|
183699
|
+
execPath: process.execPath,
|
|
183637
183700
|
platform: process.platform,
|
|
183638
183701
|
browserDeps: flags.browserDeps,
|
|
183639
183702
|
envDir: resolvedDir,
|
|
@@ -183661,11 +183724,11 @@ function buildFlowsRunDeps(args) {
|
|
|
183661
183724
|
|
|
183662
183725
|
// src/commands/flows/loadEnvFile.ts
|
|
183663
183726
|
import { readFile } from "node:fs/promises";
|
|
183664
|
-
import { join as
|
|
183727
|
+
import { join as join37 } from "node:path";
|
|
183665
183728
|
async function loadEnvFile(envDir) {
|
|
183666
183729
|
let content;
|
|
183667
183730
|
try {
|
|
183668
|
-
content = await readFile(
|
|
183731
|
+
content = await readFile(join37(envDir, ".env"), "utf8");
|
|
183669
183732
|
} catch (err) {
|
|
183670
183733
|
if (isNoEntError(err))
|
|
183671
183734
|
return;
|
|
@@ -183766,7 +183829,7 @@ async function handleFlowsRun(ctx, pattern, flags, deps) {
|
|
|
183766
183829
|
}
|
|
183767
183830
|
|
|
183768
183831
|
// src/commands/flows/hybridRunDefaults.ts
|
|
183769
|
-
import { join as
|
|
183832
|
+
import { join as join38, resolve as resolve10 } from "node:path";
|
|
183770
183833
|
function makeDefaultHybridDeps(fs9) {
|
|
183771
183834
|
return {
|
|
183772
183835
|
expandPatterns: (patterns, cwd, logger) => expandPatterns(patterns, cwd, logger, fs9),
|
|
@@ -183785,7 +183848,7 @@ async function handleHybridFlowsRun(ctx, pattern, flags, deps) {
|
|
|
183785
183848
|
if (validation !== "ok") {
|
|
183786
183849
|
return { error: validation.error, exitCode: 2 };
|
|
183787
183850
|
}
|
|
183788
|
-
const envDir = resolve10(
|
|
183851
|
+
const envDir = resolve10(join38(".qawolf", flags.env));
|
|
183789
183852
|
const patternArgs = buildPatternArgs(pattern);
|
|
183790
183853
|
const globFlows = () => resolvedDeps.expandPatterns(patternArgs, envDir, ctx.log("flows"));
|
|
183791
183854
|
let files = await globFlows();
|
|
@@ -183931,7 +183994,100 @@ function registerFlowsCommand(program2, signals) {
|
|
|
183931
183994
|
}
|
|
183932
183995
|
|
|
183933
183996
|
// src/domains/init/init.ts
|
|
183934
|
-
import { dirname as dirname13, join as
|
|
183997
|
+
import { dirname as dirname13, join as join40, relative as relative7 } from "node:path";
|
|
183998
|
+
|
|
183999
|
+
// src/domains/init/ensurePackageJson.ts
|
|
184000
|
+
import { join as join39 } from "node:path";
|
|
184001
|
+
async function ensurePackageJson(ctx, yes, deps) {
|
|
184002
|
+
const pkgPath = join39(deps.cwd, "package.json");
|
|
184003
|
+
if (!await deps.fs.pathExists(pkgPath)) {
|
|
184004
|
+
const confirmed2 = await ctx.ui.confirm(initMessages.createPackageJsonPrompt, { yes });
|
|
184005
|
+
if (!confirmed2.ok || !confirmed2.value) {
|
|
184006
|
+
ctx.ui.info(initMessages.skippedCreatingPackageJson);
|
|
184007
|
+
return;
|
|
184008
|
+
}
|
|
184009
|
+
const pkg2 = {
|
|
184010
|
+
private: true,
|
|
184011
|
+
type: "module",
|
|
184012
|
+
dependencies: { "@qawolf/flows": flowsVersion },
|
|
184013
|
+
scripts: { "test:e2e": "qawolf flows run" }
|
|
184014
|
+
};
|
|
184015
|
+
await deps.fs.writeFile(pkgPath, JSON.stringify(pkg2, undefined, 2) + `
|
|
184016
|
+
`);
|
|
184017
|
+
ctx.ui.step(initMessages.createdPackageJson);
|
|
184018
|
+
return;
|
|
184019
|
+
}
|
|
184020
|
+
const raw = await deps.fs.readFile(pkgPath);
|
|
184021
|
+
let parsed;
|
|
184022
|
+
try {
|
|
184023
|
+
parsed = JSON.parse(raw);
|
|
184024
|
+
} catch {
|
|
184025
|
+
ctx.ui.warn(initMessages.packageJsonInvalidJson);
|
|
184026
|
+
return;
|
|
184027
|
+
}
|
|
184028
|
+
if (!isRecord3(parsed)) {
|
|
184029
|
+
ctx.ui.warn(initMessages.packageJsonNotAnObject);
|
|
184030
|
+
return;
|
|
184031
|
+
}
|
|
184032
|
+
const pkg = parsed;
|
|
184033
|
+
const scripts = readSection(ctx, pkg, "scripts");
|
|
184034
|
+
const dependencies = readSection(ctx, pkg, "dependencies");
|
|
184035
|
+
const devDependencies = readSection(ctx, pkg, "devDependencies");
|
|
184036
|
+
const needScript = scripts !== undefined && !scripts["test:e2e"];
|
|
184037
|
+
const priorType = pkg["type"];
|
|
184038
|
+
const needType = priorType !== "module";
|
|
184039
|
+
const needFlowsDep = dependencies !== undefined && !dependencies["@qawolf/flows"] && !devDependencies?.["@qawolf/flows"];
|
|
184040
|
+
const changes = [];
|
|
184041
|
+
if (needScript)
|
|
184042
|
+
changes.push(initMessages.pkgChanges.script);
|
|
184043
|
+
if (needType)
|
|
184044
|
+
changes.push(initMessages.pkgChanges.type);
|
|
184045
|
+
if (needFlowsDep)
|
|
184046
|
+
changes.push(initMessages.pkgChanges.flowsDep);
|
|
184047
|
+
if (changes.length === 0) {
|
|
184048
|
+
ctx.ui.info(initMessages.packageJsonUpToDate);
|
|
184049
|
+
return;
|
|
184050
|
+
}
|
|
184051
|
+
if (scripts !== undefined && scripts["test:e2e"]) {
|
|
184052
|
+
ctx.ui.warn(initMessages.packageJsonHasTestE2e);
|
|
184053
|
+
}
|
|
184054
|
+
const confirmed = await ctx.ui.confirm(initMessages.updatePackageJsonPrompt(changes), { yes, destructive: true });
|
|
184055
|
+
if (!confirmed.ok || !confirmed.value) {
|
|
184056
|
+
ctx.ui.info(initMessages.skippedUpdatingPackageJson);
|
|
184057
|
+
return;
|
|
184058
|
+
}
|
|
184059
|
+
if (needScript && scripts !== undefined) {
|
|
184060
|
+
scripts["test:e2e"] = "qawolf flows run";
|
|
184061
|
+
pkg["scripts"] = scripts;
|
|
184062
|
+
}
|
|
184063
|
+
if (needType)
|
|
184064
|
+
pkg["type"] = "module";
|
|
184065
|
+
if (needFlowsDep && dependencies !== undefined) {
|
|
184066
|
+
dependencies["@qawolf/flows"] = flowsVersion;
|
|
184067
|
+
pkg["dependencies"] = dependencies;
|
|
184068
|
+
}
|
|
184069
|
+
const trailingNewline = raw.endsWith(`
|
|
184070
|
+
`) ? `
|
|
184071
|
+
` : "";
|
|
184072
|
+
await deps.fs.writeFile(pkgPath, JSON.stringify(pkg, undefined, 2) + trailingNewline);
|
|
184073
|
+
ctx.ui.step(initMessages.updatedPackageJson);
|
|
184074
|
+
if (needType && priorType !== undefined) {
|
|
184075
|
+
const label = typeof priorType === "string" ? priorType : JSON.stringify(priorType);
|
|
184076
|
+
ctx.ui.warn(initMessages.typeChanged(label));
|
|
184077
|
+
}
|
|
184078
|
+
}
|
|
184079
|
+
function isRecord3(value) {
|
|
184080
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
184081
|
+
}
|
|
184082
|
+
function readSection(ctx, pkg, key) {
|
|
184083
|
+
const value = pkg[key];
|
|
184084
|
+
if (value === undefined)
|
|
184085
|
+
return {};
|
|
184086
|
+
if (isRecord3(value))
|
|
184087
|
+
return value;
|
|
184088
|
+
ctx.ui.warn(initMessages.packageJsonMalformedSection(key));
|
|
184089
|
+
return;
|
|
184090
|
+
}
|
|
183935
184091
|
|
|
183936
184092
|
// src/domains/init/templates.ts
|
|
183937
184093
|
var qawolfConfigTs = `export default {
|
|
@@ -183969,9 +184125,9 @@ function makeDefaultInitDeps() {
|
|
|
183969
184125
|
async function handleInit(ctx, opts, deps = makeDefaultInitDeps()) {
|
|
183970
184126
|
ctx.ui.gap();
|
|
183971
184127
|
ctx.ui.intro(initMessages.title);
|
|
183972
|
-
const configPath =
|
|
183973
|
-
const flowPath =
|
|
183974
|
-
const gitignorePath =
|
|
184128
|
+
const configPath = join40(deps.cwd, "qawolf.config.ts");
|
|
184129
|
+
const flowPath = join40(deps.cwd, "src", "flows", "example.flow.ts");
|
|
184130
|
+
const gitignorePath = join40(deps.cwd, ".qawolf", ".gitignore");
|
|
183975
184131
|
await writeWithPrompt(ctx, configPath, qawolfConfigTs, opts.yes, deps);
|
|
183976
184132
|
await writeWithPrompt(ctx, flowPath, exampleFlowTs, opts.yes, deps);
|
|
183977
184133
|
await writeWithPrompt(ctx, gitignorePath, qawolfGitignore, opts.yes, deps);
|
|
@@ -183994,54 +184150,6 @@ async function writeWithPrompt(ctx, filePath, content, yes, deps) {
|
|
|
183994
184150
|
await deps.fs.writeFile(filePath, content);
|
|
183995
184151
|
ctx.ui.step(initMessages.createdFile(relPath));
|
|
183996
184152
|
}
|
|
183997
|
-
async function ensurePackageJson(ctx, yes, deps) {
|
|
183998
|
-
const pkgPath = join38(deps.cwd, "package.json");
|
|
183999
|
-
if (!await deps.fs.pathExists(pkgPath)) {
|
|
184000
|
-
const confirmed2 = await ctx.ui.confirm(initMessages.createPackageJsonPrompt, { yes });
|
|
184001
|
-
if (!confirmed2.ok || !confirmed2.value) {
|
|
184002
|
-
ctx.ui.info(initMessages.skippedCreatingPackageJson);
|
|
184003
|
-
return;
|
|
184004
|
-
}
|
|
184005
|
-
const pkg2 = {
|
|
184006
|
-
private: true,
|
|
184007
|
-
type: "module",
|
|
184008
|
-
dependencies: { "@qawolf/flows": flowsVersion },
|
|
184009
|
-
scripts: { "test:e2e": "qawolf flows run" }
|
|
184010
|
-
};
|
|
184011
|
-
await deps.fs.writeFile(pkgPath, JSON.stringify(pkg2, undefined, 2) + `
|
|
184012
|
-
`);
|
|
184013
|
-
ctx.ui.step(initMessages.createdPackageJson);
|
|
184014
|
-
return;
|
|
184015
|
-
}
|
|
184016
|
-
const raw = await deps.fs.readFile(pkgPath);
|
|
184017
|
-
let pkg;
|
|
184018
|
-
try {
|
|
184019
|
-
pkg = JSON.parse(raw);
|
|
184020
|
-
} catch {
|
|
184021
|
-
ctx.ui.warn(initMessages.packageJsonInvalidJson);
|
|
184022
|
-
return;
|
|
184023
|
-
}
|
|
184024
|
-
const scripts = pkg["scripts"] ?? {};
|
|
184025
|
-
if (scripts["test:e2e"]) {
|
|
184026
|
-
ctx.ui.warn(initMessages.packageJsonHasTestE2e);
|
|
184027
|
-
return;
|
|
184028
|
-
}
|
|
184029
|
-
const confirmed = await ctx.ui.confirm(initMessages.addTestE2ePrompt, {
|
|
184030
|
-
yes,
|
|
184031
|
-
destructive: true
|
|
184032
|
-
});
|
|
184033
|
-
if (!confirmed.ok || !confirmed.value) {
|
|
184034
|
-
ctx.ui.info(initMessages.skippedAddingTestE2e);
|
|
184035
|
-
return;
|
|
184036
|
-
}
|
|
184037
|
-
scripts["test:e2e"] = "qawolf flows run";
|
|
184038
|
-
pkg["scripts"] = scripts;
|
|
184039
|
-
const trailingNewline = raw.endsWith(`
|
|
184040
|
-
`) ? `
|
|
184041
|
-
` : "";
|
|
184042
|
-
await deps.fs.writeFile(pkgPath, JSON.stringify(pkg, undefined, 2) + trailingNewline);
|
|
184043
|
-
ctx.ui.step(initMessages.updatedPackageJson);
|
|
184044
|
-
}
|
|
184045
184153
|
|
|
184046
184154
|
// src/commands/init/index.ts
|
|
184047
184155
|
function registerInitCommand(program2, signals) {
|
|
@@ -184057,7 +184165,7 @@ Examples:
|
|
|
184057
184165
|
import { parseExecutionTarget as parseExecutionTarget4 } from "@qawolf/flow-targets";
|
|
184058
184166
|
|
|
184059
184167
|
// src/domains/install/android/avd.ts
|
|
184060
|
-
import { join as
|
|
184168
|
+
import { join as join41 } from "node:path";
|
|
184061
184169
|
async function installAvds(ctx, specs, deps) {
|
|
184062
184170
|
const sdkManagerPath = sdkManagerBin(deps.androidHome, deps.platform);
|
|
184063
184171
|
const avdManagerPath = avdManagerBin(deps.androidHome, deps.platform);
|
|
@@ -184067,7 +184175,7 @@ async function installAvds(ctx, specs, deps) {
|
|
|
184067
184175
|
if (versionResult.exitCode !== 0) {
|
|
184068
184176
|
throw new Error(installMessages.android.sdkmanagerNotFound(sdkManagerPath));
|
|
184069
184177
|
}
|
|
184070
|
-
const licenseFile =
|
|
184178
|
+
const licenseFile = join41(deps.androidHome, "licenses", "android-sdk-license");
|
|
184071
184179
|
if (deps.checkExists(licenseFile)) {
|
|
184072
184180
|
ctx.ui.info(installMessages.android.licensesAlreadyAccepted);
|
|
184073
184181
|
} else {
|
|
@@ -184082,7 +184190,7 @@ async function installAvds(ctx, specs, deps) {
|
|
|
184082
184190
|
for (const spec of specs) {
|
|
184083
184191
|
if (installedImages.has(spec.systemImage))
|
|
184084
184192
|
continue;
|
|
184085
|
-
const systemImg =
|
|
184193
|
+
const systemImg = join41(deps.androidHome, ...spec.systemImage.split(";"), "system.img");
|
|
184086
184194
|
if (deps.checkExists(systemImg)) {
|
|
184087
184195
|
ctx.ui.info(installMessages.android.systemImageAlreadyInstalled(spec.systemImage));
|
|
184088
184196
|
installedImages.add(spec.systemImage);
|
|
@@ -184236,6 +184344,7 @@ async function handleInstallBrowsers(ctx, pattern, options) {
|
|
|
184236
184344
|
return installBrowsers(ctx, pattern, {
|
|
184237
184345
|
cwd,
|
|
184238
184346
|
spawn: defaultSpawn,
|
|
184347
|
+
execPath: process.execPath,
|
|
184239
184348
|
platform: process.platform,
|
|
184240
184349
|
browserDeps,
|
|
184241
184350
|
expandPatterns: (patterns, dir) => expandPatterns(patterns, dir ?? cwd, undefined, fs9),
|
|
@@ -184726,4 +184835,4 @@ createProgram({ signals }).parseAsync().catch(() => {
|
|
|
184726
184835
|
process.exitCode = 1;
|
|
184727
184836
|
}).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
|
|
184728
184837
|
|
|
184729
|
-
//# debugId=
|
|
184838
|
+
//# debugId=C0B1B96CCF6C4A9564756E2164756E21
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qawolf/cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"automation",
|
|
@@ -60,7 +60,6 @@
|
|
|
60
60
|
"@clack/prompts": "1.5.1",
|
|
61
61
|
"@napi-rs/keyring": "1.3.0",
|
|
62
62
|
"@oxc-node/core": "0.1.0",
|
|
63
|
-
"@playwright/test": "1.62.0",
|
|
64
63
|
"@qawolf/api-contracts": "0.22.0",
|
|
65
64
|
"@qawolf/emails": "1.1.1",
|
|
66
65
|
"@qawolf/flow-targets": "1.0.0",
|