@delacour/warden-e2e 0.14.0 → 0.15.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/{chunk-zk3wxa70.mjs → chunk-e3cry5br.mjs} +287 -37
- package/index.mjs +32 -3
- package/package.json +2 -2
- package/preload.mjs +304 -30
- package/types/core/src/affected/affected.schema.d.ts +5 -0
- package/types/core/src/builds/builds.defaults.d.ts +8 -0
- package/types/core/src/builds/config.schema.d.ts +9 -0
- package/types/core/src/builds/define-config.d.ts +9 -1
- package/types/core/src/conditions/conditions.config.d.ts +6 -1
- package/types/core/src/conditions/conditions.types.d.ts +21 -0
- package/types/core/src/conditions/inject-state.d.ts +3 -2
- package/types/e2e/src/a11y/a11y-target.d.ts +2 -0
- package/types/e2e/src/conditions/condition-events.d.ts +6 -1
- package/types/e2e/src/conditions/device-conditions.d.ts +8 -2
- package/types/e2e/src/device.d.ts +10 -2
- package/types/e2e/src/driver/android/android-settings.d.ts +9 -2
- package/types/e2e/src/driver/ax-wedge.d.ts +38 -0
- package/types/e2e/src/driver/bridge-stall.d.ts +4 -0
- package/types/e2e/src/driver/driver.types.d.ts +30 -1
- package/types/e2e/src/driver/ios/inject.d.ts +17 -2
- package/types/e2e/src/driver/ios/ios-driver.d.ts +7 -2
- package/types/e2e/src/driver/ios/ios-keyboard.d.ts +39 -0
- package/types/e2e/src/driver/ios/simd-protocol.d.ts +99 -0
- package/types/e2e/src/driver/keyboard-state.d.ts +9 -0
- package/types/e2e/src/driver/physical-conditions.d.ts +1 -1
- package/types/e2e/src/driver/read-deadline.d.ts +4 -0
- package/types/e2e/src/driver/settle.d.ts +3 -1
- package/types/e2e/src/expect/a11y-matchers.d.ts +7 -0
- package/types/e2e/src/index.d.ts +2 -1
- package/types/e2e/src/screen/actions.d.ts +7 -0
- package/types/e2e/src/screen/context.d.ts +3 -1
- package/types/e2e/src/screen/keyboard-cover.d.ts +26 -0
- package/types/e2e/src/screen/locator.d.ts +16 -7
- package/types/e2e/src/session.d.ts +6 -0
package/preload.mjs
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
isInteractiveRole,
|
|
31
31
|
resolveRole,
|
|
32
32
|
indexSnapshot,
|
|
33
|
+
keyboardVisible,
|
|
33
34
|
testIdQuery,
|
|
34
35
|
textQuery,
|
|
35
36
|
roleQuery,
|
|
@@ -61,6 +62,10 @@ import {
|
|
|
61
62
|
createSimdClient,
|
|
62
63
|
spawnSimd,
|
|
63
64
|
connectSimd,
|
|
65
|
+
KEYBOARD_MODES,
|
|
66
|
+
DEFAULT_KEYBOARD_MODE,
|
|
67
|
+
IME_STASH_ENABLED,
|
|
68
|
+
IME_STASH_DEFAULT,
|
|
64
69
|
CAMERA_FACINGS,
|
|
65
70
|
CONDITION_AREAS,
|
|
66
71
|
resolveNetwork,
|
|
@@ -114,7 +119,7 @@ import {
|
|
|
114
119
|
onlyWasSeen,
|
|
115
120
|
WORKSPACE_VERSION,
|
|
116
121
|
WARDEN_E2E_VERSION2
|
|
117
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-e3cry5br.mjs";
|
|
118
123
|
|
|
119
124
|
// ../../packages/e2e/src/preload.ts
|
|
120
125
|
import { afterAll, setDefaultTimeout } from "bun:test";
|
|
@@ -1376,6 +1381,8 @@ function physicalConditionOps(device) {
|
|
|
1376
1381
|
locale: () => refuse("locale"),
|
|
1377
1382
|
a11y: () => refuse("a11y"),
|
|
1378
1383
|
battery: () => refuse("battery"),
|
|
1384
|
+
keyboard: () => refuse("keyboard"),
|
|
1385
|
+
keyboardState: () => refuse("keyboardState"),
|
|
1379
1386
|
memoryWarning: () => refuse("memoryWarning"),
|
|
1380
1387
|
push: () => refuse("push"),
|
|
1381
1388
|
camera: () => refuse("camera")
|
|
@@ -4079,6 +4086,75 @@ function batteryOp(c) {
|
|
|
4079
4086
|
};
|
|
4080
4087
|
};
|
|
4081
4088
|
}
|
|
4089
|
+
var nullable = (value) => value.trim() === "null" ? "" : value.trim();
|
|
4090
|
+
async function readIme(c) {
|
|
4091
|
+
const enabled = await c.shell(settingGetArgv("secure", "enabled_input_methods"));
|
|
4092
|
+
const current = await c.shell(settingGetArgv("secure", "default_input_method"));
|
|
4093
|
+
return { enabled: nullable(enabled.stdout), default: nullable(current.stdout) };
|
|
4094
|
+
}
|
|
4095
|
+
async function readImeStash(c) {
|
|
4096
|
+
const enabled = await c.shell(settingGetArgv("global", IME_STASH_ENABLED));
|
|
4097
|
+
const current = await c.shell(settingGetArgv("global", IME_STASH_DEFAULT));
|
|
4098
|
+
const state = { enabled: nullable(enabled.stdout), default: nullable(current.stdout) };
|
|
4099
|
+
return state.enabled === "" ? undefined : state;
|
|
4100
|
+
}
|
|
4101
|
+
async function readKeyboardMode(c) {
|
|
4102
|
+
return (await readIme(c)).enabled === "" ? "hardware" : "software";
|
|
4103
|
+
}
|
|
4104
|
+
function imeVisibleIn(dump) {
|
|
4105
|
+
return /\bisVisible=true\b/.test(dump);
|
|
4106
|
+
}
|
|
4107
|
+
async function readKeyboardVisible(c) {
|
|
4108
|
+
const read = await c.shell(["dumpsys", "window", "InputMethod"]);
|
|
4109
|
+
return read.ok && imeVisibleIn(read.stdout);
|
|
4110
|
+
}
|
|
4111
|
+
async function restoreImes(c) {
|
|
4112
|
+
const stash = await readImeStash(c);
|
|
4113
|
+
if (stash !== undefined) {
|
|
4114
|
+
const steps = [
|
|
4115
|
+
["settings", "put", "secure", "enabled_input_methods", stash.enabled],
|
|
4116
|
+
...stash.default === "" ? [] : [["settings", "put", "secure", "default_input_method", stash.default]],
|
|
4117
|
+
["settings", "delete", "global", IME_STASH_ENABLED],
|
|
4118
|
+
["settings", "delete", "global", IME_STASH_DEFAULT]
|
|
4119
|
+
];
|
|
4120
|
+
for (const argv of steps) {
|
|
4121
|
+
const done = await c.must(argv);
|
|
4122
|
+
if (!done.success)
|
|
4123
|
+
return done;
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
return { success: true, data: { mode: "software" } };
|
|
4127
|
+
}
|
|
4128
|
+
async function hideImes(c, current) {
|
|
4129
|
+
const listed = await c.shell(["ime", "list", "-s"]);
|
|
4130
|
+
const ids = listed.stdout.split(`
|
|
4131
|
+
`).map((line) => line.trim()).filter((line) => line.includes("/"));
|
|
4132
|
+
const steps = [
|
|
4133
|
+
["settings", "put", "global", IME_STASH_ENABLED, current.enabled],
|
|
4134
|
+
...current.default === "" ? [] : [["settings", "put", "global", IME_STASH_DEFAULT, current.default]],
|
|
4135
|
+
...ids.map((id) => ["ime", "disable", id])
|
|
4136
|
+
];
|
|
4137
|
+
for (const argv of steps) {
|
|
4138
|
+
const done = await c.must(argv);
|
|
4139
|
+
if (!done.success)
|
|
4140
|
+
return done;
|
|
4141
|
+
}
|
|
4142
|
+
if ((await readIme(c)).enabled !== "") {
|
|
4143
|
+
return driverErr("E_IO", "an input method is still enabled after ime disable", { detail: { serial: c.serial } });
|
|
4144
|
+
}
|
|
4145
|
+
return { success: true, data: { mode: "hardware", previousIme: current } };
|
|
4146
|
+
}
|
|
4147
|
+
function keyboardOp(c) {
|
|
4148
|
+
return async (mode) => {
|
|
4149
|
+
if (mode === "software")
|
|
4150
|
+
return restoreImes(c);
|
|
4151
|
+
const current = await readIme(c);
|
|
4152
|
+
if (current.enabled !== "")
|
|
4153
|
+
return hideImes(c, current);
|
|
4154
|
+
const previous = await readImeStash(c);
|
|
4155
|
+
return { success: true, data: { mode, ...previous === undefined ? {} : { previousIme: previous } } };
|
|
4156
|
+
};
|
|
4157
|
+
}
|
|
4082
4158
|
function memoryWarningOp(c) {
|
|
4083
4159
|
return async (opts) => {
|
|
4084
4160
|
const app = c.packageOf(opts?.bundleId, "memoryWarning");
|
|
@@ -4153,6 +4229,12 @@ function createAndroidSettings(deps) {
|
|
|
4153
4229
|
locale: localeOp(ctx),
|
|
4154
4230
|
a11y: a11yOp(ctx),
|
|
4155
4231
|
battery: batteryOp(ctx),
|
|
4232
|
+
keyboard: keyboardOp(ctx),
|
|
4233
|
+
keyboardMode: () => readKeyboardMode(ctx),
|
|
4234
|
+
keyboardVisible: () => readKeyboardVisible(ctx),
|
|
4235
|
+
async keyboardState() {
|
|
4236
|
+
return { success: true, data: { mode: await readKeyboardMode(ctx), visible: await readKeyboardVisible(ctx) } };
|
|
4237
|
+
},
|
|
4156
4238
|
memoryWarning: memoryWarningOp(ctx),
|
|
4157
4239
|
async push() {
|
|
4158
4240
|
return driverErr("E_UNSUPPORTED", "push notifications through the shell are iOS only (`simctl push`); Android needs FCM");
|
|
@@ -5840,7 +5922,12 @@ function buildDriver(options, session, baseScreen, clock, execBinary, facts) {
|
|
|
5840
5922
|
});
|
|
5841
5923
|
return { success: true, data: { ...applied.data, condition: op } };
|
|
5842
5924
|
};
|
|
5843
|
-
const {
|
|
5925
|
+
const {
|
|
5926
|
+
talkback,
|
|
5927
|
+
keyboardMode: _mode,
|
|
5928
|
+
keyboardVisible: _visible,
|
|
5929
|
+
...settings
|
|
5930
|
+
} = createAndroidSettings({
|
|
5844
5931
|
session,
|
|
5845
5932
|
serial,
|
|
5846
5933
|
...options.appPackage ? { appPackage: options.appPackage } : {},
|
|
@@ -5958,6 +6045,11 @@ function buildDriver(options, session, baseScreen, clock, execBinary, facts) {
|
|
|
5958
6045
|
...options.cameraHost ?? createAndroidCameraHost({ serial, exec })
|
|
5959
6046
|
}),
|
|
5960
6047
|
...facts.physical ? physicalConditionOps(`physical Android device ${serial}`) : {},
|
|
6048
|
+
keyboardState: settings.keyboardState,
|
|
6049
|
+
async dismissKeyboard() {
|
|
6050
|
+
const pressed = await pressButton("back");
|
|
6051
|
+
return pressed.success ? { success: true, data: { via: "back" } } : pressed;
|
|
6052
|
+
},
|
|
5961
6053
|
biometrics,
|
|
5962
6054
|
app: createAppCommands({
|
|
5963
6055
|
session,
|
|
@@ -6036,6 +6128,17 @@ function writeLaunchSettings(path, settings) {
|
|
|
6036
6128
|
}
|
|
6037
6129
|
}
|
|
6038
6130
|
|
|
6131
|
+
// ../../packages/e2e/src/driver/read-deadline.ts
|
|
6132
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
6133
|
+
var deadlines = new AsyncLocalStorage;
|
|
6134
|
+
function withReadDeadline(remaining, fn) {
|
|
6135
|
+
return deadlines.run({ remaining }, fn);
|
|
6136
|
+
}
|
|
6137
|
+
function readDeadlineRemaining() {
|
|
6138
|
+
const deadline = deadlines.getStore();
|
|
6139
|
+
return deadline === undefined ? undefined : Math.max(0, deadline.remaining());
|
|
6140
|
+
}
|
|
6141
|
+
|
|
6039
6142
|
// ../../packages/e2e/src/driver/ios/inject.ts
|
|
6040
6143
|
import { mkdirSync as mkdirSync7, readFileSync as readFileSync5, renameSync as renameSync6, rmSync as rmSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
6041
6144
|
import { dirname as dirname3, join as join10, resolve } from "path";
|
|
@@ -6056,12 +6159,17 @@ function encodeInjectState(state) {
|
|
|
6056
6159
|
clockOffsetMs: Math.trunc(state.clockOffsetMs ?? 0),
|
|
6057
6160
|
...state.clockFrozenMs === undefined ? {} : { clockFrozenMs: Math.trunc(state.clockFrozenMs) },
|
|
6058
6161
|
...state.a11yRead ? { a11yRead: true } : {},
|
|
6059
|
-
...state.camera === undefined ? {} : { camera: state.camera }
|
|
6162
|
+
...state.camera === undefined ? {} : { camera: state.camera },
|
|
6163
|
+
...state.keyboard === undefined ? {} : { keyboard: state.keyboard },
|
|
6164
|
+
...state.dismissKeyboard ? { dismissKeyboard: true } : {}
|
|
6060
6165
|
});
|
|
6061
6166
|
}
|
|
6062
6167
|
function isRecord3(value) {
|
|
6063
6168
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6064
6169
|
}
|
|
6170
|
+
function parseKeyboard(value) {
|
|
6171
|
+
return KEYBOARD_MODES.find((mode) => mode === value);
|
|
6172
|
+
}
|
|
6065
6173
|
function parseFeed(value) {
|
|
6066
6174
|
if (!isRecord3(value) || typeof value.path !== "string")
|
|
6067
6175
|
return;
|
|
@@ -6089,7 +6197,8 @@ function parseInjectState(text) {
|
|
|
6089
6197
|
clockOffsetMs: typeof data.clockOffsetMs === "number" ? data.clockOffsetMs : 0,
|
|
6090
6198
|
...typeof data.clockFrozenMs === "number" ? { clockFrozenMs: data.clockFrozenMs } : {},
|
|
6091
6199
|
...data.a11yRead === true ? { a11yRead: true } : {},
|
|
6092
|
-
..."camera" in data ? { camera: parseCamera(data.camera) } : {}
|
|
6200
|
+
..."camera" in data ? { camera: parseCamera(data.camera) } : {},
|
|
6201
|
+
...parseKeyboard(data.keyboard) ? { keyboard: parseKeyboard(data.keyboard) } : {}
|
|
6093
6202
|
};
|
|
6094
6203
|
} catch {
|
|
6095
6204
|
return;
|
|
@@ -6123,11 +6232,12 @@ function injectLaunchEnv(input) {
|
|
|
6123
6232
|
...input.clockOffsetMs ? { WARDEN_CLOCK_OFFSET_MS: String(Math.trunc(input.clockOffsetMs)) } : {},
|
|
6124
6233
|
...input.clockFrozenMs === undefined ? {} : { WARDEN_CLOCK_FROZEN_MS: String(Math.trunc(input.clockFrozenMs)) },
|
|
6125
6234
|
...input.camera ? { WARDEN_CAMERA: "1" } : {},
|
|
6235
|
+
...input.keyboard ? { WARDEN_KEYBOARD: input.keyboard } : {},
|
|
6126
6236
|
...input.debug ? { WARDEN_INJECT_DEBUG: "1" } : {}
|
|
6127
6237
|
};
|
|
6128
6238
|
}
|
|
6129
6239
|
function shouldInject(input) {
|
|
6130
|
-
return input.networkActive || input.clockActive || input.cameraActive === true || input.requested;
|
|
6240
|
+
return input.networkActive || input.clockActive || input.cameraActive === true || input.keyboardActive === true || input.requested;
|
|
6131
6241
|
}
|
|
6132
6242
|
function locateInjectDylib(input) {
|
|
6133
6243
|
const tried = [];
|
|
@@ -6212,7 +6322,13 @@ function createInjectChannel(input) {
|
|
|
6212
6322
|
current: readState,
|
|
6213
6323
|
write(next) {
|
|
6214
6324
|
fs.mkdir(dirname3(statePath));
|
|
6215
|
-
const
|
|
6325
|
+
const previous = readState();
|
|
6326
|
+
const keyboard = next.keyboard ?? previous.keyboard;
|
|
6327
|
+
const state = {
|
|
6328
|
+
...next,
|
|
6329
|
+
...keyboard === undefined ? {} : { keyboard },
|
|
6330
|
+
seq: Math.max(previous.seq + 1, Math.trunc(now()))
|
|
6331
|
+
};
|
|
6216
6332
|
fs.writeAtomic(statePath, encodeInjectState(state));
|
|
6217
6333
|
return state;
|
|
6218
6334
|
},
|
|
@@ -6229,9 +6345,14 @@ function createInjectChannel(input) {
|
|
|
6229
6345
|
}
|
|
6230
6346
|
},
|
|
6231
6347
|
reset() {
|
|
6348
|
+
const keyboard = readState().keyboard;
|
|
6232
6349
|
fs.remove(ackPath);
|
|
6233
6350
|
fs.remove(statePath);
|
|
6234
6351
|
fs.remove(injectEventsPath(statePath));
|
|
6352
|
+
if (keyboard !== undefined) {
|
|
6353
|
+
fs.mkdir(dirname3(statePath));
|
|
6354
|
+
fs.writeAtomic(statePath, encodeInjectState({ seq: 0, keyboard }));
|
|
6355
|
+
}
|
|
6235
6356
|
}
|
|
6236
6357
|
};
|
|
6237
6358
|
}
|
|
@@ -6792,8 +6913,14 @@ function defaultBuildCommand(platform, configuration, framework = "expo") {
|
|
|
6792
6913
|
if (platform === "ios") {
|
|
6793
6914
|
return `${IOS_NATIVE_PREPARE} && bunx expo run:ios ${configuration === "Release" ? "--configuration Release " : ""}${flags}`;
|
|
6794
6915
|
}
|
|
6795
|
-
return
|
|
6916
|
+
return androidGradleCommand(configuration, framework);
|
|
6917
|
+
}
|
|
6918
|
+
function androidGradleCommand(configuration, framework = "expo") {
|
|
6919
|
+
const gradle = `cd android && ./gradlew app:assemble${configuration} -PreactNativeArchitectures=${ANDROID_HOST_ABI}`;
|
|
6920
|
+
return framework === "react-native" ? gradle : `${ANDROID_NATIVE_PREPARE} && ${gradle}`;
|
|
6796
6921
|
}
|
|
6922
|
+
var ANDROID_NATIVE_PREPARE = "{ [ -f android/gradlew ] || bunx expo prebuild --platform android --no-install; }";
|
|
6923
|
+
var ANDROID_HOST_ABI = '"$([ "$(uname -m)" = arm64 ] && echo arm64-v8a || echo x86_64)"';
|
|
6797
6924
|
var DEFAULT_BUILD_COMMAND = {
|
|
6798
6925
|
ios: defaultBuildCommand("ios", "Debug"),
|
|
6799
6926
|
android: defaultBuildCommand("android", "Debug")
|
|
@@ -7370,6 +7497,63 @@ function createIosNativeAudit(o) {
|
|
|
7370
7497
|
};
|
|
7371
7498
|
}
|
|
7372
7499
|
|
|
7500
|
+
// ../../packages/e2e/src/driver/ios/ios-keyboard.ts
|
|
7501
|
+
var okVoid2 = { success: true, data: undefined };
|
|
7502
|
+
function createIosKeyboard(deps) {
|
|
7503
|
+
const { channel } = deps;
|
|
7504
|
+
let expectLoad = false;
|
|
7505
|
+
const mode = () => channel.current().keyboard ?? DEFAULT_KEYBOARD_MODE;
|
|
7506
|
+
return {
|
|
7507
|
+
mode,
|
|
7508
|
+
launchEnv() {
|
|
7509
|
+
const dylib = deps.dylib();
|
|
7510
|
+
if (!dylib.success)
|
|
7511
|
+
return;
|
|
7512
|
+
channel.reset();
|
|
7513
|
+
channel.write({});
|
|
7514
|
+
expectLoad = true;
|
|
7515
|
+
return injectLaunchEnv({
|
|
7516
|
+
dylib: dylib.data,
|
|
7517
|
+
statePath: channel.statePath,
|
|
7518
|
+
keyboard: mode(),
|
|
7519
|
+
...deps.debug ? { debug: true } : {}
|
|
7520
|
+
});
|
|
7521
|
+
},
|
|
7522
|
+
launchMode: () => ({ WARDEN_KEYBOARD: mode() }),
|
|
7523
|
+
async confirmLoaded() {
|
|
7524
|
+
if (!expectLoad)
|
|
7525
|
+
return okVoid2;
|
|
7526
|
+
expectLoad = false;
|
|
7527
|
+
if (await channel.acked(channel.current().seq, INJECT_LOAD_MS))
|
|
7528
|
+
return okVoid2;
|
|
7529
|
+
const error = driverError("E_INTERNAL", `the app did not load libwarden-inject.dylib within ${INJECT_LOAD_MS} ms: the keyboard mode would not reach it. Check the app is a simulator build, and run with WARDEN_E2E_DEBUG=1`, { detail: { statePath: channel.statePath } });
|
|
7530
|
+
return { success: false, error };
|
|
7531
|
+
},
|
|
7532
|
+
async dismiss() {
|
|
7533
|
+
if (!channel.attached())
|
|
7534
|
+
return { success: true, data: { attached: false } };
|
|
7535
|
+
const { seq: _seq, a11yRead: _read, ...rest } = channel.current();
|
|
7536
|
+
const state = channel.write({ ...rest, dismissKeyboard: true });
|
|
7537
|
+
if (await channel.acked(state.seq, INJECT_ACK_MS))
|
|
7538
|
+
return { success: true, data: { attached: true } };
|
|
7539
|
+
return driverErr("E_TIMEOUT", `the app did not acknowledge the keyboard dismissal within ${INJECT_ACK_MS} ms`, {
|
|
7540
|
+
detail: { statePath: channel.statePath }
|
|
7541
|
+
});
|
|
7542
|
+
},
|
|
7543
|
+
async keyboard(next) {
|
|
7544
|
+
const { seq: _seq, a11yRead: _read, ...rest } = channel.current();
|
|
7545
|
+
const state = channel.write({ ...rest, keyboard: next });
|
|
7546
|
+
if (!channel.attached())
|
|
7547
|
+
return { success: true, data: { mode: next, appliesOnLaunch: true } };
|
|
7548
|
+
if (await channel.acked(state.seq, INJECT_ACK_MS))
|
|
7549
|
+
return { success: true, data: { mode: next } };
|
|
7550
|
+
return driverErr("E_TIMEOUT", `the app did not acknowledge the keyboard mode within ${INJECT_ACK_MS} ms`, {
|
|
7551
|
+
detail: { statePath: channel.statePath }
|
|
7552
|
+
});
|
|
7553
|
+
}
|
|
7554
|
+
};
|
|
7555
|
+
}
|
|
7556
|
+
|
|
7373
7557
|
// ../../packages/e2e/src/driver/ios/ios-session.ts
|
|
7374
7558
|
var SHUTDOWN_TIMEOUT_MS = 500;
|
|
7375
7559
|
function swappableClient(initial, o) {
|
|
@@ -7779,6 +7963,9 @@ function optionalFields(node) {
|
|
|
7779
7963
|
fields.pid = node.pid;
|
|
7780
7964
|
return fields;
|
|
7781
7965
|
}
|
|
7966
|
+
function roleOf(node) {
|
|
7967
|
+
return node.role === "other" && node.identifier === "inputView" ? "keyboard" : node.role;
|
|
7968
|
+
}
|
|
7782
7969
|
function normalizeElements(wire, screen, prefix = "", depth = 0) {
|
|
7783
7970
|
const flat = [];
|
|
7784
7971
|
const elements = wire.map((node, index) => {
|
|
@@ -7786,7 +7973,7 @@ function normalizeElements(wire, screen, prefix = "", depth = 0) {
|
|
|
7786
7973
|
const element = {
|
|
7787
7974
|
...optionalFields(node),
|
|
7788
7975
|
id: node.id ?? path,
|
|
7789
|
-
role: node
|
|
7976
|
+
role: roleOf(node),
|
|
7790
7977
|
rawType: node.rawType,
|
|
7791
7978
|
frame: node.frame,
|
|
7792
7979
|
depth: node.depth ?? depth,
|
|
@@ -8459,7 +8646,7 @@ var SOCKET_RETRY_MS = 500;
|
|
|
8459
8646
|
function params(values) {
|
|
8460
8647
|
return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined));
|
|
8461
8648
|
}
|
|
8462
|
-
var
|
|
8649
|
+
var okVoid3 = { success: true, data: undefined };
|
|
8463
8650
|
function fail2(error) {
|
|
8464
8651
|
return { success: false, error };
|
|
8465
8652
|
}
|
|
@@ -8574,8 +8761,26 @@ function healthDetail(d) {
|
|
|
8574
8761
|
...d.ax.error !== undefined ? { axError: d.ax.error } : {},
|
|
8575
8762
|
...d.socket ? { socket: d.socket } : {},
|
|
8576
8763
|
...d.xcode ? { xcode: d.xcode } : {},
|
|
8577
|
-
...d.state ? { state: d.state } : {}
|
|
8578
|
-
|
|
8764
|
+
...d.state ? { state: d.state } : {},
|
|
8765
|
+
...d.axWedge ? { axWedge: toAxWedgeState(d.axWedge) } : {}
|
|
8766
|
+
};
|
|
8767
|
+
}
|
|
8768
|
+
var AX_WEDGE_RECOVER_MS = 75000;
|
|
8769
|
+
function toAxWedgeState(d) {
|
|
8770
|
+
const state = {
|
|
8771
|
+
restarts: d.restarts,
|
|
8772
|
+
maxRestarts: d.maxRestarts,
|
|
8773
|
+
recovering: d.recovering,
|
|
8774
|
+
...d.checked !== undefined ? { checked: d.checked } : {}
|
|
8775
|
+
};
|
|
8776
|
+
const last = d.last;
|
|
8777
|
+
if (last?.outcome === "restarted")
|
|
8778
|
+
state.last = { outcome: "restarted", agoMs: last.agoMs, ...last.ms !== undefined ? { ms: last.ms } : {} };
|
|
8779
|
+
else if (last?.outcome === "not-wedged")
|
|
8780
|
+
state.last = { outcome: "not-wedged", agoMs: last.agoMs };
|
|
8781
|
+
else if (last?.outcome === "failed")
|
|
8782
|
+
state.last = { outcome: "failed", agoMs: last.agoMs, error: last.error };
|
|
8783
|
+
return state;
|
|
8579
8784
|
}
|
|
8580
8785
|
|
|
8581
8786
|
class DriverFailure extends Error {
|
|
@@ -8598,14 +8803,15 @@ function decodeBase64(png) {
|
|
|
8598
8803
|
function predatesOp(error) {
|
|
8599
8804
|
return error.code === "E_UNSUPPORTED" || error.code === "E_BAD_REQUEST" && /unknown (input )?op/.test(error.message);
|
|
8600
8805
|
}
|
|
8601
|
-
async function launchWithInjection(net, a11y, requested) {
|
|
8806
|
+
async function launchWithInjection(net, a11y, keyboard, requested) {
|
|
8602
8807
|
const injected = net ? await net.launchEnv(requested ?? {}) : undefined;
|
|
8603
8808
|
if (injected && !injected.success)
|
|
8604
8809
|
return injected;
|
|
8605
8810
|
const forA11y = injected?.data || !a11y ? undefined : await a11y.launchEnv(requested ?? {});
|
|
8606
8811
|
if (forA11y && !forA11y.success)
|
|
8607
8812
|
return forA11y;
|
|
8608
|
-
const
|
|
8813
|
+
const carried = injected?.data ?? forA11y?.data;
|
|
8814
|
+
const env = keyboard ? carried ? { ...carried, ...keyboard.launchMode() } : keyboard.launchEnv() : carried;
|
|
8609
8815
|
return { success: true, data: env ? { ...requested, env: { ...requested?.env, ...env } } : requested };
|
|
8610
8816
|
}
|
|
8611
8817
|
function createIosDriver(swap, simctl, opts) {
|
|
@@ -8620,6 +8826,7 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8620
8826
|
relaunch: (bundleId) => driverRef ? driverRef.app.launch(bundleId, { relaunch: true, inject: true }) : noLeaseProxy()
|
|
8621
8827
|
});
|
|
8622
8828
|
const a11y = opts.a11y?.();
|
|
8829
|
+
const kbd = opts.keyboard?.();
|
|
8623
8830
|
const nativeAudit = opts.nativeAudit?.({ lastBundle: () => lastLaunched });
|
|
8624
8831
|
const { client } = swap;
|
|
8625
8832
|
let axFailures = 0;
|
|
@@ -8686,7 +8893,7 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8686
8893
|
const send = (op, p = {}, timeoutMs) => request(op, p, timeoutMs === undefined ? {} : { timeoutMs });
|
|
8687
8894
|
const sendVoid = async (op, p = {}, timeoutMs) => {
|
|
8688
8895
|
const result = await send(op, p, timeoutMs);
|
|
8689
|
-
return result.success ?
|
|
8896
|
+
return result.success ? okVoid3 : result;
|
|
8690
8897
|
};
|
|
8691
8898
|
const gestureTimeout = (durationMs, base = 0) => (durationMs ?? 0) + base + GESTURE_MARGIN_MS;
|
|
8692
8899
|
const helperOutdated = () => fail2(driverError("E_UNSUPPORTED", `this warden-simd predates the gesture op: restart the helper (warden ui close --udid ${udid}) or rebuild it (bun run --cwd packages/e2e native:build)`, { detail: { reason: "helper_outdated" } }));
|
|
@@ -8725,7 +8932,7 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8725
8932
|
if (!viaHelper.success)
|
|
8726
8933
|
return viaHelper;
|
|
8727
8934
|
note(viaHelper.data);
|
|
8728
|
-
return
|
|
8935
|
+
return okVoid3;
|
|
8729
8936
|
}
|
|
8730
8937
|
let failureDiagnosed = false;
|
|
8731
8938
|
const fetchSnapshot = async (o) => {
|
|
@@ -8775,10 +8982,11 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8775
8982
|
async function snapshot(o) {
|
|
8776
8983
|
if (bridgeProven)
|
|
8777
8984
|
return snapshotOnce(o);
|
|
8985
|
+
const budgetMs = opts.coldBridgeBudgetMs ?? COLD_BRIDGE_BUDGET_MS;
|
|
8778
8986
|
const result = await retryColdSnapshot(() => snapshotOnce(o), {
|
|
8779
8987
|
now,
|
|
8780
8988
|
sleep,
|
|
8781
|
-
budgetMs:
|
|
8989
|
+
budgetMs: Math.min(budgetMs, readDeadlineRemaining() ?? budgetMs),
|
|
8782
8990
|
...opts.log ? { log: opts.log } : {}
|
|
8783
8991
|
});
|
|
8784
8992
|
if (result.success)
|
|
@@ -8832,6 +9040,9 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8832
9040
|
const a11yLoaded = await a11y?.confirmLoaded();
|
|
8833
9041
|
if (a11yLoaded && !a11yLoaded.success)
|
|
8834
9042
|
return a11yLoaded.error;
|
|
9043
|
+
const kbdLoaded = await kbd?.confirmLoaded();
|
|
9044
|
+
if (kbdLoaded && !kbdLoaded.success)
|
|
9045
|
+
return kbdLoaded.error;
|
|
8835
9046
|
return;
|
|
8836
9047
|
}
|
|
8837
9048
|
async function rebind(bundleId) {
|
|
@@ -8846,8 +9057,6 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8846
9057
|
return false;
|
|
8847
9058
|
}
|
|
8848
9059
|
noteRebind(reply.data);
|
|
8849
|
-
if (reply.data.bound)
|
|
8850
|
-
bridgeProven = true;
|
|
8851
9060
|
return reply.data.bound;
|
|
8852
9061
|
}
|
|
8853
9062
|
function noteSettleAxFailure(message) {
|
|
@@ -8933,6 +9142,18 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
8933
9142
|
const result = await request("frontmost", { bundleId }, { timeoutMs: FRONTMOST_TIMEOUT_MS });
|
|
8934
9143
|
return result.success ? { success: true, data: result.data.frontmost } : result;
|
|
8935
9144
|
}
|
|
9145
|
+
async function axWedge(o) {
|
|
9146
|
+
const recover = o?.recover === true;
|
|
9147
|
+
const result = await request("axWedge", { recover }, { timeoutMs: recover ? AX_WEDGE_RECOVER_MS : 5000 });
|
|
9148
|
+
if (result.success)
|
|
9149
|
+
return { success: true, data: toAxWedgeState(result.data) };
|
|
9150
|
+
if (predatesOp(result.error)) {
|
|
9151
|
+
return driverErr("E_UNSUPPORTED", "this warden-simd predates the axWedge op", {
|
|
9152
|
+
detail: { reason: "helper_outdated" }
|
|
9153
|
+
});
|
|
9154
|
+
}
|
|
9155
|
+
return result;
|
|
9156
|
+
}
|
|
8936
9157
|
async function health() {
|
|
8937
9158
|
const result = await request("health");
|
|
8938
9159
|
if (!result.success)
|
|
@@ -9002,6 +9223,7 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
9002
9223
|
alert,
|
|
9003
9224
|
alertOn,
|
|
9004
9225
|
isFrontmost,
|
|
9226
|
+
axWedge,
|
|
9005
9227
|
readA11y: async (snapshot) => a11y ? a11y.read(snapshot) : driverErr("E_UNSUPPORTED", "this iOS driver was opened without the injected library channel"),
|
|
9006
9228
|
a11yEvents: async (since) => a11y ? a11y.events(since) : driverErr("E_UNSUPPORTED", "this iOS driver was opened without the injected library channel"),
|
|
9007
9229
|
auditNatively: async (options) => nativeAudit ? nativeAudit.audit(options ?? {}) : { issues: [], skipped: { source: "xcuitest", reason: "this iOS driver was opened without the runner" } },
|
|
@@ -9014,6 +9236,26 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
9014
9236
|
locale: (tag, o) => settings ? settings.locale(tag, o) : noSettings(),
|
|
9015
9237
|
a11y: (op) => settings ? settings.a11y(op) : noSettings(),
|
|
9016
9238
|
battery: (op) => settings ? settings.battery(op) : noSettings(),
|
|
9239
|
+
keyboard: async (mode) => kbd ? kbd.keyboard(mode) : driverErr("E_UNSUPPORTED", "this iOS driver was opened without the injected library channel"),
|
|
9240
|
+
async dismissKeyboard() {
|
|
9241
|
+
const resigned = kbd ? await kbd.dismiss() : undefined;
|
|
9242
|
+
if (resigned !== undefined && !resigned.success)
|
|
9243
|
+
return resigned;
|
|
9244
|
+
if (resigned?.data.attached)
|
|
9245
|
+
return { success: true, data: { via: "resign" } };
|
|
9246
|
+
opts.log?.("[ios] keyboard dismissed with Enter: the app was launched without libwarden-inject.dylib, so Return may submit the focused field");
|
|
9247
|
+
const pressed = await sendVoid("key", params({ usage: KEY_USAGE.Enter }));
|
|
9248
|
+
return pressed.success ? { success: true, data: { via: "key" } } : pressed;
|
|
9249
|
+
},
|
|
9250
|
+
async keyboardState() {
|
|
9251
|
+
const taken = await snapshot();
|
|
9252
|
+
if (!taken.success)
|
|
9253
|
+
return taken;
|
|
9254
|
+
return {
|
|
9255
|
+
success: true,
|
|
9256
|
+
data: { mode: kbd?.mode() ?? DEFAULT_KEYBOARD_MODE, visible: keyboardVisible(taken.data) }
|
|
9257
|
+
};
|
|
9258
|
+
},
|
|
9017
9259
|
camera: async (op) => net ? net.camera(op) : driverErr("E_UNSUPPORTED", "the simulated camera on iOS needs a device lease for the injected dylib: run the spec with `warden e2e`, or `warden ui`; a bare `bun test` has no lease"),
|
|
9018
9260
|
memoryWarning: (o) => settings ? settings.memoryWarning(o) : noSettings(),
|
|
9019
9261
|
push: (payload, o) => settings ? settings.push(payload, o) : noSettings(),
|
|
@@ -9035,7 +9277,7 @@ function createIosDriver(swap, simctl, opts) {
|
|
|
9035
9277
|
app: {
|
|
9036
9278
|
launch: async (bundleId, plain) => {
|
|
9037
9279
|
const requested = settings ? withStagedSettings(plain, settings.launchSettings()) : plain;
|
|
9038
|
-
const withEnv = await launchWithInjection(net, a11y, requested);
|
|
9280
|
+
const withEnv = await launchWithInjection(net, a11y, kbd, requested);
|
|
9039
9281
|
if (!withEnv.success)
|
|
9040
9282
|
return withEnv;
|
|
9041
9283
|
const o = withEnv.data;
|
|
@@ -9171,6 +9413,7 @@ async function openIosDriver(o) {
|
|
|
9171
9413
|
...o.coldBridgeBudgetMs !== undefined ? { coldBridgeBudgetMs: o.coldBridgeBudgetMs } : {},
|
|
9172
9414
|
...network ? { network } : {},
|
|
9173
9415
|
a11y: () => iosA11yFor(o, now, sleep),
|
|
9416
|
+
keyboard: () => iosKeyboardFor(o, now, sleep),
|
|
9174
9417
|
nativeAudit: (ctx) => nativeAuditFor(o, exec, log, ctx),
|
|
9175
9418
|
settings: (ctx) => settingsFor(o, exec, ctx),
|
|
9176
9419
|
...o.clockRecorder ? { clockRecorder: o.clockRecorder } : {}
|
|
@@ -9210,6 +9453,28 @@ function iosNetworkFactory(o, simctl, now, sleep) {
|
|
|
9210
9453
|
...o.debug ? { debug: true } : {}
|
|
9211
9454
|
});
|
|
9212
9455
|
}
|
|
9456
|
+
function iosKeyboardFor(o, now, sleep) {
|
|
9457
|
+
const wardenHome2 = o.wardenHome ?? wardenHome();
|
|
9458
|
+
return createIosKeyboard({
|
|
9459
|
+
channel: createInjectChannel({
|
|
9460
|
+
statePath: injectStatePath2(wardenHome2, o.udid),
|
|
9461
|
+
now,
|
|
9462
|
+
sleep,
|
|
9463
|
+
...o.bundleId ? { bundleId: () => o.bundleId } : {},
|
|
9464
|
+
...o.injectFs ? { fs: o.injectFs } : {}
|
|
9465
|
+
}),
|
|
9466
|
+
dylib: () => locateInjectDylib({
|
|
9467
|
+
env: { [INJECT_DYLIB_ENV]: process.env[INJECT_DYLIB_ENV], WARDEN_HELPER_DIR: o.env?.helperDir },
|
|
9468
|
+
execPath: o.execPath ?? process.execPath,
|
|
9469
|
+
importDir: o.importDir ?? import.meta.dir,
|
|
9470
|
+
wardenHome: wardenHome2,
|
|
9471
|
+
exists: o.exists ?? existsSync8,
|
|
9472
|
+
realpath: o.realpath ?? realpathSync2,
|
|
9473
|
+
...o.version ? { version: o.version } : {}
|
|
9474
|
+
}),
|
|
9475
|
+
...o.debug ? { debug: true } : {}
|
|
9476
|
+
});
|
|
9477
|
+
}
|
|
9213
9478
|
function iosA11yFor(o, now, sleep) {
|
|
9214
9479
|
const wardenHome2 = o.wardenHome ?? wardenHome();
|
|
9215
9480
|
return createIosA11y({
|
|
@@ -9453,7 +9718,7 @@ var SCREENSHOT_FALLBACK2 = new Set(["E_UNSUPPORTED", "E_IO", "E_INTERNAL"]);
|
|
|
9453
9718
|
function params2(values) {
|
|
9454
9719
|
return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined));
|
|
9455
9720
|
}
|
|
9456
|
-
var
|
|
9721
|
+
var okVoid4 = { success: true, data: undefined };
|
|
9457
9722
|
function fail3(error) {
|
|
9458
9723
|
return { success: false, error };
|
|
9459
9724
|
}
|
|
@@ -9486,7 +9751,7 @@ function createIosDeviceDriver(client, devicectl, opts) {
|
|
|
9486
9751
|
}
|
|
9487
9752
|
const sendVoid = async (op, p = {}, timeoutMs) => {
|
|
9488
9753
|
const result = await request(op, p, timeoutMs === undefined ? {} : { timeoutMs });
|
|
9489
|
-
return result.success ?
|
|
9754
|
+
return result.success ? okVoid4 : result;
|
|
9490
9755
|
};
|
|
9491
9756
|
async function snapshot(o) {
|
|
9492
9757
|
const result = await request("snapshot", params2({ interactiveOnly: o?.interactiveOnly, backend: o?.backend }));
|
|
@@ -9621,7 +9886,7 @@ function createIosDeviceDriver(client, devicectl, opts) {
|
|
|
9621
9886
|
return installed;
|
|
9622
9887
|
for (const bundleId of installed.data.bundleIds)
|
|
9623
9888
|
owned.add(bundleId);
|
|
9624
|
-
return
|
|
9889
|
+
return okVoid4;
|
|
9625
9890
|
}
|
|
9626
9891
|
async function uninstall(bundleId) {
|
|
9627
9892
|
const refused = guard(bundleId, "uninstall");
|
|
@@ -9660,6 +9925,11 @@ function createIosDeviceDriver(client, devicectl, opts) {
|
|
|
9660
9925
|
gesture: async () => unsupported2("gesture", "the XCUITest runner takes taps, swipes and drags only"),
|
|
9661
9926
|
biometrics: async () => unsupported2("biometrics", "Face ID / Touch ID cannot be simulated on a real sensor; use a simulator"),
|
|
9662
9927
|
...physicalConditionOps(`physical iPhone ${udid}`),
|
|
9928
|
+
dismissKeyboard: async () => {
|
|
9929
|
+
const pressed = await sendVoid("key", params2({ usage: KEY_USAGE.Enter }));
|
|
9930
|
+
return pressed.success ? { success: true, data: { via: "key" } } : pressed;
|
|
9931
|
+
},
|
|
9932
|
+
keyboardState: async () => unsupported2("the keyboard mode", "the injected library runs in simulator apps only"),
|
|
9663
9933
|
typeText: (text) => sendVoid("typeText", { text }, deviceTypeTextBudgetMs(text)),
|
|
9664
9934
|
key: (key, modifiers) => sendVoid("key", params2({ usage: KEY_USAGE[key], modifiers: modifiers && [...modifiers] })),
|
|
9665
9935
|
pressButton,
|
|
@@ -10382,6 +10652,10 @@ function createDevice({
|
|
|
10382
10652
|
locale: conditions.locale,
|
|
10383
10653
|
a11y: conditions.a11y,
|
|
10384
10654
|
battery: conditions.battery,
|
|
10655
|
+
keyboard: conditions.keyboard,
|
|
10656
|
+
async keyboardVisible() {
|
|
10657
|
+
return (await unwrap(() => driver.keyboardState(), "read the keyboard", signal())).visible;
|
|
10658
|
+
},
|
|
10385
10659
|
camera: conditions.camera,
|
|
10386
10660
|
memoryWarning: conditions.memoryWarning,
|
|
10387
10661
|
push: conditions.push,
|
|
@@ -10451,13 +10725,9 @@ function createDevice({
|
|
|
10451
10725
|
await unwrap(() => driver.clipboard(text), "set clipboard", signal());
|
|
10452
10726
|
},
|
|
10453
10727
|
async hideKeyboard() {
|
|
10454
|
-
|
|
10455
|
-
if (!snapshot.flat.some((element) => element.role === "keyboard"))
|
|
10728
|
+
if (!await device.keyboardVisible())
|
|
10456
10729
|
return;
|
|
10457
|
-
|
|
10458
|
-
await unwrap(() => driver.key("Enter"), "hide keyboard", signal());
|
|
10459
|
-
else
|
|
10460
|
-
await unwrap(() => driver.pressButton("back"), "hide keyboard", signal());
|
|
10730
|
+
await unwrap(() => driver.dismissKeyboard(), "hide keyboard", signal());
|
|
10461
10731
|
},
|
|
10462
10732
|
async screenshot(name) {
|
|
10463
10733
|
const dir = session.attemptDir ?? join22(session.out, "adhoc");
|
|
@@ -10698,13 +10968,15 @@ class Runtime {
|
|
|
10698
10968
|
}
|
|
10699
10969
|
async poll(step, timeoutMs, options = {}) {
|
|
10700
10970
|
const signal = this.host.signal;
|
|
10701
|
-
const
|
|
10971
|
+
const outer = readDeadlineRemaining();
|
|
10972
|
+
const deadline = this.clock.now() + (outer === undefined ? timeoutMs : Math.min(timeoutMs, outer));
|
|
10973
|
+
const result = await withReadDeadline(() => deadline - this.clock.now(), () => poll(step, {
|
|
10702
10974
|
timeoutMs,
|
|
10703
10975
|
...options.intervalMs === undefined ? {} : { intervalMs: options.intervalMs },
|
|
10704
10976
|
...signal === undefined ? {} : { signal },
|
|
10705
10977
|
now: this.clock.now,
|
|
10706
10978
|
sleep: this.clock.sleep
|
|
10707
|
-
});
|
|
10979
|
+
}));
|
|
10708
10980
|
if (result.status === "aborted")
|
|
10709
10981
|
throw abortError(signal);
|
|
10710
10982
|
return result;
|
|
@@ -10877,6 +11149,8 @@ function traceDevice(device, span) {
|
|
|
10877
11149
|
locale: (tag, options) => span("device.locale", () => device.locale(tag, options)),
|
|
10878
11150
|
a11y: (op) => span("device.a11y", () => device.a11y(op)),
|
|
10879
11151
|
battery: (op) => span("device.battery", () => device.battery(op)),
|
|
11152
|
+
keyboard: (mode) => span("device.keyboard", () => device.keyboard(mode)),
|
|
11153
|
+
keyboardVisible: () => span("device.keyboardVisible", () => device.keyboardVisible()),
|
|
10880
11154
|
camera: {
|
|
10881
11155
|
set: (path, options) => span("device.camera.set", () => camera.set(path, options)),
|
|
10882
11156
|
clear: (facing) => span("device.camera.clear", () => camera.clear(facing)),
|
|
@@ -167,6 +167,7 @@ export declare const e2eSuiteSchema: z.ZodObject<{
|
|
|
167
167
|
except: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
168
168
|
keep: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
169
169
|
}, z.core.$strict>]>>;
|
|
170
|
+
golden: z.ZodOptional<z.ZodBoolean>;
|
|
170
171
|
biometrics: z.ZodOptional<z.ZodBoolean>;
|
|
171
172
|
reclaim: z.ZodOptional<z.ZodEnum<{
|
|
172
173
|
none: "none";
|
|
@@ -262,6 +263,10 @@ export declare const e2eSuiteSchema: z.ZodObject<{
|
|
|
262
263
|
}>>;
|
|
263
264
|
reduceMotion: z.ZodOptional<z.ZodBoolean>;
|
|
264
265
|
}, z.core.$strict>>;
|
|
266
|
+
keyboard: z.ZodOptional<z.ZodEnum<{
|
|
267
|
+
software: "software";
|
|
268
|
+
hardware: "hardware";
|
|
269
|
+
}>>;
|
|
265
270
|
}, z.core.$strict>>;
|
|
266
271
|
a11y: z.ZodOptional<z.ZodObject<{
|
|
267
272
|
ignore: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -12,6 +12,12 @@ export type BuildConfiguration = "Debug" | "Release";
|
|
|
12
12
|
export declare const IOS_NATIVE_PREPARE: string;
|
|
13
13
|
/** Local build command (run in the project root) when `build.<platform>` is not configured. */
|
|
14
14
|
export declare function defaultBuildCommand(platform: Platform, configuration: BuildConfiguration, framework?: AppFramework): string;
|
|
15
|
+
/**
|
|
16
|
+
* Android build: prebuild a CNG checkout that has no `android/`, then Gradle alone. Never `expo run:android`: it has no
|
|
17
|
+
* build-only mode (its `--no-install` skips dependency install, not the app's) and installs the APK on whichever
|
|
18
|
+
* emulator is booted, warden's or not. warden installs the cached build itself.
|
|
19
|
+
*/
|
|
20
|
+
export declare function androidGradleCommand(configuration: BuildConfiguration, framework?: AppFramework): string;
|
|
15
21
|
/** What an iOS device build is signed with: the team (always) and, when set, the bundle id that replaces the project's. */
|
|
16
22
|
export type IosDeviceBuild = {
|
|
17
23
|
team: string;
|
|
@@ -55,6 +61,8 @@ export declare const EAS_TIMEOUT_MS: number;
|
|
|
55
61
|
export declare const EAS_TRIGGER_GRACE_MS: number;
|
|
56
62
|
/** Local native build timeout. */
|
|
57
63
|
export declare const LOCAL_BUILD_TIMEOUT_MS: number;
|
|
64
|
+
/** How often a local build nobody watches says it is still running (`still building ios (6m 0s): …`). */
|
|
65
|
+
export declare const BUILD_HEARTBEAT_MS = 60000;
|
|
58
66
|
/** Fingerprint command timeout. */
|
|
59
67
|
export declare const FINGERPRINT_TIMEOUT_MS: number;
|
|
60
68
|
/** Build-lock lease ttl; the lease also carries the holder's pid so it lives as long as the process. */
|