@qawolf/cli 1.34.0 → 1.36.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/dist/cli.js
CHANGED
|
@@ -8816,7 +8816,8 @@ var interactMessages = {
|
|
|
8816
8816
|
actionFlagsWithStdin: '"-" reads the whole action from stdin, so an action flag passed alongside it would be ignored. Pipe the action in on its own, or name the action type and use flags.',
|
|
8817
8817
|
actionMayHaveHappened: "The runner could not be reached, which does not mean the action was not performed: it may have stopped answering mid-action. Take a screenshot before repeating it.",
|
|
8818
8818
|
actionNotJson: `Stdin did not hold a JSON action. Pipe one object, for example '{"type":"click","button":"left","x":480,"y":260}'.`,
|
|
8819
|
-
|
|
8819
|
+
actionNotSupportedOnBrowser: (type) => `Only a mobile runner performs ${type}. On a browser runner, click at --x and --y, drag along a --path, and type into whatever has focus.`,
|
|
8820
|
+
actionNotSupportedOnMobile: (type) => `A mobile runner has a touchscreen, so it cannot perform ${type} as asked. Use tap, swipe, fill, or type into whatever the last tap focused.`,
|
|
8820
8821
|
actionFailedScreenshotToStdout: "Its screen was written to stdout as a JPEG, so look at that rather than sending the action again.",
|
|
8821
8822
|
actionFailedScreenshotUnwritten: (detail) => `Its screen could not be written, because ${detail}, so take one with qawolf runner screenshot rather than sending the action again.`,
|
|
8822
8823
|
actionFailedScreenshotWritten: (path) => `Its screen was written to ${path}, so look at that rather than sending the action again.`,
|
|
@@ -10076,7 +10077,6 @@ var bigint = /^-?\d+n?$/;
|
|
|
10076
10077
|
var integer = /^-?\d+$/;
|
|
10077
10078
|
var number = /^-?\d+(?:\.\d+)?$/;
|
|
10078
10079
|
var boolean = /^(?:true|false)$/i;
|
|
10079
|
-
var _null = /^null$/i;
|
|
10080
10080
|
var lowercase = /^[^A-Z]*$/;
|
|
10081
10081
|
var uppercase = /^[^a-z]*$/;
|
|
10082
10082
|
|
|
@@ -10997,23 +10997,6 @@ var $ZodBigInt = /* @__PURE__ */ $constructor("$ZodBigInt", (inst, def) => {
|
|
|
10997
10997
|
return payload;
|
|
10998
10998
|
};
|
|
10999
10999
|
});
|
|
11000
|
-
var $ZodNull = /* @__PURE__ */ $constructor("$ZodNull", (inst, def) => {
|
|
11001
|
-
$ZodType.init(inst, def);
|
|
11002
|
-
inst._zod.pattern = _null;
|
|
11003
|
-
inst._zod.values = new Set([null]);
|
|
11004
|
-
inst._zod.parse = (payload, _ctx) => {
|
|
11005
|
-
const input = payload.value;
|
|
11006
|
-
if (input === null)
|
|
11007
|
-
return payload;
|
|
11008
|
-
payload.issues.push({
|
|
11009
|
-
expected: "null",
|
|
11010
|
-
code: "invalid_type",
|
|
11011
|
-
input,
|
|
11012
|
-
inst
|
|
11013
|
-
});
|
|
11014
|
-
return payload;
|
|
11015
|
-
};
|
|
11016
|
-
});
|
|
11017
11000
|
var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
11018
11001
|
$ZodType.init(inst, def);
|
|
11019
11002
|
inst._zod.parse = (payload) => payload;
|
|
@@ -12548,12 +12531,6 @@ function _coercedBigint(Class, params) {
|
|
|
12548
12531
|
...normalizeParams(params)
|
|
12549
12532
|
});
|
|
12550
12533
|
}
|
|
12551
|
-
function _null2(Class, params) {
|
|
12552
|
-
return new Class({
|
|
12553
|
-
type: "null",
|
|
12554
|
-
...normalizeParams(params)
|
|
12555
|
-
});
|
|
12556
|
-
}
|
|
12557
12534
|
function _unknown(Class) {
|
|
12558
12535
|
return new Class({
|
|
12559
12536
|
type: "unknown"
|
|
@@ -14183,14 +14160,6 @@ var ZodBigInt = /* @__PURE__ */ $constructor("ZodBigInt", (inst, def) => {
|
|
|
14183
14160
|
inst.maxValue = bag.maximum ?? null;
|
|
14184
14161
|
inst.format = bag.format ?? null;
|
|
14185
14162
|
});
|
|
14186
|
-
var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
14187
|
-
$ZodNull.init(inst, def);
|
|
14188
|
-
ZodType.init(inst, def);
|
|
14189
|
-
inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params);
|
|
14190
|
-
});
|
|
14191
|
-
function _null3(params) {
|
|
14192
|
-
return _null2(ZodNull, params);
|
|
14193
|
-
}
|
|
14194
14163
|
var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
14195
14164
|
$ZodUnknown.init(inst, def);
|
|
14196
14165
|
ZodType.init(inst, def);
|
|
@@ -14642,12 +14611,6 @@ function refine(fn, _params = {}) {
|
|
|
14642
14611
|
function superRefine(fn, params) {
|
|
14643
14612
|
return _superRefine(fn, params);
|
|
14644
14613
|
}
|
|
14645
|
-
function json(params) {
|
|
14646
|
-
const jsonSchema = lazy(() => {
|
|
14647
|
-
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record(string2(), jsonSchema)]);
|
|
14648
|
-
});
|
|
14649
|
-
return jsonSchema;
|
|
14650
|
-
}
|
|
14651
14614
|
// node_modules/zod/v4/classic/coerce.js
|
|
14652
14615
|
var exports_coerce = {};
|
|
14653
14616
|
__export(exports_coerce, {
|
|
@@ -16635,7 +16598,7 @@ var agentSessionStatuses = [
|
|
|
16635
16598
|
"failed",
|
|
16636
16599
|
"cancelled"
|
|
16637
16600
|
];
|
|
16638
|
-
var agentSessionStatusSchema = _enum(agentSessionStatuses).describe('Where the work stands. "working" means the AI is still on it. "waiting-for-you" means it asked a question and cannot continue until agent.send answers it. "completed", "failed" and "cancelled" are settled and will not change.');
|
|
16601
|
+
var agentSessionStatusSchema = _enum(agentSessionStatuses).describe('Where the work stands. "working" means the AI is still on it. "waiting-for-you" means it asked a question and cannot continue until agent.send answers it. "completed" means it finished what it was asked, and a new agent.send continues it. "failed" and "cancelled" are settled and will not change.');
|
|
16639
16602
|
var agentReplySchema = object({
|
|
16640
16603
|
askedAt: exports_iso.datetime().describe("When the AI wrote this, as an ISO 8601 timestamp."),
|
|
16641
16604
|
choices: array(string2()).optional().describe("The answers the AI offered, when the reply is a question with a fixed set of them. Answer by sending one of these back through agent.send."),
|
|
@@ -16646,6 +16609,75 @@ var agentReplySchema = object({
|
|
|
16646
16609
|
var maxAgentWaitSeconds = 45;
|
|
16647
16610
|
var agentWakeReasonSchema = _enum(["reply", "status", "timeout"]).describe('Why a held check answered. "reply" means the AI said something new, "status" means the session settled or needs you, "timeout" means the hold ran out with nothing new.');
|
|
16648
16611
|
|
|
16612
|
+
// node_modules/@qawolf/api-contracts/dist/v1/run/summary.js
|
|
16613
|
+
var publicRunStatusValues = [
|
|
16614
|
+
"queued",
|
|
16615
|
+
"running",
|
|
16616
|
+
"passed",
|
|
16617
|
+
"failed",
|
|
16618
|
+
"canceled"
|
|
16619
|
+
];
|
|
16620
|
+
var makeRunSummaryFields = (ids) => ({
|
|
16621
|
+
completedAt: exports_iso.datetime().optional().describe("When the run finished executing. Absent while queued or running, and also absent for a terminal run that never completed execution (e.g. every flow was canceled or skipped)."),
|
|
16622
|
+
createdAt: exports_iso.datetime(),
|
|
16623
|
+
git: object({
|
|
16624
|
+
branch: string2().optional(),
|
|
16625
|
+
commitMessage: string2().optional(),
|
|
16626
|
+
commitSha: string2().optional(),
|
|
16627
|
+
commitUrl: string2().optional().describe("Link to the commit on the code host.")
|
|
16628
|
+
}).describe("The branch and commit under test. The fields are present when a deploy notification started the run, and absent for runs started another way, for example manually or with run.create."),
|
|
16629
|
+
needsReview: boolean2().optional().describe("True once every flow has finished its attempts and at least one failed flow still has no diagnosis, including one whose investigation carried over to a later run. `status` stays `running` until that failure is diagnosed, so a caller that is not waiting for a diagnosis can stop polling here and read the run's failed flows."),
|
|
16630
|
+
runId: ids.run,
|
|
16631
|
+
status: _enum(publicRunStatusValues).describe("Whole-run status, and the value to gate a pipeline on. Terminal statuses are passed, failed, and canceled; poll until one is reached. `failed` means the run found a bug that is still open and serious enough to block — a lower-priority bug, or one since resolved, reads `passed`, and the per-flow diagnoses are still in `flows`. The run stays `running` while any investigation is unresolved, including one that carried over to a later run, so a terminal status always means a settled answer. `needsReview` tells such a run apart from one that is still executing.")
|
|
16632
|
+
});
|
|
16633
|
+
|
|
16634
|
+
// node_modules/@qawolf/api-contracts/dist/v1/deployment/didNotRunReason.js
|
|
16635
|
+
var didNotRunReasonSchema = _enum([
|
|
16636
|
+
"billing-prevented",
|
|
16637
|
+
"branch-still-syncing",
|
|
16638
|
+
"deployment-no-longer-live",
|
|
16639
|
+
"duplicate-run",
|
|
16640
|
+
"environment-not-linked-to-branch",
|
|
16641
|
+
"environment-not-ready",
|
|
16642
|
+
"environment-terminated",
|
|
16643
|
+
"internal-error",
|
|
16644
|
+
"low-risk-change",
|
|
16645
|
+
"no-flows-to-run",
|
|
16646
|
+
"no-matching-trigger",
|
|
16647
|
+
"no-pull-request",
|
|
16648
|
+
"no-relevant-flows",
|
|
16649
|
+
"rate-limited",
|
|
16650
|
+
"run-not-created",
|
|
16651
|
+
"skipped",
|
|
16652
|
+
"test-configuration-error",
|
|
16653
|
+
"trigger-not-found",
|
|
16654
|
+
"workspace-inactive",
|
|
16655
|
+
"workspace-not-ready"
|
|
16656
|
+
]).describe([
|
|
16657
|
+
"Why the matched trigger created no run, as a stable value safe to branch on in a CI pipeline. The accompanying `message` is the wording for a person to read and may be reworded at any time; this value will not be.",
|
|
16658
|
+
"billing-prevented: a billing restriction on the workspace stopped the run.",
|
|
16659
|
+
"branch-still-syncing: the environment was still syncing its flows.",
|
|
16660
|
+
"deployment-no-longer-live: the deployment was torn down or replaced by a newer one before the run started.",
|
|
16661
|
+
"duplicate-run: another run already covered this same deployment.",
|
|
16662
|
+
"environment-not-linked-to-branch: the environment has no branch to take flows from yet.",
|
|
16663
|
+
"environment-not-ready: the environment was still being prepared; retrying later can succeed.",
|
|
16664
|
+
"environment-terminated: the environment for the run is terminated.",
|
|
16665
|
+
"internal-error: QA Wolf could not start the run and the cause is on our side.",
|
|
16666
|
+
"low-risk-change: adaptive flow selection assessed the change as low risk, so nothing needed to run.",
|
|
16667
|
+
"no-flows-to-run: no flow was eligible, because the trigger's flows are in maintenance, still drafts, or missing on this branch.",
|
|
16668
|
+
"no-matching-trigger: no deployment trigger matched.",
|
|
16669
|
+
"no-pull-request: the trigger uses adaptive flow selection, which needs an open pull request, and this deployment had none.",
|
|
16670
|
+
"no-relevant-flows: adaptive flow selection found no existing flow covering this change.",
|
|
16671
|
+
"rate-limited: too many runs were requested at once; retrying later can succeed.",
|
|
16672
|
+
"run-not-created: the run never reached a decision.",
|
|
16673
|
+
"skipped: the run was skipped for a reason with no more specific value.",
|
|
16674
|
+
"test-configuration-error: the workspace's flows or dependency rules need fixing before this can run.",
|
|
16675
|
+
"trigger-not-found: the trigger no longer exists.",
|
|
16676
|
+
"workspace-inactive: the workspace is not active.",
|
|
16677
|
+
"workspace-not-ready: the workspace has not finished setting up."
|
|
16678
|
+
].join(`
|
|
16679
|
+
`));
|
|
16680
|
+
|
|
16649
16681
|
// node_modules/@qawolf/api-contracts/dist/v1/resource.js
|
|
16650
16682
|
function resource(fields, { urlFieldDescription = "Absolute URL." } = {}) {
|
|
16651
16683
|
return object({
|
|
@@ -16814,7 +16846,7 @@ var defaultIdSchemas = {
|
|
|
16814
16846
|
trigger: string2().min(1).describe("The id of the trigger."),
|
|
16815
16847
|
workspace: string2().min(1).describe("The id of the workspace.")
|
|
16816
16848
|
};
|
|
16817
|
-
var workspaceForEnvironmentRef = (workspace) => workspace.optional().describe("The workspace the environment belongs to
|
|
16849
|
+
var workspaceForEnvironmentRef = (workspace) => workspace.optional().describe("The workspace the environment belongs to, which an alias resolves in. Read it from whoami.");
|
|
16818
16850
|
|
|
16819
16851
|
// node_modules/@qawolf/api-contracts/dist/v1/run/flowSelection.js
|
|
16820
16852
|
var makeFlowSelectionSchema = (ids) => object({
|
|
@@ -16986,9 +17018,10 @@ var runnerNameSchema = _enum([
|
|
|
16986
17018
|
"basic",
|
|
16987
17019
|
"playwright",
|
|
16988
17020
|
"android",
|
|
16989
|
-
"ios"
|
|
17021
|
+
"ios",
|
|
17022
|
+
"windows"
|
|
16990
17023
|
]);
|
|
16991
|
-
var runnerWorkspaceRequirement = "
|
|
17024
|
+
var runnerWorkspaceRequirement = "Read it from whoami.";
|
|
16992
17025
|
var runnerWorkspaceIdDescription = `The workspace the runner belongs to. ${runnerWorkspaceRequirement}`;
|
|
16993
17026
|
var runnerIdSchema = string2().min(1).max(63).regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "A runner id may contain only lowercase letters, digits and dashes, and must start and end with a letter or digit.");
|
|
16994
17027
|
var runnerWatchUrlSchema = url().describe("A QA Wolf page showing what the runner is doing right now, where the person who launched it can watch and take over with their own mouse and keyboard. Opening it requires being signed in to QA Wolf. This link belongs to the user: put it in a normal message as soon as the runner is launched, so they can follow along while the browser is being driven. It is theirs to open, never a page for the caller to fetch or navigate to. The page ends when the runner is terminated, so share it while the runner is alive and report what you found at the end instead of repeating a dead link.");
|
|
@@ -17106,7 +17139,11 @@ function makeRunnerFailureSchema(reasons) {
|
|
|
17106
17139
|
|
|
17107
17140
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/inspectMobile.js
|
|
17108
17141
|
var maxElementTextLength = 500;
|
|
17109
|
-
var selectorStrategySchema = _enum([
|
|
17142
|
+
var selectorStrategySchema = _enum([
|
|
17143
|
+
"ios-predicate",
|
|
17144
|
+
"shadow",
|
|
17145
|
+
"xpath"
|
|
17146
|
+
]);
|
|
17110
17147
|
var elementsRequestSchema = discriminatedUnion("by", [
|
|
17111
17148
|
object({
|
|
17112
17149
|
by: literal("point"),
|
|
@@ -17269,6 +17306,65 @@ var runFilesSchema = record(string2(), string2()).superRefine((files, refinement
|
|
|
17269
17306
|
}).refine((files) => runFilesByteLength(files) <= maxRunFilesByteLength, {
|
|
17270
17307
|
error: `The files in one request may carry at most ${maxRunFilesByteLength} bytes in total.`
|
|
17271
17308
|
});
|
|
17309
|
+
// node_modules/@qawolf/api-contracts/dist/v1/runner/runnerAction.js
|
|
17310
|
+
var maxSwipeDurationMs = 1e4;
|
|
17311
|
+
var selectorSchema2 = string2().min(1).max(maxSelectorLength).describe("The element to act on, resolved the way a screen object's own selector is.");
|
|
17312
|
+
var strategySchema = selectorStrategySchema.optional().describe("How `selector` is resolved. Defaults to `xpath`.");
|
|
17313
|
+
function refuseStrategyWithoutSelector(action, context) {
|
|
17314
|
+
if (action.strategy !== undefined && action.selector === undefined) {
|
|
17315
|
+
context.addIssue({
|
|
17316
|
+
code: "custom",
|
|
17317
|
+
message: "`strategy` says how to resolve a `selector`, so it needs one.",
|
|
17318
|
+
path: ["strategy"]
|
|
17319
|
+
});
|
|
17320
|
+
}
|
|
17321
|
+
}
|
|
17322
|
+
var tapActionSchema = strictObject({
|
|
17323
|
+
selector: selectorSchema2.optional(),
|
|
17324
|
+
strategy: strategySchema,
|
|
17325
|
+
type: literal("tap"),
|
|
17326
|
+
x: screenCoordinateSchema.optional(),
|
|
17327
|
+
y: screenCoordinateSchema.optional()
|
|
17328
|
+
}).superRefine((tap, context) => {
|
|
17329
|
+
refuseStrategyWithoutSelector(tap, context);
|
|
17330
|
+
const hasPoint = tap.x !== undefined || tap.y !== undefined;
|
|
17331
|
+
if (tap.selector !== undefined && hasPoint) {
|
|
17332
|
+
context.addIssue({
|
|
17333
|
+
code: "custom",
|
|
17334
|
+
message: "A tap aims at `x` and `y` or at a `selector`, not both.",
|
|
17335
|
+
path: ["selector"]
|
|
17336
|
+
});
|
|
17337
|
+
}
|
|
17338
|
+
if (tap.selector === undefined && (tap.x === undefined || tap.y === undefined)) {
|
|
17339
|
+
context.addIssue({
|
|
17340
|
+
code: "custom",
|
|
17341
|
+
message: "A tap needs both `x` and `y`, or a `selector`.",
|
|
17342
|
+
path: [tap.x === undefined ? "x" : "y"]
|
|
17343
|
+
});
|
|
17344
|
+
}
|
|
17345
|
+
});
|
|
17346
|
+
var swipeActionSchema = strictObject({
|
|
17347
|
+
duration_ms: int().positive().max(maxSwipeDurationMs).optional().describe("How long the swipe takes, in milliseconds. A slow one scrolls, a fast one flings. The device's default is 300."),
|
|
17348
|
+
from: screenPointSchema,
|
|
17349
|
+
to: screenPointSchema,
|
|
17350
|
+
type: literal("swipe")
|
|
17351
|
+
}).refine(({ from, to }) => from.x !== to.x || from.y !== to.y, {
|
|
17352
|
+
message: "A swipe whose `from` and `to` are the same travels nowhere.",
|
|
17353
|
+
path: ["to"]
|
|
17354
|
+
});
|
|
17355
|
+
var fillActionSchema = strictObject({
|
|
17356
|
+
selector: selectorSchema2,
|
|
17357
|
+
strategy: strategySchema,
|
|
17358
|
+
text: string2().max(maxTypedTextLength).describe("What the field holds afterwards, in place of its old value. Empty clears it."),
|
|
17359
|
+
type: literal("fill")
|
|
17360
|
+
});
|
|
17361
|
+
var runnerActionSchema = discriminatedUnion("type", [
|
|
17362
|
+
...browserActionSchema.options,
|
|
17363
|
+
tapActionSchema,
|
|
17364
|
+
swipeActionSchema,
|
|
17365
|
+
fillActionSchema
|
|
17366
|
+
]);
|
|
17367
|
+
|
|
17272
17368
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/screen.js
|
|
17273
17369
|
var screenFailureReasons = [
|
|
17274
17370
|
"runner-has-no-screen",
|
|
@@ -17277,17 +17373,18 @@ var screenFailureReasons = [
|
|
|
17277
17373
|
];
|
|
17278
17374
|
var screenNotReadyDescription = "`screen-not-ready` if the runner has a screen that cannot serve this instant. Retry in a second or two: the desktop restarts when a run changes the display size, and it serves one see-or-act request at a time, so a screenshot or action already in flight is the usual reason. Do not submit a run to clear this — a run may restart the display and discard what is on it.";
|
|
17279
17375
|
var screenNeedsARunDescription = "`screen-needs-a-run` if the runner's virtual desktop has never started. Waiting will not change this and retrying is pointless — call `runner.runFlow` with a flow that opens a browser, then ask for the screen again. On a runner image with a browser that has never run anything, any `runner.performAction` also starts the browser itself. Evaluating a snippet does not start the desktop.";
|
|
17280
|
-
var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner
|
|
17376
|
+
var runnerHasNoScreenDescription = "`runner-has-no-screen` if this runner has no browser desktop to see or drive, and retrying will never help. Launch a `playwright` runner, or on `windows` use `runner.runFlow`.";
|
|
17281
17377
|
var screenshotImageSchema = string2().min(1).describe("The screenshot, as a base64-encoded JPEG. Decode it and write the bytes to a `.jpg` file — writing this string to the file leaves you with base64 text rather than an image.");
|
|
17282
17378
|
|
|
17283
17379
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/performAction.js
|
|
17284
17380
|
var unreachableDescription = "`runner-unreachable` if the runner could not be reached: it may still be starting, it may have terminated after inactivity, or it may have stopped answering mid-action. This does not mean the action was not performed — take a screenshot before repeating it.";
|
|
17285
|
-
var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `click` taps
|
|
17381
|
+
var notSupportedOnMobileDescription = "`action-not-supported-on-mobile` if the runner is a mobile device and this action has no touchscreen equivalent: `double_click`, `scroll`, `move`, `keypress` and `navigate`, and a `click` whose `button` is not `left`, are all pointer-device concepts a touchscreen has nothing to offer for. `type` types into whatever the last tap focused. Deprecated on mobile and to be removed: `click` taps and `drag` swipes between its path's first and last point; send `tap` and `swipe` instead.";
|
|
17382
|
+
var mobileActionsDescription = "Only a mobile runner performs `tap`, `swipe` and `fill`: `tap` touches a point or the element a `selector` names, `swipe` moves from one point to another over `duration_ms`, and `fill` replaces the value of the field a `selector` names. A browser runner answers them with `action-not-supported-on-browser`.";
|
|
17286
17383
|
var withScreenshotDescription = "With `withScreenshot: true`, the answer also carries `imageJpegBase64`: a screenshot taken after the action. One call instead of `runner.performAction` followed by `runner.takeScreenshot`. The action itself is performed exactly as without the option; if the screen could serve no frame after it — a display restart, or a `navigate` on a desktop that is still starting — the action's result comes back without `imageJpegBase64`, so take a screenshot separately rather than repeating the action. On a mobile runner the screenshot is the device's own, taken right after a performed action.";
|
|
17287
17384
|
var maxActionErrorMessageLength = 1000;
|
|
17288
17385
|
var makePerformActionOnRunnerContract = (ids) => {
|
|
17289
17386
|
const input = object({
|
|
17290
|
-
action:
|
|
17387
|
+
action: runnerActionSchema.describe(`The action to perform. Coordinates are whole pixels on the runner's virtual desktop, in the same space as \`runner.takeScreenshot\`. The browser action shapes follow the computer-use vocabulary, minus \`screenshot\` (use \`runner.takeScreenshot\`) and \`wait\` (delay on the caller's side). A \`navigate\` does not go through the screen, so a screen that is not ready does not stop it. ${notSupportedOnMobileDescription} ${mobileActionsDescription}`),
|
|
17291
17388
|
id: runnerIdSchema.describe("Id of the runner to act on."),
|
|
17292
17389
|
withScreenshot: boolean2().optional().describe(withScreenshotDescription),
|
|
17293
17390
|
workspaceId: ids.workspace.optional().describe(runnerWorkspaceIdDescription)
|
|
@@ -17303,6 +17400,7 @@ var makePerformActionOnRunnerContract = (ids) => {
|
|
|
17303
17400
|
makeRunnerFailureSchema([
|
|
17304
17401
|
...screenFailureReasons,
|
|
17305
17402
|
"action-not-supported-on-mobile",
|
|
17403
|
+
"action-not-supported-on-browser",
|
|
17306
17404
|
runnerUnreachableFailureReason
|
|
17307
17405
|
])
|
|
17308
17406
|
]);
|
|
@@ -17319,7 +17417,7 @@ var makePerformActionOnRunnerContract = (ids) => {
|
|
|
17319
17417
|
openWorldHint: true,
|
|
17320
17418
|
readOnlyHint: false
|
|
17321
17419
|
},
|
|
17322
|
-
description: `Perform one raw
|
|
17420
|
+
description: `Perform one raw action on an interactive runner: click, double_click, move, drag, scroll, keypress, type, or navigate; on mobile, tap, swipe, fill, or type. One action per request, and the runner serves one at a time. A success means the action took effect. \`action-failed\`, with a reason, if it reached the runner and did not take effect. On a runner image with a browser, the first action on a runner that has never run anything starts its browser and waits for it, so it can take up to a minute to answer — no \`runner.runFlow\` is needed before acting; if the browser is still starting when the wait runs out, the answer is \`screen-not-ready\` and retrying converges. On a mobile runner, the same \`screen-needs-a-run\` and \`screen-not-ready\` outcomes mean no Appium session has started yet, or it did not answer this instant; \`runner.runFlow\` is what starts one, same as a browser. \`screen-needs-a-run\` if the browser could not be started that way — usually a runner whose runs all finished without starting its desktop; call \`runner.runFlow\` with a flow that opens a browser. ${screenNotReadyDescription} ${runnerHasNoScreenDescription} ${unreachableDescription}`,
|
|
17323
17421
|
input,
|
|
17324
17422
|
kind: "write",
|
|
17325
17423
|
name: "runner.performAction",
|
|
@@ -17534,7 +17632,6 @@ function makeRecordingContracts(ids) {
|
|
|
17534
17632
|
recordings: makeRunnerRecordingsContract(ids)
|
|
17535
17633
|
};
|
|
17536
17634
|
}
|
|
17537
|
-
|
|
17538
17635
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/runSelection.js
|
|
17539
17636
|
var runSelectionSchema = object({
|
|
17540
17637
|
endLine: int().positive().describe("Last line to run, 1-indexed and inclusive."),
|
|
@@ -17569,23 +17666,28 @@ var makeTriggerActionSchema = (ids) => object({
|
|
|
17569
17666
|
instructions: string2().min(1).optional().describe("Guidance for QA Wolf. Applies to generativeSuite only."),
|
|
17570
17667
|
investigateFailures: boolean2().optional().describe("Whether QA Wolf investigates failures in the resulting runs. Defaults to true."),
|
|
17571
17668
|
kind: triggerActionKindSchema.default("createSuite"),
|
|
17669
|
+
runConcurrencyLimit: string2().trim().min(1).max(255).optional().describe(`How many runs of the resulting suite may execute at once: a whole number from 1 to 1000, "unlimited", or a concurrency expression, which the server validates. It replaces the environment's limit rather than capping below it. Omit it to leave the environment's limit in charge.`),
|
|
17572
17670
|
tagNames: array(string2().min(1)).default([]).describe("Tags naming the flows to run. Combined with flowIds.")
|
|
17573
17671
|
}).describe("What the trigger runs when it fires.");
|
|
17574
17672
|
var makeTriggerScheduleFields = (ids) => ({
|
|
17575
17673
|
action: makeTriggerActionSchema(ids),
|
|
17576
17674
|
cadence: triggerCadenceSchema,
|
|
17577
17675
|
dayOfWeek: triggerDayOfWeekSchema.optional().describe("The day a weekly schedule fires on, read in timezoneId. Required when cadence is weekly."),
|
|
17676
|
+
daysOfWeek: array(triggerDayOfWeekSchema).min(1).refine((daysOfWeek) => new Set(daysOfWeek).size === daysOfWeek.length, {
|
|
17677
|
+
message: "Expected each day to be named at most once."
|
|
17678
|
+
}).optional().describe("The only days an hourly or daily schedule fires on, read in timezoneId. Name each day at most once. Omitting it fires on every day."),
|
|
17578
17679
|
environmentId: ids.environmentId.describe("The environment the scheduled runs happen in."),
|
|
17579
17680
|
minuteOfHour: number2().int().min(0).max(59).optional().describe("Minutes past the hour an hourly schedule fires. Defaults to 0."),
|
|
17580
17681
|
timeOfDay: string2().regex(/^([01]\d|2[0-3]):[0-5]\d$/).optional().describe('The wall clock time a daily or weekly schedule fires, as "HH:mm". Required when cadence is daily or weekly.'),
|
|
17581
|
-
timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone
|
|
17682
|
+
timezoneId: string2().min(1).refine(isTimezone, "Expected an IANA timezone, such as America/New_York.").optional().describe("The IANA timezone the schedule is read in, such as America/New_York. Required for every cadence: it sets the day boundaries daysOfWeek is read against, and the wall clock timeOfDay is read against.")
|
|
17582
17683
|
});
|
|
17583
17684
|
var makeTriggerDeploymentFields = (ids) => ({
|
|
17584
17685
|
action: makeTriggerActionSchema(ids),
|
|
17585
17686
|
branchPattern: string2().min(1).optional().describe("Only fire for deployments of a branch matching this pattern."),
|
|
17586
|
-
deployTargetPattern: string2().min(1).optional().describe("Only fire for deployments
|
|
17687
|
+
deployTargetPattern: string2().min(1).optional().describe("Only fire for deployments whose deploy target matches this pattern. A deploy target is the URL or label the deploy reported, which many deployments do not carry."),
|
|
17587
17688
|
environmentIds: array(ids.environment).default([]).describe("Only fire for deployments to these environments. Mutually exclusive with environmentPattern."),
|
|
17588
|
-
environmentPattern: string2().min(1).optional().describe("Only fire for deployments to environments matching this pattern. Mutually exclusive with environmentIds.")
|
|
17689
|
+
environmentPattern: string2().min(1).optional().describe("Only fire for deployments to environments matching this pattern. Mutually exclusive with environmentIds."),
|
|
17690
|
+
servicePattern: string2().min(1).optional().describe("Only fire for deployments whose service matches this pattern. A deployment that names no service never matches it.")
|
|
17589
17691
|
});
|
|
17590
17692
|
|
|
17591
17693
|
// node_modules/@qawolf/api-contracts/dist/v1/trigger/configurationRules.js
|
|
@@ -17618,23 +17720,31 @@ var checkAction = (action, ctx) => {
|
|
|
17618
17720
|
};
|
|
17619
17721
|
var requiredScheduleFields = {
|
|
17620
17722
|
daily: ["timeOfDay", "timezoneId"],
|
|
17621
|
-
hourly: [],
|
|
17723
|
+
hourly: ["timezoneId"],
|
|
17622
17724
|
weekly: ["dayOfWeek", "timeOfDay", "timezoneId"]
|
|
17623
17725
|
};
|
|
17726
|
+
var optionalScheduleFields = {
|
|
17727
|
+
daily: ["daysOfWeek"],
|
|
17728
|
+
hourly: ["daysOfWeek", "minuteOfHour"],
|
|
17729
|
+
weekly: []
|
|
17730
|
+
};
|
|
17624
17731
|
var cadencesUsingField = {
|
|
17625
17732
|
dayOfWeek: "a weekly cadence",
|
|
17733
|
+
daysOfWeek: "an hourly or daily cadence",
|
|
17626
17734
|
minuteOfHour: "an hourly cadence",
|
|
17627
17735
|
timeOfDay: "a daily or weekly cadence",
|
|
17628
|
-
timezoneId: "
|
|
17736
|
+
timezoneId: "an hourly, daily or weekly cadence"
|
|
17629
17737
|
};
|
|
17630
17738
|
var scheduleFields = [
|
|
17631
17739
|
"dayOfWeek",
|
|
17740
|
+
"daysOfWeek",
|
|
17632
17741
|
"minuteOfHour",
|
|
17633
17742
|
"timeOfDay",
|
|
17634
17743
|
"timezoneId"
|
|
17635
17744
|
];
|
|
17636
17745
|
var checkScheduleFields = (value, ctx) => {
|
|
17637
17746
|
const required = requiredScheduleFields[value.cadence];
|
|
17747
|
+
const optional = optionalScheduleFields[value.cadence];
|
|
17638
17748
|
for (const field of scheduleFields) {
|
|
17639
17749
|
const isSupplied = value[field] !== undefined;
|
|
17640
17750
|
if (required.includes(field)) {
|
|
@@ -17647,7 +17757,7 @@ var checkScheduleFields = (value, ctx) => {
|
|
|
17647
17757
|
}
|
|
17648
17758
|
continue;
|
|
17649
17759
|
}
|
|
17650
|
-
if (isSupplied && !(
|
|
17760
|
+
if (isSupplied && !optional.includes(field)) {
|
|
17651
17761
|
ctx.addIssue({
|
|
17652
17762
|
code: "custom",
|
|
17653
17763
|
message: `${field} applies to ${cadencesUsingField[field]} only.`,
|
|
@@ -18023,12 +18133,14 @@ var makeDeploymentResourceSchema = (ids) => resource({
|
|
|
18023
18133
|
commitAuthorName: string2().optional().describe("The author of the deployed commit."),
|
|
18024
18134
|
commitMessage: string2().optional().describe("The message of the deployed commit."),
|
|
18025
18135
|
commitSha: string2().optional().describe("The sha of the deployed commit."),
|
|
18136
|
+
commitUrl: string2().optional().describe("A link to the deployed commit, as declared by the deployment report."),
|
|
18026
18137
|
deployedAt: exports_iso.datetime().describe("When QA Wolf first received the deployment."),
|
|
18027
18138
|
deployTarget: string2().optional().describe("Identifies the deployed app within the environment: the URL it serves, or the build path of a mobile build. A trigger's deployTargetPattern matches against it."),
|
|
18028
18139
|
environmentId: ids.environment.describe("The QA Wolf environment the deployment reported into."),
|
|
18029
18140
|
environmentName: string2().optional().describe("The environment's name. Absent when the environment has since been deleted."),
|
|
18030
18141
|
id: ids.deployment,
|
|
18031
18142
|
provider: _enum(["github", "gitlab", "api"]).optional().describe("How QA Wolf received the deployment: a GitHub webhook, a GitLab webhook, or the deployment.reportStatus API."),
|
|
18143
|
+
service: string2().optional().describe("Which application was deployed, as the deployer named it. Absent when the deployer named none."),
|
|
18032
18144
|
status: _enum(["pending", "success", "failure", "inactive"]).optional().describe("The deployment's lifecycle status, in the vocabulary deployment.reportStatus accepts. Absent when no status was ever reported.")
|
|
18033
18145
|
}, {
|
|
18034
18146
|
urlFieldDescription: "Absolute URL of the workspace's deployments page."
|
|
@@ -18059,7 +18171,7 @@ var makeFindDeploymentsContract = (ids) => {
|
|
|
18059
18171
|
};
|
|
18060
18172
|
|
|
18061
18173
|
// node_modules/@qawolf/api-contracts/dist/v1/deployment/listTriggerEvaluations.js
|
|
18062
|
-
var conditionKindSchema = _enum(["environment", "deployTarget", "branch"]).describe("What the condition checks on the deployment: the environment it reported into, the deploy target
|
|
18174
|
+
var conditionKindSchema = _enum(["environment", "deployTarget", "branch", "service"]).describe("What the condition checks on the deployment: the environment it reported into, the deploy target it serves, the git branch of the deployed commit, or the service it deployed.");
|
|
18063
18175
|
var conditionVerdictSchema = discriminatedUnion("outcome", [
|
|
18064
18176
|
object({
|
|
18065
18177
|
kind: conditionKindSchema,
|
|
@@ -18082,12 +18194,13 @@ var makeRunOutcomeSchema = (ids) => discriminatedUnion("status", [
|
|
|
18082
18194
|
}),
|
|
18083
18195
|
object({ status: literal("starting") }),
|
|
18084
18196
|
object({
|
|
18085
|
-
|
|
18197
|
+
message: string2().describe("Why the matched trigger created no run, in plain language."),
|
|
18198
|
+
reason: didNotRunReasonSchema,
|
|
18086
18199
|
status: literal("did-not-run"),
|
|
18087
18200
|
supersededByRunId: ids.run.optional().describe("The run that covered this deployment instead, when an earlier delivery of the same deployment had already created one.")
|
|
18088
18201
|
}),
|
|
18089
18202
|
object({ status: literal("unknown") })
|
|
18090
|
-
]).describe("What became of the match. Matching is not running: a matched trigger can still be stopped from creating a run, and did-not-run carries the reason. starting means run creation is still in progress; unknown means QA Wolf has no record of what followed the match.");
|
|
18203
|
+
]).describe("What became of the match. Matching is not running: a matched trigger can still be stopped from creating a run, and did-not-run carries the reason. starting means run creation is still in progress; unknown means QA Wolf has no record of what followed the match. did-not-run also carries a stable reason to branch on, beside the message for a person to read.");
|
|
18091
18204
|
var makeVerdictSchema = (ids) => discriminatedUnion("outcome", [
|
|
18092
18205
|
object({
|
|
18093
18206
|
conditionSets: conditionSetsField,
|
|
@@ -18136,6 +18249,7 @@ var deploymentReportMetadata = strictObject({
|
|
|
18136
18249
|
commitAuthorName: string2().trim().min(1).max(255).describe("The display name of the person who authored the deployed commit.").optional(),
|
|
18137
18250
|
commitMessage: string2().trim().min(1).max(2048).describe("The message of the deployed commit. The deployments list shows its first line.").optional(),
|
|
18138
18251
|
commitSha: string2().trim().min(1).max(255).describe("The commit sha of the deployed application revision.").optional(),
|
|
18252
|
+
commitUrl: httpUrl().max(2048).describe("A link to the deployed commit in your code host. Send this when QA Wolf cannot resolve the commit itself, for example when the QA Wolf GitHub App is not installed.").optional(),
|
|
18139
18253
|
pullRequestNumber: number2().int().positive().describe("The number of the pull request the deployment belongs to. Requires repository.").optional(),
|
|
18140
18254
|
ref: string2().trim().min(1).max(255).describe("The branch or ref that was deployed.").optional(),
|
|
18141
18255
|
repository: string2().trim().min(1).max(255).describe('The owner/name of the repository, e.g. "acme/web".').optional()
|
|
@@ -18170,6 +18284,7 @@ var makeReportDeploymentStatusContract = (ids) => {
|
|
|
18170
18284
|
environmentVariables: record(string2(), string2()).describe("Environment variable overrides for the runs this deployment requests. A report that omits this field keeps the stored values. A report that sends it replaces them.").optional(),
|
|
18171
18285
|
metadata: deploymentReportMetadata.describe("Details the deployer declares about the deployed revision; a code host integration's own record of the same commit is shown in preference to the message and author declared here.").optional(),
|
|
18172
18286
|
providerDeploymentId: string2().trim().min(1).max(255).describe('Your identifier for the deployment, e.g. "vercel_dpl_123". Reports with the same providerDeploymentId update one deployment within this workspace.'),
|
|
18287
|
+
service: string2().trim().min(1).max(255).describe('Which application was deployed, e.g. "checkout-api", when several services deploy into one environment. A report that omits it keeps the stored value.').optional(),
|
|
18173
18288
|
status: deploymentStatusSchema.describe("The deployment lifecycle status. A deployment's first success report evaluates global triggers asynchronously, and it is the only report that does. The response does not include the resulting runs."),
|
|
18174
18289
|
workspaceId: ids.workspace.describe("The workspace to report the deployment status into. A team API key must name its own workspace.")
|
|
18175
18290
|
}).superRefine((value, context) => {
|
|
@@ -18840,6 +18955,70 @@ var makeGetIssueContract = (ids) => {
|
|
|
18840
18955
|
};
|
|
18841
18956
|
};
|
|
18842
18957
|
|
|
18958
|
+
// node_modules/@qawolf/api-contracts/dist/v1/investigation/finding.js
|
|
18959
|
+
var investigationFindingStateDescription = 'What the investigation concluded about the cause. Known values: "investigating", "fixed", "fix-proposed", "reported", "report-proposed", "flake", "question" and "dismissed". New values can appear.';
|
|
18960
|
+
var makeInvestigationFindingSchema = (ids) => object({
|
|
18961
|
+
actual: string2().optional(),
|
|
18962
|
+
commitHash: string2().optional(),
|
|
18963
|
+
decidedBy: _enum(["agent", "user"]).optional().describe("Who decided: the AI on its own, or a person who approved or dismissed it. Absent until someone decides."),
|
|
18964
|
+
disputeReason: string2().optional().describe("Why a person disputed what the AI did. Present on a proposal the AI made again after that dispute."),
|
|
18965
|
+
expected: string2().optional(),
|
|
18966
|
+
findingId: string2(),
|
|
18967
|
+
flowIds: array(ids.flow),
|
|
18968
|
+
headline: string2().optional(),
|
|
18969
|
+
issueId: ids.issue.optional(),
|
|
18970
|
+
kind: string2().describe('What the failure is. Known values: "maintenance", "bug", "flake" and "unknown". New values can appear.'),
|
|
18971
|
+
matchReason: string2().optional(),
|
|
18972
|
+
priority: issuePrioritySchema.optional(),
|
|
18973
|
+
question: object({
|
|
18974
|
+
answers: array(object({
|
|
18975
|
+
description: string2().optional(),
|
|
18976
|
+
title: string2(),
|
|
18977
|
+
value: string2().describe('What choosing this answer means. Known values: "apply", "dismiss", "report", "maintenance" and "bug". New values can appear.')
|
|
18978
|
+
})),
|
|
18979
|
+
text: string2()
|
|
18980
|
+
}).optional().describe("The question waiting for a person, with the answers offered."),
|
|
18981
|
+
response: object({
|
|
18982
|
+
answer: string2().optional(),
|
|
18983
|
+
at: exports_iso.datetime(),
|
|
18984
|
+
reason: string2().optional(),
|
|
18985
|
+
type: string2().describe('Known values: "answer" and "dispute". New values can appear.')
|
|
18986
|
+
}).optional().describe("A person's answer or dispute that the investigation hasn't acted on yet."),
|
|
18987
|
+
state: string2().describe(investigationFindingStateDescription),
|
|
18988
|
+
steps: array(string2()).optional(),
|
|
18989
|
+
subSessionIds: array(ids.chatSession),
|
|
18990
|
+
summary: string2().optional(),
|
|
18991
|
+
updatedAt: exports_iso.datetime()
|
|
18992
|
+
});
|
|
18993
|
+
|
|
18994
|
+
// node_modules/@qawolf/api-contracts/dist/v1/investigation/get.js
|
|
18995
|
+
var makeGetInvestigationContract = (ids) => {
|
|
18996
|
+
const input = object({ runId: ids.run });
|
|
18997
|
+
const output = resource({
|
|
18998
|
+
findings: array(makeInvestigationFindingSchema(ids)),
|
|
18999
|
+
runId: ids.run,
|
|
19000
|
+
sessionId: ids.chatSession.optional().describe("The investigation session. Absent when the run has none."),
|
|
19001
|
+
status: _enum(["investigating", "finished", "not-investigated"]).describe('Whether the investigation session is still working. "not-investigated" when the run has no investigation.')
|
|
19002
|
+
}, { urlFieldDescription: "The run in the QA Wolf app." });
|
|
19003
|
+
return {
|
|
19004
|
+
annotations: {
|
|
19005
|
+
destructiveHint: false,
|
|
19006
|
+
openWorldHint: false,
|
|
19007
|
+
readOnlyHint: true
|
|
19008
|
+
},
|
|
19009
|
+
description: "Read what the QA Wolf AI investigating a run has concluded: one finding per cause of its failures, " + "with the question waiting for a person and any answer or dispute the investigation hasn't acted on yet.",
|
|
19010
|
+
input,
|
|
19011
|
+
kind: "read",
|
|
19012
|
+
name: "investigation.get",
|
|
19013
|
+
output
|
|
19014
|
+
};
|
|
19015
|
+
};
|
|
19016
|
+
|
|
19017
|
+
// node_modules/@qawolf/api-contracts/dist/v1/investigation/index.js
|
|
19018
|
+
var makeInvestigationContracts = (ids) => ({
|
|
19019
|
+
get: makeGetInvestigationContract(ids)
|
|
19020
|
+
});
|
|
19021
|
+
|
|
18843
19022
|
// node_modules/@qawolf/api-contracts/dist/v1/issue/addFlows.js
|
|
18844
19023
|
var makeAddFlowsToIssueContract = (ids) => {
|
|
18845
19024
|
const input = object({
|
|
@@ -18868,7 +19047,7 @@ var makeCreateIssueContract = (ids) => {
|
|
|
18868
19047
|
const commonFields = {
|
|
18869
19048
|
description: string2().optional().describe("The issue description as plain text; each line becomes a paragraph. Markdown is not parsed."),
|
|
18870
19049
|
name: string2().trim().min(1).max(255),
|
|
18871
|
-
priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized".'),
|
|
19050
|
+
priority: issuePrioritySchema.optional().describe('Defaults to "unprioritized" for bug reports and coverage requests.'),
|
|
18872
19051
|
workspaceId: ids.workspace.optional().describe("The workspace to create the issue in. Required when authenticating with an organization or user API key.")
|
|
18873
19052
|
};
|
|
18874
19053
|
const input = discriminatedUnion("type", [
|
|
@@ -18880,6 +19059,13 @@ var makeCreateIssueContract = (ids) => {
|
|
|
18880
19059
|
...commonFields,
|
|
18881
19060
|
estimatedDueDate: exports_iso.date().optional().describe("The calendar date the coverage is estimated to be complete, as YYYY-MM-DD."),
|
|
18882
19061
|
type: literal("coverageRequest")
|
|
19062
|
+
}),
|
|
19063
|
+
object({
|
|
19064
|
+
...commonFields,
|
|
19065
|
+
effort: _enum(["extraSmall", "small", "medium", "large", "extraLarge"]).describe("The effort to repair the flows."),
|
|
19066
|
+
priority: _enum(["low", "medium", "high", "urgent"]),
|
|
19067
|
+
reason: _enum(["dataChanged", "flowNeedsWork", "other", "uiChanged"]).describe("Why the flows need maintenance."),
|
|
19068
|
+
type: literal("maintenance")
|
|
18883
19069
|
})
|
|
18884
19070
|
]);
|
|
18885
19071
|
const output = object({
|
|
@@ -18891,7 +19077,7 @@ var makeCreateIssueContract = (ids) => {
|
|
|
18891
19077
|
openWorldHint: true,
|
|
18892
19078
|
readOnlyHint: false
|
|
18893
19079
|
},
|
|
18894
|
-
description: "Create a bug or coverage request issue for the caller's team. " + "
|
|
19080
|
+
description: "Create a bug report, maintenance report, or coverage request issue for the caller's team. " + "A user can create a maintenance report only when they can see the workspace's maintenance reports; " + "a team or organization API key credits it to the workspace's automation user. " + "Link its failed flows afterwards with run.diagnose.",
|
|
18895
19081
|
input,
|
|
18896
19082
|
kind: "write",
|
|
18897
19083
|
name: "issue.create",
|
|
@@ -18980,6 +19166,8 @@ var makeLegacyTriggerSchema = (ids) => {
|
|
|
18980
19166
|
isPaused: boolean2(),
|
|
18981
19167
|
name: string2(),
|
|
18982
19168
|
pausedAt: exports_iso.datetime().optional(),
|
|
19169
|
+
runConcurrencyLimit: string2().describe(`How many of the trigger's runs may execute at once: a whole number, "unlimited", or a concurrency expression. A trigger that stores no limit reads as "unlimited", which leaves the environment's limit in charge. Copy a number or an expression onto the current trigger action's runConcurrencyLimit, and omit that field when this reads "unlimited".`),
|
|
19170
|
+
shouldTriage: boolean2().describe("Whether QA Wolf investigates the failures of the runs this trigger creates. It becomes the current trigger action's investigateFailures, which is on unless the trigger says otherwise."),
|
|
18983
19171
|
tags: array(namedIdentity)
|
|
18984
19172
|
};
|
|
18985
19173
|
return union([
|
|
@@ -19096,20 +19284,6 @@ var makeDiagnoseRunContract = (ids) => {
|
|
|
19096
19284
|
};
|
|
19097
19285
|
};
|
|
19098
19286
|
|
|
19099
|
-
// node_modules/@qawolf/api-contracts/dist/v1/run/summary.js
|
|
19100
|
-
var makeRunSummaryFields = (ids) => ({
|
|
19101
|
-
completedAt: exports_iso.datetime().optional().describe("When the run finished executing. Absent while queued or running, and also absent for a terminal run that never completed execution (e.g. every flow was canceled or skipped)."),
|
|
19102
|
-
createdAt: exports_iso.datetime(),
|
|
19103
|
-
git: object({
|
|
19104
|
-
branch: string2().optional(),
|
|
19105
|
-
commitMessage: string2().optional(),
|
|
19106
|
-
commitSha: string2().optional(),
|
|
19107
|
-
commitUrl: string2().optional().describe("Link to the commit on the code host.")
|
|
19108
|
-
}).describe("The branch and commit under test. The fields are present when a deploy notification started the run, and absent for runs started another way, for example manually or with run.create."),
|
|
19109
|
-
runId: ids.run,
|
|
19110
|
-
status: _enum(["queued", "running", "passed", "failed", "canceled"]).describe("Whole-run status. Terminal statuses are passed, failed, and canceled; poll until one is reached.")
|
|
19111
|
-
});
|
|
19112
|
-
|
|
19113
19287
|
// node_modules/@qawolf/api-contracts/dist/v1/run/find.js
|
|
19114
19288
|
var makeFindRunsContract = (ids) => {
|
|
19115
19289
|
const input = object({
|
|
@@ -19140,7 +19314,9 @@ var makeFindRunsContract = (ids) => {
|
|
|
19140
19314
|
|
|
19141
19315
|
// node_modules/@qawolf/api-contracts/dist/v1/run/get.js
|
|
19142
19316
|
var makeGetRunContract = (ids) => {
|
|
19317
|
+
const flowStatus = _enum(publicRunStatusValues);
|
|
19143
19318
|
const input = object({
|
|
19319
|
+
flowStatuses: array(flowStatus).min(1).optional().describe("Return only the flows whose status is one of these. A suite run can " + "hold hundreds of flows, so start an investigation with failed " + "alone. A flow that passed after a retry reads passed, so add " + "passed when a flaky flow is missing from the answer. Omit to " + "return every flow. The run-level fields are unaffected."),
|
|
19144
19320
|
runId: ids.run
|
|
19145
19321
|
});
|
|
19146
19322
|
const artifactUrls = {
|
|
@@ -19197,11 +19373,12 @@ var makeGetRunContract = (ids) => {
|
|
|
19197
19373
|
attempts,
|
|
19198
19374
|
flowId: ids.flow,
|
|
19199
19375
|
name: string2(),
|
|
19200
|
-
status:
|
|
19376
|
+
status: flowStatus.exclude(["failed"])
|
|
19201
19377
|
});
|
|
19202
|
-
const flows = array(discriminatedUnion("status", [failedFlow, nonFailedFlow])).describe("The run's flows, ordered alphabetically by name.");
|
|
19378
|
+
const flows = array(discriminatedUnion("status", [failedFlow, nonFailedFlow])).describe("The run's flows, ordered alphabetically by name. Only the flows " + "matching flowStatuses when the request set it.");
|
|
19203
19379
|
const output = resource({
|
|
19204
19380
|
...makeRunSummaryFields(ids),
|
|
19381
|
+
blockingBugCount: number2().int().nonnegative().describe("How many bugs this run found are blocking: still open, and priority urgent, high, or unprioritized — unprioritized counts because nobody has ruled it out yet. This is what `failed` is derived from, so it explains a failure rather than adding a second verdict: gate on `status`, then read this to say how many bugs are holding the build. It counts a bug filed against a later run by an investigation that carried over from this one, and it drops a bug once that bug is resolved."),
|
|
19205
19382
|
flows,
|
|
19206
19383
|
runId: ids.run.describe("The run this response describes. Treat it as canonical: it can differ from the id you asked for. A deploy notification returns a run id before the run exists, and if a second notification for the same commit is folded into an earlier run, that id resolves to the earlier run instead.")
|
|
19207
19384
|
}, { urlFieldDescription: "Absolute URL of the run page." });
|
|
@@ -19211,7 +19388,7 @@ var makeGetRunContract = (ids) => {
|
|
|
19211
19388
|
openWorldHint: false,
|
|
19212
19389
|
readOnlyHint: true
|
|
19213
19390
|
},
|
|
19214
|
-
description: "Get a run's status, per-flow results, and
|
|
19391
|
+
description: "Get a run's status, per-flow results, links, and how many of its bugs are blocking.",
|
|
19215
19392
|
input,
|
|
19216
19393
|
kind: "read",
|
|
19217
19394
|
name: "run.get",
|
|
@@ -19264,54 +19441,6 @@ var makeStopRunContract = (ids) => {
|
|
|
19264
19441
|
};
|
|
19265
19442
|
};
|
|
19266
19443
|
|
|
19267
|
-
// node_modules/@qawolf/api-contracts/dist/v1/run/triage.js
|
|
19268
|
-
var probability = number2().min(0).max(1);
|
|
19269
|
-
var verdictAnswer = object({
|
|
19270
|
-
choice: _enum(["bug", "maintenance"]),
|
|
19271
|
-
confidence: probability,
|
|
19272
|
-
probabilities: record(string2(), probability),
|
|
19273
|
-
type: literal("choice")
|
|
19274
|
-
});
|
|
19275
|
-
var makeTriageRunContract = (ids) => {
|
|
19276
|
-
const input = object({
|
|
19277
|
-
flowId: ids.flow.describe("The flow that failed in the run."),
|
|
19278
|
-
runId: ids.run
|
|
19279
|
-
});
|
|
19280
|
-
const decision = discriminatedUnion("type", [
|
|
19281
|
-
object({
|
|
19282
|
-
diagnosis: _enum(["bug", "maintenance"]),
|
|
19283
|
-
type: literal("diagnose")
|
|
19284
|
-
}),
|
|
19285
|
-
object({
|
|
19286
|
-
diagnosis: _enum(["bug", "maintenance"]),
|
|
19287
|
-
type: literal("suggest")
|
|
19288
|
-
}),
|
|
19289
|
-
object({
|
|
19290
|
-
type: literal("needsHuman")
|
|
19291
|
-
})
|
|
19292
|
-
]);
|
|
19293
|
-
const output = object({
|
|
19294
|
-
answers: object({
|
|
19295
|
-
verdict: verdictAnswer
|
|
19296
|
-
}),
|
|
19297
|
-
decision: decision.describe("What the triage would do with the verdict. The prototype records nothing; it only reports."),
|
|
19298
|
-
model: string2(),
|
|
19299
|
-
state: json().describe("The context that was sent to the model, for inspection.")
|
|
19300
|
-
});
|
|
19301
|
-
return {
|
|
19302
|
-
annotations: {
|
|
19303
|
-
destructiveHint: false,
|
|
19304
|
-
openWorldHint: false,
|
|
19305
|
-
readOnlyHint: true
|
|
19306
|
-
},
|
|
19307
|
-
description: "Prototype. Ask Jev, a TypeSafe System One model, whether a flow failure in a run is a bug in the product " + "or a test that needs maintenance. Compares the failing attempt with the flow's last passing run in the " + "same environment. Records nothing.",
|
|
19308
|
-
input,
|
|
19309
|
-
kind: "read",
|
|
19310
|
-
name: "run.triage",
|
|
19311
|
-
output
|
|
19312
|
-
};
|
|
19313
|
-
};
|
|
19314
|
-
|
|
19315
19444
|
// node_modules/@qawolf/api-contracts/dist/v1/runner/evaluateSnippet.js
|
|
19316
19445
|
var maxSnippetCodeLength = 64 * 1024;
|
|
19317
19446
|
var makeEvaluateSnippetOnRunnerContract = (ids) => {
|
|
@@ -19463,8 +19592,12 @@ var makeImportPackageOnRunnerContract = (ids) => {
|
|
|
19463
19592
|
var makeLaunchRunnerContract = (ids) => {
|
|
19464
19593
|
const input = object({
|
|
19465
19594
|
id: runnerIdSchema.describe("Id to launch the runner under, chosen by the caller. Launching the same id again returns the runner already running under it."),
|
|
19595
|
+
initialUrl: navigableUrlSchema.optional().describe("The page to open as the browser starts, so the first screenshot already shows the application rather than a blank page."),
|
|
19466
19596
|
runnerName: runnerNameSchema.optional().describe("The runner family to launch. Defaults to the standard web family, playwright."),
|
|
19467
19597
|
workspaceId: ids.workspace.optional().describe(`The workspace to launch the runner in. ${runnerWorkspaceRequirement}`)
|
|
19598
|
+
}).refine((request) => request.initialUrl === undefined || (request.runnerName ?? "playwright") === "playwright", {
|
|
19599
|
+
message: "initialUrl opens a page in the runner's browser, so only the playwright runner takes it.",
|
|
19600
|
+
path: ["initialUrl"]
|
|
19468
19601
|
});
|
|
19469
19602
|
const output = makeRunnerSchema().extend({
|
|
19470
19603
|
alreadyRunning: boolean2().describe("True when a runner was already running under this id and was returned unchanged, so no second runner was started and nothing new is billed. Not an error either way."),
|
|
@@ -19476,7 +19609,7 @@ var makeLaunchRunnerContract = (ids) => {
|
|
|
19476
19609
|
openWorldHint: false,
|
|
19477
19610
|
readOnlyHint: false
|
|
19478
19611
|
},
|
|
19479
|
-
description: "Launch an interactive runner on the caller's team under an id the caller chooses. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner
|
|
19612
|
+
description: "Launch an interactive runner on the caller's team under an id the caller chooses. Send `initialUrl` so its browser comes up on the page the work starts from, which saves a separate navigation and the browser's cold start. Launching the same id again returns the runner already running rather than starting a second one, and the same id with a different runnerName is refused. A runner is not permanent: it terminates on its own after a period of inactivity, and launching the same id after that starts and bills a new runner, so read `alreadyRunning` to tell which happened. A success means the runner is answering: the call waits for the pod it started to come up, so the very next call to the runner reaches it. If the pod does not come up in time the call fails instead, leaving the runner running, and launching the same id again attaches to it.",
|
|
19480
19613
|
input,
|
|
19481
19614
|
kind: "write",
|
|
19482
19615
|
name: "runner.launch",
|
|
@@ -19522,7 +19655,7 @@ var makeListRunnersContract = (ids) => {
|
|
|
19522
19655
|
openWorldHint: false,
|
|
19523
19656
|
readOnlyHint: true
|
|
19524
19657
|
},
|
|
19525
|
-
description: "List the runners running on the caller's team right now. A
|
|
19658
|
+
description: "List the runners running on the caller's team right now. A listed runner may be driven by another machine or session, so sending it work can collide with theirs. A runner that was terminated, or that terminated on its own after inactivity, is not listed, because the run system keeps no record of a runner once it is gone. This is a lookup: it never starts a runner, and it does not reset a runner's inactivity clock the way reading its journal does. It is how to find a runner launched from another machine or in an earlier session, when the id it was launched under is no longer at hand.",
|
|
19526
19659
|
input,
|
|
19527
19660
|
kind: "read",
|
|
19528
19661
|
name: "runner.list",
|
|
@@ -19607,6 +19740,7 @@ var makeRunFlowOnRunnerContract = (ids) => {
|
|
|
19607
19740
|
env: runEnvironmentSchema.optional().describe("Environment variables to make available to the run."),
|
|
19608
19741
|
environmentId: ids.environmentRef.optional().describe("A QA Wolf environment whose variables the run is given, by id or alias. QA Wolf reads and decrypts them itself, so they never travel in the request and the count and length limits on `env` do not apply to them. Send this or `env`, not both."),
|
|
19609
19742
|
files: runFilesSchema.describe("Every file the run needs keyed by its path — the flow file, everything it imports, package.json and tsconfig.json. A runner holds no copy of your project, so what runs is exactly what is sent here."),
|
|
19743
|
+
flowId: ids.flow.optional().describe("The QA Wolf flow this run is for. The run then sees it as `QAWOLF_WORKFLOW_ID`, the same value a platform run of that flow sees, so fixtures named and cleaned up by it match across both. Omit it when the flow is not in QA Wolf yet, and the run has no `QAWOLF_WORKFLOW_ID`."),
|
|
19610
19744
|
id: runnerIdSchema.describe("Id of the runner to run the flow on."),
|
|
19611
19745
|
selection: runSelectionSchema.optional().describe("Run only these lines, inside the page the runner is already on, instead of running the whole flow from a fresh browser. Omit to run the whole entry point."),
|
|
19612
19746
|
unchangedFiles: unchangedFilesSchema.optional().describe("Files this runner already holds from an earlier run, keyed by path with a hex SHA-256 of the content it should hold. Send this to make `files` only what changed. The runner refuses with `needs-full-sync` if it holds none of a referenced path, so it never runs something other than what was asked for. Omit it to send every file."),
|
|
@@ -19858,6 +19992,7 @@ var makeContractsV1 = (ids) => {
|
|
|
19858
19992
|
removeTag: makeRemoveTagFromFlowsContract(resolvedIds),
|
|
19859
19993
|
update: makeUpdateFlowContract(resolvedIds)
|
|
19860
19994
|
},
|
|
19995
|
+
investigation: makeInvestigationContracts(resolvedIds),
|
|
19861
19996
|
issue: {
|
|
19862
19997
|
addFlows: makeAddFlowsToIssueContract(resolvedIds),
|
|
19863
19998
|
create: makeCreateIssueContract(resolvedIds),
|
|
@@ -19873,8 +20008,7 @@ var makeContractsV1 = (ids) => {
|
|
|
19873
20008
|
find: makeFindRunsContract(resolvedIds),
|
|
19874
20009
|
get: makeGetRunContract(resolvedIds),
|
|
19875
20010
|
reattempt: makeReattemptRunContract(resolvedIds),
|
|
19876
|
-
stop: makeStopRunContract(resolvedIds)
|
|
19877
|
-
triage: makeTriageRunContract(resolvedIds)
|
|
20011
|
+
stop: makeStopRunContract(resolvedIds)
|
|
19878
20012
|
},
|
|
19879
20013
|
runner: makeRunnerContracts(resolvedIds),
|
|
19880
20014
|
skill: makeSkillContracts(),
|
|
@@ -22390,7 +22524,7 @@ function startUpdateCheck(deps) {
|
|
|
22390
22524
|
// package.json
|
|
22391
22525
|
var package_default = {
|
|
22392
22526
|
name: "@qawolf/cli",
|
|
22393
|
-
version: "1.
|
|
22527
|
+
version: "1.36.0",
|
|
22394
22528
|
description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
|
|
22395
22529
|
keywords: [
|
|
22396
22530
|
"automation",
|
|
@@ -22461,7 +22595,7 @@ var package_default = {
|
|
|
22461
22595
|
"@clack/prompts": "1.5.1",
|
|
22462
22596
|
"@napi-rs/keyring": "1.3.0",
|
|
22463
22597
|
"@oxc-node/core": "0.1.0",
|
|
22464
|
-
"@qawolf/api-contracts": "0.
|
|
22598
|
+
"@qawolf/api-contracts": "0.73.0",
|
|
22465
22599
|
"@qawolf/emails": "1.1.1",
|
|
22466
22600
|
"@qawolf/flow-targets": "1.0.0",
|
|
22467
22601
|
"@qawolf/flows": "0.1.4",
|
|
@@ -35991,6 +36125,21 @@ async function writeSequenceFrames(options, deps) {
|
|
|
35991
36125
|
};
|
|
35992
36126
|
}
|
|
35993
36127
|
|
|
36128
|
+
// src/core/interactiveRunner/flagValues.ts
|
|
36129
|
+
function parsePoint(flag, point) {
|
|
36130
|
+
const [x, y, ...rest] = point.split(",");
|
|
36131
|
+
if (x === undefined || y === undefined || rest.length > 0) {
|
|
36132
|
+
return {
|
|
36133
|
+
error: `${flag} must be one point as x,y in screenshot pixels, for example 200,800.`,
|
|
36134
|
+
ok: false
|
|
36135
|
+
};
|
|
36136
|
+
}
|
|
36137
|
+
return { ok: true, value: { x: toNumber(x), y: toNumber(y) } };
|
|
36138
|
+
}
|
|
36139
|
+
function toNumber(value) {
|
|
36140
|
+
return value.trim() === "" ? Number.NaN : Number(value);
|
|
36141
|
+
}
|
|
36142
|
+
|
|
35994
36143
|
// src/core/interactiveRunner/browserAction.ts
|
|
35995
36144
|
function parseJsonPath(path) {
|
|
35996
36145
|
try {
|
|
@@ -36002,34 +36151,48 @@ function parseJsonPath(path) {
|
|
|
36002
36151
|
};
|
|
36003
36152
|
}
|
|
36004
36153
|
}
|
|
36005
|
-
function
|
|
36006
|
-
return value.trim() === "" ? Number.NaN : Number(value);
|
|
36007
|
-
}
|
|
36008
|
-
function buildBrowserAction(type, flags) {
|
|
36154
|
+
function buildRunnerAction(type, flags) {
|
|
36009
36155
|
const parsedPath = flags.path === undefined ? undefined : parseJsonPath(flags.path);
|
|
36010
36156
|
if (parsedPath !== undefined && !parsedPath.ok)
|
|
36011
36157
|
return parsedPath;
|
|
36158
|
+
const from = flags.from === undefined ? undefined : parsePoint("--from", flags.from);
|
|
36159
|
+
if (from !== undefined && !from.ok)
|
|
36160
|
+
return from;
|
|
36161
|
+
const to = flags.to === undefined ? undefined : parsePoint("--to", flags.to);
|
|
36162
|
+
if (to !== undefined && !to.ok)
|
|
36163
|
+
return to;
|
|
36012
36164
|
const candidate = {
|
|
36013
36165
|
type,
|
|
36014
36166
|
...flags.button === undefined ? {} : { button: flags.button },
|
|
36167
|
+
...flags.durationMs === undefined ? {} : { duration_ms: toNumber(flags.durationMs) },
|
|
36168
|
+
...from === undefined ? {} : { from: from.value },
|
|
36015
36169
|
...flags.keys === undefined ? {} : { keys: flags.keys },
|
|
36016
36170
|
...parsedPath === undefined ? {} : { path: parsedPath.value },
|
|
36017
36171
|
...flags.scrollX === undefined ? {} : { scroll_x: toNumber(flags.scrollX) },
|
|
36018
36172
|
...flags.scrollY === undefined ? {} : { scroll_y: toNumber(flags.scrollY) },
|
|
36173
|
+
...flags.selector === undefined ? {} : { selector: flags.selector },
|
|
36174
|
+
...flags.strategy === undefined ? {} : { strategy: flags.strategy },
|
|
36019
36175
|
...flags.text === undefined ? {} : { text: flags.text },
|
|
36176
|
+
...to === undefined ? {} : { to: to.value },
|
|
36020
36177
|
...flags.url === undefined ? {} : { url: flags.url },
|
|
36021
36178
|
...flags.x === undefined ? {} : { x: toNumber(flags.x) },
|
|
36022
36179
|
...flags.y === undefined ? {} : { y: toNumber(flags.y) }
|
|
36023
36180
|
};
|
|
36024
|
-
return
|
|
36181
|
+
return parseRunnerAction(candidate);
|
|
36025
36182
|
}
|
|
36026
|
-
function
|
|
36027
|
-
const parsed =
|
|
36183
|
+
function parseWith(schema, candidate) {
|
|
36184
|
+
const parsed = schema.safeParse(candidate);
|
|
36028
36185
|
if (!parsed.success) {
|
|
36029
36186
|
return { error: prettifyError(parsed.error), ok: false };
|
|
36030
36187
|
}
|
|
36031
36188
|
return { action: parsed.data, ok: true };
|
|
36032
36189
|
}
|
|
36190
|
+
function parseRunnerAction(candidate) {
|
|
36191
|
+
return parseWith(runnerActionSchema, candidate);
|
|
36192
|
+
}
|
|
36193
|
+
function parseBrowserAction(candidate) {
|
|
36194
|
+
return parseWith(browserActionSchema, candidate);
|
|
36195
|
+
}
|
|
36033
36196
|
|
|
36034
36197
|
// src/domains/interactiveRunner/readActions.ts
|
|
36035
36198
|
var stdinArgument = "-";
|
|
@@ -37224,6 +37387,11 @@ function describePerformActionFailure(options) {
|
|
|
37224
37387
|
error: interactiveRunnerMessages.actionNotSupportedOnMobile(actionType),
|
|
37225
37388
|
exitCode: exitCodes.invalidArgs
|
|
37226
37389
|
};
|
|
37390
|
+
case "action-not-supported-on-browser":
|
|
37391
|
+
return {
|
|
37392
|
+
error: interactiveRunnerMessages.actionNotSupportedOnBrowser(actionType),
|
|
37393
|
+
exitCode: exitCodes.invalidArgs
|
|
37394
|
+
};
|
|
37227
37395
|
case "screen-needs-a-run":
|
|
37228
37396
|
return {
|
|
37229
37397
|
error: interactiveRunnerMessages.screenNeedsARun,
|
|
@@ -37307,7 +37475,7 @@ async function describeFailureScreenshot(options, deps) {
|
|
|
37307
37475
|
var stdinArgument3 = "-";
|
|
37308
37476
|
async function readAction(type, flags, deps) {
|
|
37309
37477
|
if (type !== stdinArgument3)
|
|
37310
|
-
return
|
|
37478
|
+
return buildRunnerAction(type, flags);
|
|
37311
37479
|
if (Object.values(flags).some((value) => value !== undefined)) {
|
|
37312
37480
|
return { error: interactiveRunnerMessages.actionFlagsWithStdin, ok: false };
|
|
37313
37481
|
}
|
|
@@ -37316,7 +37484,7 @@ async function readAction(type, flags, deps) {
|
|
|
37316
37484
|
return { error: interactiveRunnerMessages.stdinEmptyAction, ok: false };
|
|
37317
37485
|
}
|
|
37318
37486
|
try {
|
|
37319
|
-
return
|
|
37487
|
+
return parseRunnerAction(JSON.parse(piped));
|
|
37320
37488
|
} catch {
|
|
37321
37489
|
return { error: interactiveRunnerMessages.actionNotJson, ok: false };
|
|
37322
37490
|
}
|
|
@@ -37452,14 +37620,7 @@ function describeUnwritten(written, out) {
|
|
|
37452
37620
|
};
|
|
37453
37621
|
}
|
|
37454
37622
|
|
|
37455
|
-
// src/commands/runner/
|
|
37456
|
-
var defaultScreenshotPath = "screenshot.jpg";
|
|
37457
|
-
var screenshotExamples = `
|
|
37458
|
-
Examples:
|
|
37459
|
-
$ qawolf runner screenshot
|
|
37460
|
-
$ qawolf runner screenshot --out screens/step-3.jpg
|
|
37461
|
-
$ qawolf runner screenshot --out - > step-3.jpg
|
|
37462
|
-
$ qawolf runner screenshot --out - | my-vision-tool`;
|
|
37623
|
+
// src/commands/runner/actExamples.ts
|
|
37463
37624
|
var actExamples = `
|
|
37464
37625
|
Examples:
|
|
37465
37626
|
$ qawolf runner act click --button left --x 480 --y 260
|
|
@@ -37469,17 +37630,37 @@ Examples:
|
|
|
37469
37630
|
$ qawolf runner act drag --path '[{"x":10,"y":20},{"x":80,"y":90}]'
|
|
37470
37631
|
$ qawolf runner act click --button left --x 480 --y 260 --screenshot step-4.jpg
|
|
37471
37632
|
$ echo '{"type":"click","button":"left","x":1,"y":2}' | qawolf runner act -
|
|
37472
|
-
$ echo '{"type":"click","button":"left","x":1,"y":2}' | qawolf runner act - --screenshot - > step-5.jpg
|
|
37633
|
+
$ echo '{"type":"click","button":"left","x":1,"y":2}' | qawolf runner act - --screenshot - > step-5.jpg
|
|
37634
|
+
|
|
37635
|
+
Mobile:
|
|
37636
|
+
$ qawolf runner act tap --x 540 --y 1200
|
|
37637
|
+
$ qawolf runner act tap --selector '//*[@content-desc="Continue"]'
|
|
37638
|
+
$ qawolf runner act fill --selector 'name == "Postal code"' --strategy ios-predicate --text 94107
|
|
37639
|
+
$ qawolf runner act swipe --from 540,1600 --to 540,600 --duration-ms 1500`;
|
|
37640
|
+
|
|
37641
|
+
// src/commands/runner/interact.register.ts
|
|
37642
|
+
var defaultScreenshotPath = "screenshot.jpg";
|
|
37643
|
+
var screenshotExamples = `
|
|
37644
|
+
Examples:
|
|
37645
|
+
$ qawolf runner screenshot
|
|
37646
|
+
$ qawolf runner screenshot --out screens/step-3.jpg
|
|
37647
|
+
$ qawolf runner screenshot --out - > step-3.jpg
|
|
37648
|
+
$ qawolf runner screenshot --out - | my-vision-tool`;
|
|
37473
37649
|
function registerRunnerInteractCommands(runner, signals) {
|
|
37474
37650
|
declareCommandKind(runner.command("screenshot"), "read").description("Save a JPEG of an interactive runner's screen to a file, or write it to stdout with --out -").option("--out <path>", "File to write the image to. - writes the JPEG bytes to stdout on their own and moves the confirmation, JSON included, to stderr", defaultScreenshotPath).option("--runner <id>", runnerFlagDescription).addHelpText("after", screenshotExamples).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerScreenshot(ctx, { out: opts.out, runner: opts.runner }, runnerDeps(ctx)))(opts, command));
|
|
37475
|
-
declareCommandKind(runner.command("act <action>"), "write").description("Perform one raw action on a runner's screen
|
|
37651
|
+
declareCommandKind(runner.command("act <action>"), "write").description("Perform one raw action on a runner's screen. A browser runner takes click, double_click, scroll, move, drag, keypress, navigate and type; a mobile runner takes tap, swipe, fill and type. A browser runner answers mobile actions with action-not-supported-on-browser; a mobile runner answers the other browser actions with action-not-supported-on-mobile. Use - to read a whole action as JSON from stdin").option("--button <button>", "click: left, right, wheel, back or forward").option("--duration-ms <ms>", "swipe: how long it takes, up to 10000. Slow scrolls, fast flings").option("--from <x,y>", "swipe: the point it starts at").option("--keys <keys...>", "keypress: modifiers and the key, e.g. Control a").option("--path <json>", "drag: JSON array of points to drag through").option("--runner <id>", runnerFlagDescription).option("--screenshot <path>", "Also save a JPEG of the screen, taken after the action, to this file, in place of a separate screenshot. An action that did not take effect answers with one too. - writes it to stdout and moves the confirmation, JSON included, to stderr").option("--scroll-x <delta>", "scroll: horizontal wheel delta").option("--scroll-y <delta>", "scroll: vertical wheel delta").option("--selector <selector>", "tap or fill: the element to act on, as a screen object would find it. tap takes it in place of --x and --y").option("--strategy <strategy>", "how --selector is resolved: xpath (default), ios-predicate or shadow").option("--text <text>", "type: the text to type into what has focus. fill: the field's new value").option("--to <x,y>", "swipe: the point it ends at").option("--url <url>", "navigate: the http or https URL to go to").option("--x <pixels>", "click, tap and the like: x, in screenshot pixels").option("--y <pixels>", "click, tap and the like: y, in screenshot pixels").addHelpText("after", actExamples).action((action, opts, command) => withAuthContext(signals, (ctx) => handleRunnerAct(ctx, {
|
|
37476
37652
|
flags: {
|
|
37477
37653
|
button: opts.button,
|
|
37654
|
+
durationMs: opts.durationMs,
|
|
37655
|
+
from: opts.from,
|
|
37478
37656
|
keys: opts.keys,
|
|
37479
37657
|
path: opts.path,
|
|
37480
37658
|
scrollX: opts.scrollX,
|
|
37481
37659
|
scrollY: opts.scrollY,
|
|
37660
|
+
selector: opts.selector,
|
|
37661
|
+
strategy: opts.strategy,
|
|
37482
37662
|
text: opts.text,
|
|
37663
|
+
to: opts.to,
|
|
37483
37664
|
url: opts.url,
|
|
37484
37665
|
x: opts.x,
|
|
37485
37666
|
y: opts.y
|
|
@@ -38665,4 +38846,4 @@ createProgram({ signals }).parseAsync().catch(() => {
|
|
|
38665
38846
|
process.exitCode = 1;
|
|
38666
38847
|
}).finally(() => exitWhenIdle(typeof process.exitCode === "number" ? process.exitCode : 0));
|
|
38667
38848
|
|
|
38668
|
-
//# debugId=
|
|
38849
|
+
//# debugId=9A39ADF2531708B264756E2164756E21
|