@keepsnappy/appium-driver 0.1.0-alpha.12 → 0.1.0-alpha.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/dist/src/browserstack.js +1 -1
- package/dist/src/browserstack.js.map +1 -1
- package/dist/src/cli.js +0 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/links.d.ts +4 -1
- package/dist/src/links.js +5 -2
- package/dist/src/links.js.map +1 -1
- package/dist/src/platform.d.ts +11 -2
- package/dist/src/platform.js +45 -38
- package/dist/src/platform.js.map +1 -1
- package/dist/src/run.d.ts +27 -2
- package/dist/src/run.js +209 -48
- package/dist/src/run.js.map +1 -1
- package/dist/src/session.d.ts +66 -3
- package/dist/src/session.js +127 -7
- package/dist/src/session.js.map +1 -1
- package/dist/src/tokens.d.ts +1 -1
- package/dist/src/tokens.js +2 -2
- package/dist/src/tokens.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @keepsnappy/appium-driver
|
|
2
2
|
|
|
3
|
-
KeepSnappy's built-in Appium driver for `
|
|
3
|
+
KeepSnappy's built-in Appium driver for `keepsnappy farm run --driver appium --journey-module <file>` (BrowserStack App Automate, iOS and Android; `--platform ios|android`, default ios). A thin step vocabulary over W3C WebDriver: you write the journey, the driver owns the session, run tokens, step markers, the readiness wait (`expectNext`) after a touch and the result files. Design: `docs/plans/54b-appium-driver.md`.
|
|
4
4
|
|
|
5
5
|
A journey module default-exports `defineJourney({ app, home, options?, setup?, journeys })`; see the plan for the full shape. A journey needs no import from this package: selectors are plain objects (`{ id }`, `{ text }`, `{ ...sel, childOf }`, or a bare string) and everything else is on the `t` it is given (`t.acceptAlert`, `t.openLink`, ...). `defineJourney` is only an identity helper for editor types. The CLI runs its own bundled copy, so do not `instanceof` driver errors (`WdError`) from your own copy; test `e.wdError`.
|
|
6
6
|
|
|
@@ -20,7 +20,7 @@ How to write journeys that run fast on Android, with measured costs: `docs/writi
|
|
|
20
20
|
|
|
21
21
|
With `--action-gc on` the driver asks the app for a full garbage collection before every declared step, after the step's readiness wait and before its start marker, and once more before the run's flush. Design: `docs/plans/gc-before-action.md`; device checks: `docs/plans/gc-before-action-measurement.md`.
|
|
22
22
|
|
|
23
|
-
- Each command has a number `n`, unique in the session. Android sends it as a broadcast (`mobile: broadcast`, action `<bundleId>.
|
|
23
|
+
- Each command has a number `n`, unique in the session. Android sends it as a broadcast (`mobile: broadcast`, action `<bundleId>.keepsnappy.COMMAND`, extras `cmd=gc`, `n`) and reads the answer `gc:<n> ...` from the broadcast's result. iOS opens `<scheme>devtools/keepsnappy?cmd=gc&n=<n>` and waits up to 10 s for the element `keepsnappy.ack` whose label starts with `gc:<n> `.
|
|
24
24
|
- The step's start marker carries `gc_n`, so the backend (derivation 18) pairs the step with its GC record without mapping clocks.
|
|
25
25
|
- No answer turns the command off for the rest of the session (`actionGc: unsupported` in `driver-log.json`); the test still passes. Safari link mode sends none (`safari`).
|
|
26
26
|
- The GC command ends the app's open windows: runs with and without it are a different instrument (`actionGc` aspect), never compared as an app change.
|
|
@@ -32,7 +32,12 @@ One GC command at the end of every run, after the journey's last step and its re
|
|
|
32
32
|
- Same command and fallbacks as above; an app that does not answer turns it off for the rest of the session.
|
|
33
33
|
- The command ends the last open window (end reason `gc-command`) instead of the flush: that one window per run is shorter than on a driver without it. Driver 0.2.0 carries both commands, so runs before and after it are a different instrument already (`driverVersion` aspect).
|
|
34
34
|
- On by default (REQ-MEAS-35, REQ-FARM-28; driver 0.3.0); `--end-gc off` or `endGc: false` turns it off. It changes the memory readings only (it runs after the last window): a main without it still judges a PR's render, commit and component measures; only the memory verdict needs end-GC runs on both sides (`endGc` setup aspect, memory measures only). Older SDKs do not answer and send no line.
|
|
35
|
+
- Right after the GC's answer the driver sends `memread` (same n) and waits for its answer before it sends the markers and the flush link, which background the app. The SDK takes one memory sample at once (`endgc-read:<n>`); memory kept is derived from it (derivation 23). No answer: logged as `memread` status 1, the run goes on, and later runs of the session do not ask.
|
|
35
36
|
|
|
36
37
|
## The default run configuration (`links.ts`)
|
|
37
38
|
|
|
38
|
-
`RUN_DEFAULTS` and the link builders are the one source of the activation, flush and GC links (REQ-FARM-28): `profile=1`, `diag=1` (the React export), ttl 3600, no `cpuprof`, and the end GC on (`END_GC_DEFAULT`). A journey module's `sdkArgs` (`k=v&...`) are set over the defaults key by key, so `sdkArgs: 'profile=1'` still gets `diag=1`; `diag=0` turns the export off explicitly. `
|
|
39
|
+
`RUN_DEFAULTS` and the link builders are the one source of the activation, flush and GC links (REQ-FARM-28): `profile=1`, `diag=1` (the React export), ttl 3600, no `cpuprof`, and the end GC on (`END_GC_DEFAULT`). A journey module's `sdkArgs` (`k=v&...`) are set over the defaults key by key, so `sdkArgs: 'profile=1'` still gets `diag=1`; `diag=0` turns the export off explicitly. `keepsnappy activation-link | flush-link | gc-link` print the same links for runners that are not this driver, and `keepsnappy farm open` writes the settings into `tokens.js` (`output.keepsnappyLinkArgs`) for Maestro flows. Maestro runs send no GC for now. A guard test in `apps/agent` fails on a hand-written activation link anywhere else in the repo.
|
|
40
|
+
|
|
41
|
+
## driver-log.json while the run goes
|
|
42
|
+
|
|
43
|
+
`<out>/driver-log.json` is rewritten atomically at every top-level step and iteration boundary, so a killed run still leaves a valid log. `status` is `running`, `done`, `terminated` or `error`; `lastStep` names the last step started and `steps` times every step (`ms: null` while one runs). On SIGTERM or SIGINT (the farm's step timeout) the driver flushes the log as `terminated` with the signal, captures the failure screen and source (at most 20 s), ends the session as failed (at most 10 s) and exits 143 or 130, within 45 s in all; a second signal exits at once. `keepsnappy farm run` counts a driver that exits non-zero as infrastructure.
|
package/dist/src/browserstack.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserstack.js","sourceRoot":"","sources":["../../src/browserstack.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"browserstack.js","sourceRoot":"","sources":["../../src/browserstack.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
CHANGED
|
File without changes
|
package/dist/src/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { END_GC_DEFAULT, RUN_DEFAULTS, acceptAlert, activationLink, flushLink, g
|
|
|
3
3
|
export { defineJourney, type JourneyContext, type JourneyFn, type JourneyModule } from './journey.js';
|
|
4
4
|
export { ANDROID, IOS, PLATFORMS, platformOf, type Platform, type PlatformName } from './platform.js';
|
|
5
5
|
export { androidLocators, childOf, describeSelector, id, idText, locator, text, toSelector, type Selector, type SelectorLike } from './selectors.js';
|
|
6
|
-
export { FLUSH_WAIT_MS, HOST_CLOCK_TRIPS, Session, sendMarkers, type ActionGc, type ClockTrip, type Condition, type Marker } from './session.js';
|
|
6
|
+
export { FLUSH_END_RUN_FAILED, FLUSH_ERROR, FLUSH_OFF, FLUSH_NOT_ACKNOWLEDGED, FLUSH_RESEND_MS, FLUSH_UNREADABLE, FLUSH_WAIT_MS, type FlushEvidence, HOST_CLOCK_TRIPS, Session, sendMarkers, type ActionGc, type ClockTrip, type Condition, type Marker } from './session.js';
|
|
7
7
|
export { loadElements, parseTokensJs, plan, type PlannedRun } from './tokens.js';
|
|
8
8
|
export { runDriver, DRIVER_OPTIONS, type IterationRecord, type RunDeps } from './run.js';
|
|
9
9
|
export { loadJourneyModule, main } from './load.js';
|
package/dist/src/index.js
CHANGED
|
@@ -3,7 +3,7 @@ export { END_GC_DEFAULT, RUN_DEFAULTS, acceptAlert, activationLink, flushLink, g
|
|
|
3
3
|
export { defineJourney } from './journey.js';
|
|
4
4
|
export { ANDROID, IOS, PLATFORMS, platformOf } from './platform.js';
|
|
5
5
|
export { androidLocators, childOf, describeSelector, id, idText, locator, text, toSelector } from './selectors.js';
|
|
6
|
-
export { FLUSH_WAIT_MS, HOST_CLOCK_TRIPS, Session, sendMarkers } from './session.js';
|
|
6
|
+
export { FLUSH_END_RUN_FAILED, FLUSH_ERROR, FLUSH_OFF, FLUSH_NOT_ACKNOWLEDGED, FLUSH_RESEND_MS, FLUSH_UNREADABLE, FLUSH_WAIT_MS, HOST_CLOCK_TRIPS, Session, sendMarkers } from './session.js';
|
|
7
7
|
export { loadElements, parseTokensJs, plan } from './tokens.js';
|
|
8
8
|
export { runDriver, DRIVER_OPTIONS } from './run.js';
|
|
9
9
|
export { loadJourneyModule, main } from './load.js';
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAmD,MAAM,gBAAgB,CAAC;AAC7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AAC5J,OAAO,EAAE,aAAa,EAA2D,MAAM,cAAc,CAAC;AACtG,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,EAAoC,MAAM,eAAe,CAAC;AACtG,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAoC,MAAM,gBAAgB,CAAC;AACrJ,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAmD,MAAM,gBAAgB,CAAC;AAC7G,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,YAAY,CAAC;AAC5J,OAAO,EAAE,aAAa,EAA2D,MAAM,cAAc,CAAC;AACtG,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,EAAoC,MAAM,eAAe,CAAC;AACtG,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAoC,MAAM,gBAAgB,CAAC;AACrJ,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,SAAS,EAAE,sBAAsB,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAsB,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAA8D,MAAM,cAAc,CAAC;AAC9Q,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,IAAI,EAAmB,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAsC,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/src/links.d.ts
CHANGED
|
@@ -19,9 +19,12 @@ export declare function parseSdkArgs(args: string): Array<[string, string]>;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function linkArgs(args?: string): string;
|
|
21
21
|
export declare const activationLink: (scheme: string, token: string, args?: string) => string;
|
|
22
|
-
|
|
22
|
+
/** `ack` names this flush link; the SDK echoes it at the end of its answer's detail. */
|
|
23
|
+
export declare const flushLink: (scheme: string, ack?: string) => string;
|
|
23
24
|
/** Command n (a GC); the SDK takes it as a link on both platforms, and Android drivers send the same command as a broadcast. */
|
|
24
25
|
export declare const gcLink: (scheme: string, n: number) => string;
|
|
26
|
+
/** Command n again, `memread`: the end GC's memory read, sent with the GC's own n after the GC's answer. */
|
|
27
|
+
export declare const memReadLink: (scheme: string, n: number) => string;
|
|
25
28
|
/** Taps the button of a system alert if one shows within `waitMs` ("Open in ...?" and any permission prompt). Returns the label tapped, or null. */
|
|
26
29
|
export declare function acceptAlert(driver: Driver, labels: readonly string[], waitMs: number): Promise<string | null>;
|
|
27
30
|
export interface LinkState {
|
package/dist/src/links.js
CHANGED
|
@@ -7,7 +7,7 @@ export const ALERT_POLL_MS = 250;
|
|
|
7
7
|
export const RUN_DEFAULTS = { ttl: 3600, profile: 1, diag: 1 };
|
|
8
8
|
export const END_GC_DEFAULT = true;
|
|
9
9
|
// The SDK's link route under the app's own URL scheme (e.g. `myapp://`).
|
|
10
|
-
const route = (scheme) => `${scheme}devtools/
|
|
10
|
+
const route = (scheme) => `${scheme}devtools/keepsnappy`;
|
|
11
11
|
/** `k=v&k2=v2` into pairs; an empty string gives none. */
|
|
12
12
|
export function parseSdkArgs(args) {
|
|
13
13
|
return args
|
|
@@ -30,9 +30,12 @@ export function linkArgs(args = '') {
|
|
|
30
30
|
return [...fields].map(([k, v]) => `${k}=${v}`).join('&');
|
|
31
31
|
}
|
|
32
32
|
export const activationLink = (scheme, token, args = '') => `${route(scheme)}?activate=1&${linkArgs(args)}&runToken=${token}`;
|
|
33
|
-
|
|
33
|
+
/** `ack` names this flush link; the SDK echoes it at the end of its answer's detail. */
|
|
34
|
+
export const flushLink = (scheme, ack) => `${route(scheme)}?flush=1&activate=0${ack === undefined ? '' : `&ack=${ack}`}`;
|
|
34
35
|
/** Command n (a GC); the SDK takes it as a link on both platforms, and Android drivers send the same command as a broadcast. */
|
|
35
36
|
export const gcLink = (scheme, n) => `${route(scheme)}?cmd=gc&n=${n}`;
|
|
37
|
+
/** Command n again, `memread`: the end GC's memory read, sent with the GC's own n after the GC's answer. */
|
|
38
|
+
export const memReadLink = (scheme, n) => `${route(scheme)}?cmd=memread&n=${n}`;
|
|
36
39
|
/** Taps the button of a system alert if one shows within `waitMs` ("Open in ...?" and any permission prompt). Returns the label tapped, or null. */
|
|
37
40
|
export async function acceptAlert(driver, labels, waitMs) {
|
|
38
41
|
const deadline = driver.now() + waitMs;
|
package/dist/src/links.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/links.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAW,CAAC;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC,yEAAyE;AACzE,MAAM,KAAK,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/links.ts"],"names":[],"mappings":"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"}
|
package/dist/src/platform.d.ts
CHANGED
|
@@ -21,12 +21,13 @@ export interface Platform {
|
|
|
21
21
|
/** Accepts a system prompt if one shows within `waitMs`; returns what it accepted, or null. */
|
|
22
22
|
acceptAlert(driver: Driver, labels: readonly string[], waitMs: number): Promise<string | null>;
|
|
23
23
|
/**
|
|
24
|
-
* `
|
|
24
|
+
* `keepsnappy.flushed`: the lookup tried on every poll, which attribute holds the status, and a heavier lookup tried now and
|
|
25
25
|
* then when the cheap one misses (it needs `setting` on while it runs).
|
|
26
26
|
*/
|
|
27
27
|
readonly flush: {
|
|
28
28
|
lookup: Locator;
|
|
29
29
|
statusAttribute: string;
|
|
30
|
+
detailAttribute: string;
|
|
30
31
|
fallback?: {
|
|
31
32
|
lookup: Locator;
|
|
32
33
|
setting: string;
|
|
@@ -53,11 +54,19 @@ export interface Platform {
|
|
|
53
54
|
* Returns the SDK's answer (`gc:<n> ok` or `gc:<n> unavailable`), or null when no answer came (an SDK without the command).
|
|
54
55
|
*/
|
|
55
56
|
gcCommand(driver: Driver, n: number, scheme: string, state: LinkState): Promise<string | null>;
|
|
57
|
+
/**
|
|
58
|
+
* The end GC's manual memory read, asked for after the GC's answer with the GC's own n: the SDK takes one sample at once and
|
|
59
|
+
* answers `memread:<n> ok` (or `unavailable`). Returns the answer, or null when none came (an SDK without the command).
|
|
60
|
+
*/
|
|
61
|
+
memReadCommand(driver: Driver, n: number, scheme: string, state: LinkState): Promise<string | null>;
|
|
56
62
|
}
|
|
57
63
|
export declare const GC_ANSWER_WAIT_MS = 10000;
|
|
64
|
+
export declare const MEMREAD_ANSWER_WAIT_MS = 3000;
|
|
65
|
+
type Command = 'gc' | 'memread';
|
|
58
66
|
/** The answer for command n out of `am broadcast` output (`Broadcast completed: result=-1, data="gc:3 ok"`). */
|
|
59
|
-
export declare function parseBroadcastAnswer(out: unknown, n: number): string | null;
|
|
67
|
+
export declare function parseBroadcastAnswer(out: unknown, n: number, cmd?: Command): string | null;
|
|
60
68
|
export declare const IOS: Platform;
|
|
61
69
|
export declare const ANDROID: Platform;
|
|
62
70
|
export declare const PLATFORMS: Record<PlatformName, Platform>;
|
|
63
71
|
export declare function platformOf(name: string): Platform;
|
|
72
|
+
export {};
|
package/dist/src/platform.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { ALERT_POLL_MS, acceptAlert as acceptIosAlert, gcLink, openLink as openIosLink } from './links.js';
|
|
1
|
+
import { ALERT_POLL_MS, acceptAlert as acceptIosAlert, gcLink, memReadLink, openLink as openIosLink } from './links.js';
|
|
2
2
|
import { androidAnyOfIds, androidLocators, id, locator } from './selectors.js';
|
|
3
3
|
import { Screen, parseAndroidSource } from './snapshot.js';
|
|
4
4
|
import { WdError } from './webdriver.js';
|
|
5
5
|
// The split of `model-os` is BrowserStack's: the last dash starts the OS version.
|
|
6
6
|
const modelOf = (device) => device.replace(/-[^-]*$/, '');
|
|
7
7
|
const versionOf = (device) => device.replace(/^.*-/, '');
|
|
8
|
-
const FLUSH_ID = '
|
|
9
|
-
const ACK_ID = '
|
|
8
|
+
const FLUSH_ID = 'keepsnappy.flushed';
|
|
9
|
+
const ACK_ID = 'keepsnappy.ack';
|
|
10
10
|
// Only ends the wait for an iOS answer that never comes (an SDK without the command); no window edge depends on it.
|
|
11
11
|
export const GC_ANSWER_WAIT_MS = 10_000;
|
|
12
12
|
const GC_POLL_MS = 100;
|
|
13
|
+
// The read is one native call answered after a JS tick; the bound only ends the wait for an SDK that does not know the command.
|
|
14
|
+
export const MEMREAD_ANSWER_WAIT_MS = 3000;
|
|
13
15
|
/** The answer for command n out of `am broadcast` output (`Broadcast completed: result=-1, data="gc:3 ok"`). */
|
|
14
|
-
export function parseBroadcastAnswer(out, n) {
|
|
16
|
+
export function parseBroadcastAnswer(out, n, cmd = 'gc') {
|
|
15
17
|
const data = /data="([^"]*)"/.exec(String(out ?? ''))?.[1];
|
|
16
|
-
return data !== undefined && data.startsWith(
|
|
18
|
+
return data !== undefined && data.startsWith(`${cmd}:${n} `) ? data : null;
|
|
17
19
|
}
|
|
18
|
-
// A command waits for the app to go idle by default;
|
|
20
|
+
// A command waits for the app to go idle by default; KeepSnappy must not change the app's pace (docs/plans/61-android-support.md 1.2).
|
|
19
21
|
const NO_WAIT_MS = 0;
|
|
20
22
|
// Appium's own session-idle limit, the same on both platforms.
|
|
21
23
|
const NEW_COMMAND_TIMEOUT_S = 300;
|
|
@@ -38,30 +40,32 @@ export const IOS = {
|
|
|
38
40
|
appArg: (bundleId) => ({ bundleId }),
|
|
39
41
|
openLink: (driver, url, state) => openIosLink(driver, url, state),
|
|
40
42
|
acceptAlert: (driver, labels, waitMs) => acceptIosAlert(driver, labels, waitMs),
|
|
41
|
-
flush: { lookup: { using: 'accessibility id', value: FLUSH_ID }, statusAttribute: 'label' },
|
|
43
|
+
flush: { lookup: { using: 'accessibility id', value: FLUSH_ID }, statusAttribute: 'label', detailAttribute: 'value' },
|
|
42
44
|
uploadFields: { ios_keychain_support: 'true' },
|
|
43
|
-
// The link, then the `
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const want = `type == "XCUIElementTypeStaticText" AND name == "${ACK_ID}" AND label BEGINSWITH "gc:${n} "`;
|
|
47
|
-
const deadline = driver.now() + GC_ANSWER_WAIT_MS;
|
|
48
|
-
for (;;) {
|
|
49
|
-
const el = await driver.find('-ios predicate string', want);
|
|
50
|
-
// The predicate already matched `gc:<n> `; an unreadable label is taken as ok and logged, so a run that relied on it can be found.
|
|
51
|
-
if (el)
|
|
52
|
-
return driver
|
|
53
|
-
.cmd('GET', `/element/${el}/attribute/label`)
|
|
54
|
-
.then(String)
|
|
55
|
-
.catch(() => {
|
|
56
|
-
driver.log.push({ ...driver.context, cmd: 'gc-ack-label', t: driver.now(), ms: 0, status: 1 });
|
|
57
|
-
return `gc:${n} ok`;
|
|
58
|
-
});
|
|
59
|
-
if (driver.now() > deadline)
|
|
60
|
-
return null;
|
|
61
|
-
await driver.sleep(GC_POLL_MS);
|
|
62
|
-
}
|
|
63
|
-
},
|
|
45
|
+
// The link, then the `keepsnappy.ack` element. The trailing space keeps `gc:1` from matching the answer to 10.
|
|
46
|
+
gcCommand: (driver, n, scheme, state) => iosCommand(driver, gcLink(scheme, n), 'gc', n, state, GC_ANSWER_WAIT_MS),
|
|
47
|
+
memReadCommand: (driver, n, scheme, state) => iosCommand(driver, memReadLink(scheme, n), 'memread', n, state, MEMREAD_ANSWER_WAIT_MS),
|
|
64
48
|
};
|
|
49
|
+
async function iosCommand(driver, link, cmd, n, state, waitMs) {
|
|
50
|
+
await openIosLink(driver, link, state);
|
|
51
|
+
const want = `type == "XCUIElementTypeStaticText" AND name == "${ACK_ID}" AND label BEGINSWITH "${cmd}:${n} "`;
|
|
52
|
+
const deadline = driver.now() + waitMs;
|
|
53
|
+
for (;;) {
|
|
54
|
+
const el = await driver.find('-ios predicate string', want);
|
|
55
|
+
// The predicate already matched `<cmd>:<n> `; an unreadable label is taken as ok and logged, so a run that relied on it can be found.
|
|
56
|
+
if (el)
|
|
57
|
+
return driver
|
|
58
|
+
.cmd('GET', `/element/${el}/attribute/label`)
|
|
59
|
+
.then(String)
|
|
60
|
+
.catch(() => {
|
|
61
|
+
driver.log.push({ ...driver.context, cmd: `${cmd}-ack-label`, t: driver.now(), ms: 0, status: 1 });
|
|
62
|
+
return `${cmd}:${n} ok`;
|
|
63
|
+
});
|
|
64
|
+
if (driver.now() > deadline)
|
|
65
|
+
return null;
|
|
66
|
+
await driver.sleep(GC_POLL_MS);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
65
69
|
export const ANDROID = {
|
|
66
70
|
name: 'android',
|
|
67
71
|
// The phone of the TapIn farm workflow (docs/plans/61-android-support.md 1.2).
|
|
@@ -106,6 +110,7 @@ export const ANDROID = {
|
|
|
106
110
|
flush: {
|
|
107
111
|
lookup: { using: '-android uiautomator', value: `new UiSelector().description("${FLUSH_ID}")` },
|
|
108
112
|
statusAttribute: 'text',
|
|
113
|
+
detailAttribute: 'hint',
|
|
109
114
|
fallback: { lookup: { using: 'xpath', value: `//*[@content-desc="${FLUSH_ID}"]` }, setting: 'allowInvisibleElements' },
|
|
110
115
|
},
|
|
111
116
|
async readScreen(driver) {
|
|
@@ -125,17 +130,19 @@ export const ANDROID = {
|
|
|
125
130
|
anyOfIds: androidAnyOfIds,
|
|
126
131
|
uploadFields: {},
|
|
127
132
|
// A broadcast pauses no activity (a link does). `am broadcast` returns once the SDK finished the receiver, so its output is the answer.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
action: `${driver.bundleId}.perflab.COMMAND`,
|
|
131
|
-
package: driver.bundleId,
|
|
132
|
-
extras: [['s', 'cmd', 'gc'], ['i', 'n', String(n)]],
|
|
133
|
-
// FLAG_RECEIVER_FOREGROUND: the foreground broadcast queue, not the background one that other apps' broadcasts can delay.
|
|
134
|
-
flags: '0x10000000',
|
|
135
|
-
});
|
|
136
|
-
return parseBroadcastAnswer(out, n);
|
|
137
|
-
},
|
|
133
|
+
gcCommand: (driver, n) => androidCommand(driver, 'gc', n),
|
|
134
|
+
memReadCommand: (driver, n) => androidCommand(driver, 'memread', n),
|
|
138
135
|
};
|
|
136
|
+
async function androidCommand(driver, cmd, n) {
|
|
137
|
+
const out = await driver.execute('mobile: broadcast', {
|
|
138
|
+
action: `${driver.bundleId}.keepsnappy.COMMAND`,
|
|
139
|
+
package: driver.bundleId,
|
|
140
|
+
extras: [['s', 'cmd', cmd], ['i', 'n', String(n)]],
|
|
141
|
+
// FLAG_RECEIVER_FOREGROUND: the foreground broadcast queue, not the background one that other apps' broadcasts can delay.
|
|
142
|
+
flags: '0x10000000',
|
|
143
|
+
});
|
|
144
|
+
return parseBroadcastAnswer(out, n, cmd);
|
|
145
|
+
}
|
|
139
146
|
export const PLATFORMS = { ios: IOS, android: ANDROID };
|
|
140
147
|
export function platformOf(name) {
|
|
141
148
|
if (!Object.hasOwn(PLATFORMS, name))
|
package/dist/src/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,EAAE,QAAQ,IAAI,WAAW,EAAkB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":"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"}
|
package/dist/src/run.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { JourneyModule } from './journey.js';
|
|
2
|
+
import { type FlushEvidence } from './session.js';
|
|
2
3
|
import { type FetchLike } from './webdriver.js';
|
|
3
4
|
export interface IterationRecord {
|
|
4
5
|
journey: string;
|
|
@@ -11,6 +12,7 @@ export interface IterationRecord {
|
|
|
11
12
|
ms: number;
|
|
12
13
|
};
|
|
13
14
|
flushed?: string | null;
|
|
15
|
+
flush?: FlushEvidence | null;
|
|
14
16
|
t_start?: number;
|
|
15
17
|
begin_ms?: number;
|
|
16
18
|
journey_ms?: number;
|
|
@@ -24,9 +26,28 @@ export interface RunDeps {
|
|
|
24
26
|
sleep: (ms: number) => Promise<void>;
|
|
25
27
|
print: (line: string) => void;
|
|
26
28
|
error: (line: string) => void;
|
|
29
|
+
/** The signals and the exit; absent in a test that does not exercise them (no handler is installed then). */
|
|
30
|
+
process?: ProcessHooks;
|
|
31
|
+
/** How long a SIGTERM may spend before the process exits (the farm kills 2 minutes after its TERM). */
|
|
32
|
+
term?: Partial<TerminationBudget>;
|
|
27
33
|
}
|
|
34
|
+
export type TerminationSignal = 'SIGTERM' | 'SIGINT';
|
|
35
|
+
export interface ProcessHooks {
|
|
36
|
+
on(signal: TerminationSignal, handler: () => unknown): void;
|
|
37
|
+
off(signal: TerminationSignal, handler: () => unknown): void;
|
|
38
|
+
exit(code: number): void;
|
|
39
|
+
}
|
|
40
|
+
/** After a signal: the failure screen and source, the session end, and the hard deadline for all of it. */
|
|
41
|
+
export interface TerminationBudget {
|
|
42
|
+
captureMs: number;
|
|
43
|
+
endMs: number;
|
|
44
|
+
hardMs: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const TERMINATION_BUDGET: TerminationBudget;
|
|
47
|
+
export type DriverStatus = 'running' | 'done' | 'terminated' | 'error';
|
|
48
|
+
export declare const realProcessHooks: ProcessHooks;
|
|
28
49
|
export declare const realRunDeps: () => RunDeps;
|
|
29
|
-
/** The flags `
|
|
50
|
+
/** The flags `keepsnappy farm run` passes (docs/plans/54a section 4); a journey module adds its own through `options`. */
|
|
30
51
|
export declare const DRIVER_OPTIONS: {
|
|
31
52
|
readonly 'journey-module': {
|
|
32
53
|
readonly type: "string";
|
|
@@ -85,8 +106,12 @@ export declare function parseDriverArgs(argv: readonly string[], module: Journey
|
|
|
85
106
|
export declare function journeyModulePath(argv: readonly string[]): string | undefined;
|
|
86
107
|
/**
|
|
87
108
|
* One BrowserStack App Automate session that runs every iteration of the module's journeys, then a final flush, and
|
|
88
|
-
* writes <out>/driver-log.json and <out>/browserstack.<platform>.json in the shape `
|
|
109
|
+
* writes <out>/driver-log.json and <out>/browserstack.<platform>.json in the shape `keepsnappy farm close --bs-build`
|
|
89
110
|
* reads. Returns the exit code: 0, or 1 when the session or an iteration failed (the result files are written anyway).
|
|
111
|
+
*
|
|
112
|
+
* driver-log.json is rewritten (atomically) at every step and iteration boundary, `status` saying where the run is. A SIGTERM or
|
|
113
|
+
* SIGINT flushes it as `terminated` first, then captures the failure screen and ends the session within `TERMINATION_BUDGET`, and
|
|
114
|
+
* exits; a second signal exits at once.
|
|
90
115
|
*/
|
|
91
116
|
export declare function runDriver(argv: readonly string[], module: JourneyModule, deps?: RunDeps): Promise<number>;
|
|
92
117
|
export {};
|