@delacour/warden-e2e 0.11.0 → 0.12.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-ggcjzrvh.mjs → chunk-qz94hsb6.mjs} +365 -216
- package/index.mjs +5 -2
- package/package.json +2 -2
- package/preload.mjs +570 -419
- package/types/e2e/src/devtools/native-log-tail.d.ts +13 -0
- package/types/e2e/src/devtools/native-log.d.ts +14 -1
- package/types/e2e/src/runner/failure.d.ts +2 -0
- package/types/e2e/src/session.d.ts +1 -1
|
@@ -2193,6 +2193,12 @@ function scrollGaveUp(target, absent, effort, screen) {
|
|
|
2193
2193
|
return new E2eError2("LOCATOR_NOT_FOUND", `${target} was not found after ${effort}`, screen);
|
|
2194
2194
|
return new E2eError2("NOT_ACTIONABLE", `${target} is still not on screen after ${effort}`, screen);
|
|
2195
2195
|
}
|
|
2196
|
+
async function scrollOnce(rt, observed, direction, momentum) {
|
|
2197
|
+
const vector = swipeVector(direction, screenRect(observed.snapshot.screen), momentum);
|
|
2198
|
+
const scrolled = canActOnElements(observed.driver) && rt.drive("scrollUntilVisible", await observed.driver.scrollElement(direction));
|
|
2199
|
+
if (!scrolled)
|
|
2200
|
+
rt.drive("scrollUntilVisible", await observed.driver.swipe(vector.from, vector.to, vector.options));
|
|
2201
|
+
}
|
|
2196
2202
|
async function scrollUntilVisible(rt, target, options = {}) {
|
|
2197
2203
|
assertOptions("scrollUntilVisible", options, ["direction", "momentum", "maxSwipes", "timeout"]);
|
|
2198
2204
|
const direction = options.direction ?? "down";
|
|
@@ -2213,17 +2219,14 @@ async function scrollUntilVisible(rt, target, options = {}) {
|
|
|
2213
2219
|
if (swipes >= maxSwipes || budget.remaining() <= 0) {
|
|
2214
2220
|
throw scrollGaveUp(target, entry === undefined, `${swipes} swipes ${direction}`, rt.excerpt(observed.snapshot));
|
|
2215
2221
|
}
|
|
2216
|
-
|
|
2217
|
-
const scrolled = canActOnElements(observed.driver) && rt.drive("scrollUntilVisible", await observed.driver.scrollElement(direction));
|
|
2218
|
-
if (!scrolled)
|
|
2219
|
-
rt.drive("scrollUntilVisible", await observed.driver.swipe(vector.from, vector.to, vector.options));
|
|
2222
|
+
await scrollOnce(rt, observed, direction, options.momentum);
|
|
2220
2223
|
await observed.driver.settle(SCROLL_SETTLE);
|
|
2221
2224
|
}
|
|
2222
2225
|
});
|
|
2223
2226
|
}
|
|
2224
2227
|
|
|
2225
2228
|
// ../../packages/e2e/src/session.ts
|
|
2226
|
-
import { mkdirSync as
|
|
2229
|
+
import { mkdirSync as mkdirSync3, writeSync } from "fs";
|
|
2227
2230
|
import { resolve as resolve2 } from "path";
|
|
2228
2231
|
|
|
2229
2232
|
// ../../packages/e2e/src/devtools/devtools.types.ts
|
|
@@ -4121,6 +4124,227 @@ async function openDevtoolsFacet(o) {
|
|
|
4121
4124
|
});
|
|
4122
4125
|
}
|
|
4123
4126
|
|
|
4127
|
+
// ../../packages/e2e/src/devtools/native-log.ts
|
|
4128
|
+
import { copyFileSync, mkdirSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
4129
|
+
import { homedir } from "os";
|
|
4130
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
4131
|
+
|
|
4132
|
+
// ../../packages/e2e/src/devtools/native-log-tail.ts
|
|
4133
|
+
var TAIL_LINES = 20;
|
|
4134
|
+
var MAX_MESSAGE = 200;
|
|
4135
|
+
var COMPOSE_FAILURE = "<compose failure";
|
|
4136
|
+
var cut = (message) => message.length > MAX_MESSAGE ? `${message.slice(0, MAX_MESSAGE)}\u2026` : message;
|
|
4137
|
+
function pick(entries) {
|
|
4138
|
+
const ordered = [...entries].sort((a, b) => a.sortKey < b.sortKey ? -1 : a.sortKey > b.sortKey ? 1 : 0);
|
|
4139
|
+
const severe = ordered.filter((e) => e.severe).slice(-TAIL_LINES);
|
|
4140
|
+
const rest = ordered.filter((e) => !e.severe).slice(-(TAIL_LINES - severe.length));
|
|
4141
|
+
return [...severe, ...rest].sort((a, b) => a.sortKey < b.sortKey ? -1 : a.sortKey > b.sortKey ? 1 : 0).map((e) => e.text);
|
|
4142
|
+
}
|
|
4143
|
+
function parseIos(text) {
|
|
4144
|
+
const events = [];
|
|
4145
|
+
for (const line of text.split(`
|
|
4146
|
+
`)) {
|
|
4147
|
+
if (!line.startsWith("{"))
|
|
4148
|
+
continue;
|
|
4149
|
+
try {
|
|
4150
|
+
const parsed = JSON.parse(line);
|
|
4151
|
+
if (typeof parsed === "object" && parsed !== null)
|
|
4152
|
+
events.push(parsed);
|
|
4153
|
+
} catch {}
|
|
4154
|
+
}
|
|
4155
|
+
return events;
|
|
4156
|
+
}
|
|
4157
|
+
function iosTail(ndjson) {
|
|
4158
|
+
const entries = [];
|
|
4159
|
+
for (const event of parseIos(ndjson)) {
|
|
4160
|
+
const message = event.eventMessage;
|
|
4161
|
+
if (event.eventType !== "logEvent" || !message || message.startsWith(COMPOSE_FAILURE))
|
|
4162
|
+
continue;
|
|
4163
|
+
const stamp = event.timestamp ?? "";
|
|
4164
|
+
const time = /(\d\d:\d\d:\d\d\.\d{3})/.exec(stamp)?.[1] ?? stamp;
|
|
4165
|
+
const level = (event.messageType ?? "Default").toLowerCase();
|
|
4166
|
+
const where = [event.subsystem, event.category].filter(Boolean).join("/");
|
|
4167
|
+
entries.push({
|
|
4168
|
+
sortKey: stamp,
|
|
4169
|
+
severe: level === "error" || level === "fault",
|
|
4170
|
+
text: cut(`${time} ${level} ${where ? `${where} ` : ""}${message}`)
|
|
4171
|
+
});
|
|
4172
|
+
}
|
|
4173
|
+
return pick(entries);
|
|
4174
|
+
}
|
|
4175
|
+
function unresolvedShare(ndjson) {
|
|
4176
|
+
let unresolved = 0;
|
|
4177
|
+
let total = 0;
|
|
4178
|
+
for (const event of parseIos(ndjson)) {
|
|
4179
|
+
if (event.eventType !== "logEvent" || !event.eventMessage)
|
|
4180
|
+
continue;
|
|
4181
|
+
total += 1;
|
|
4182
|
+
if (event.eventMessage.startsWith(COMPOSE_FAILURE))
|
|
4183
|
+
unresolved += 1;
|
|
4184
|
+
}
|
|
4185
|
+
return { unresolved, total };
|
|
4186
|
+
}
|
|
4187
|
+
function androidTail(logcat) {
|
|
4188
|
+
const entries = [];
|
|
4189
|
+
for (const line of logcat.split(`
|
|
4190
|
+
`)) {
|
|
4191
|
+
const m = /^(\d+\.\d+)\s+\d+\s+\d+\s+([VDIWEF])\s/.exec(line);
|
|
4192
|
+
if (!m)
|
|
4193
|
+
continue;
|
|
4194
|
+
entries.push({ sortKey: (m[1] ?? "").padStart(20, "0"), severe: "EFW".includes(m[2] ?? ""), text: cut(line) });
|
|
4195
|
+
}
|
|
4196
|
+
return pick(entries);
|
|
4197
|
+
}
|
|
4198
|
+
function formatNativeTail(lines) {
|
|
4199
|
+
if (lines.length === 0)
|
|
4200
|
+
return [];
|
|
4201
|
+
return [
|
|
4202
|
+
` native log, last ${lines.length} line${lines.length === 1 ? "" : "s"} before the failure (full: native.log):`,
|
|
4203
|
+
...lines.map((l) => ` ${l}`)
|
|
4204
|
+
];
|
|
4205
|
+
}
|
|
4206
|
+
|
|
4207
|
+
// ../../packages/e2e/src/devtools/native-log.ts
|
|
4208
|
+
var NATIVE_LOG = "native.log";
|
|
4209
|
+
var NATIVE_PRIVATE_DATA_ENV = "WARDEN_NATIVE_LOG_PRIVATE";
|
|
4210
|
+
async function enableNativePrivateData(udid, exec, timeoutMs = DEFAULT_TIMEOUT_MS3) {
|
|
4211
|
+
const log = (...args) => exec(["xcrun", "simctl", "spawn", udid, "log", ...args], { timeoutMs });
|
|
4212
|
+
try {
|
|
4213
|
+
const status = await log("config", "--status");
|
|
4214
|
+
if (status.exitCode === 0 && status.stdout.includes("PRIVATE_DATA"))
|
|
4215
|
+
return;
|
|
4216
|
+
const res = await log("config", "--mode", "private_data:on");
|
|
4217
|
+
return res.exitCode === 0 ? undefined : `native log: ${failed("log config private_data:on", res)}`;
|
|
4218
|
+
} catch (cause) {
|
|
4219
|
+
return `native log: private_data:on: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
var UNRESOLVED_MIN_EVENTS = 10;
|
|
4223
|
+
var DEFAULT_TIMEOUT_MS3 = 1e4;
|
|
4224
|
+
var SLACK_S = 5;
|
|
4225
|
+
var MAX_BYTES = 2000000;
|
|
4226
|
+
function realNativeFs() {
|
|
4227
|
+
return {
|
|
4228
|
+
listReports: (dir) => {
|
|
4229
|
+
try {
|
|
4230
|
+
return readdirSync(dir).map((name) => ({ name, mtimeMs: statSync(join2(dir, name)).mtimeMs }));
|
|
4231
|
+
} catch {
|
|
4232
|
+
return [];
|
|
4233
|
+
}
|
|
4234
|
+
},
|
|
4235
|
+
copy: (from, to) => {
|
|
4236
|
+
mkdirSync(dirname2(to), { recursive: true });
|
|
4237
|
+
copyFileSync(from, to);
|
|
4238
|
+
},
|
|
4239
|
+
write: (path, text) => {
|
|
4240
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
4241
|
+
writeFileSync(path, text);
|
|
4242
|
+
}
|
|
4243
|
+
};
|
|
4244
|
+
}
|
|
4245
|
+
function realNativeLogDeps(exec, adb) {
|
|
4246
|
+
return { exec, adb, fs: realNativeFs(), reportsDir: join2(homedir(), "Library", "Logs", "DiagnosticReports") };
|
|
4247
|
+
}
|
|
4248
|
+
function tail(text) {
|
|
4249
|
+
return text.length > MAX_BYTES ? text.slice(text.length - MAX_BYTES) : text;
|
|
4250
|
+
}
|
|
4251
|
+
function failed(what, res) {
|
|
4252
|
+
return `${what}: exit ${res.exitCode} ${res.stderr.trim().split(`
|
|
4253
|
+
`)[0] ?? ""}`.trim();
|
|
4254
|
+
}
|
|
4255
|
+
async function iosProcessName(target, exec, timeoutMs) {
|
|
4256
|
+
const container = await exec(["xcrun", "simctl", "get_app_container", target.udid, target.bundleId, "app"], {
|
|
4257
|
+
timeoutMs
|
|
4258
|
+
});
|
|
4259
|
+
const app = container.stdout.trim();
|
|
4260
|
+
if (container.exitCode !== 0 || !app)
|
|
4261
|
+
return { error: failed(`app container of ${target.bundleId}`, container) };
|
|
4262
|
+
const name = await exec(["plutil", "-extract", "CFBundleExecutable", "raw", "-o", "-", join2(app, "Info.plist")], {
|
|
4263
|
+
timeoutMs
|
|
4264
|
+
});
|
|
4265
|
+
const exe = name.stdout.trim();
|
|
4266
|
+
return name.exitCode === 0 && exe ? { exe } : { error: failed("CFBundleExecutable", name) };
|
|
4267
|
+
}
|
|
4268
|
+
async function iosNativeLog(target, deps, win, timeoutMs) {
|
|
4269
|
+
const capture = { files: [], problems: [], tail: [] };
|
|
4270
|
+
const proc = await iosProcessName(target, deps.exec, timeoutMs);
|
|
4271
|
+
if (proc.error !== undefined || proc.exe === undefined) {
|
|
4272
|
+
capture.problems.push(`native log: ${proc.error ?? "unknown process"}`);
|
|
4273
|
+
return capture;
|
|
4274
|
+
}
|
|
4275
|
+
const seconds = Math.ceil((win.nowMs - win.sinceMs) / 1000) + SLACK_S;
|
|
4276
|
+
const show = await deps.exec([
|
|
4277
|
+
"xcrun",
|
|
4278
|
+
"simctl",
|
|
4279
|
+
"spawn",
|
|
4280
|
+
target.udid,
|
|
4281
|
+
"log",
|
|
4282
|
+
"show",
|
|
4283
|
+
"--style",
|
|
4284
|
+
"ndjson",
|
|
4285
|
+
"--info",
|
|
4286
|
+
"--debug",
|
|
4287
|
+
"--last",
|
|
4288
|
+
`${seconds}s`,
|
|
4289
|
+
"--predicate",
|
|
4290
|
+
`process == "${proc.exe}"`
|
|
4291
|
+
], { timeoutMs });
|
|
4292
|
+
if (show.exitCode === 0) {
|
|
4293
|
+
deps.fs.write(join2(win.dir, NATIVE_LOG), tail(show.stdout));
|
|
4294
|
+
capture.files.push(NATIVE_LOG);
|
|
4295
|
+
capture.tail = iosTail(show.stdout);
|
|
4296
|
+
const { unresolved, total } = unresolvedShare(show.stdout);
|
|
4297
|
+
if (total >= UNRESOLVED_MIN_EVENTS && unresolved * 2 > total) {
|
|
4298
|
+
capture.problems.push(`native log: ${unresolved} of ${total} messages unresolved (<compose failure>): the simulator runtime's shared cache could not be read back`);
|
|
4299
|
+
}
|
|
4300
|
+
} else {
|
|
4301
|
+
capture.problems.push(`native log: ${failed("log show", show)}`);
|
|
4302
|
+
}
|
|
4303
|
+
for (const report of deps.fs.listReports(deps.reportsDir)) {
|
|
4304
|
+
if (!report.name.startsWith(proc.exe) || !report.name.endsWith(".ips") || report.mtimeMs < win.sinceMs)
|
|
4305
|
+
continue;
|
|
4306
|
+
deps.fs.copy(join2(deps.reportsDir, report.name), join2(win.dir, report.name));
|
|
4307
|
+
capture.files.push(report.name);
|
|
4308
|
+
}
|
|
4309
|
+
return capture;
|
|
4310
|
+
}
|
|
4311
|
+
async function androidNativeLog(target, deps, win, timeoutMs) {
|
|
4312
|
+
const capture = { files: [], problems: [], tail: [] };
|
|
4313
|
+
const adb = (...args) => deps.exec([deps.adb, "-s", target.serial, ...args], { timeoutMs });
|
|
4314
|
+
const pid = await adb("shell", "pidof", target.pkg);
|
|
4315
|
+
const pidArg = pid.exitCode === 0 && /^\d+/.test(pid.stdout.trim()) ? [`--pid=${pid.stdout.trim().split(/\s+/)[0]}`] : [];
|
|
4316
|
+
const since = ((win.sinceMs - SLACK_S * 1000) / 1000).toFixed(3);
|
|
4317
|
+
const main = await adb("logcat", "-d", "-v", "epoch", ...pidArg, "-T", since);
|
|
4318
|
+
const crash = await adb("logcat", "-d", "-b", "crash", "-v", "epoch");
|
|
4319
|
+
if (main.exitCode !== 0 && crash.exitCode !== 0) {
|
|
4320
|
+
capture.problems.push(`native log: ${failed("logcat", main)}`);
|
|
4321
|
+
return capture;
|
|
4322
|
+
}
|
|
4323
|
+
const sections = [
|
|
4324
|
+
main.exitCode === 0 ? main.stdout : "",
|
|
4325
|
+
crash.exitCode === 0 ? `--- crash buffer ---
|
|
4326
|
+
${crash.stdout}` : ""
|
|
4327
|
+
];
|
|
4328
|
+
deps.fs.write(join2(win.dir, NATIVE_LOG), tail(sections.filter(Boolean).join(`
|
|
4329
|
+
`)));
|
|
4330
|
+
capture.files.push(NATIVE_LOG);
|
|
4331
|
+
capture.tail = androidTail(sections.filter(Boolean).join(`
|
|
4332
|
+
`));
|
|
4333
|
+
return capture;
|
|
4334
|
+
}
|
|
4335
|
+
async function captureNativeLog(target, deps, win) {
|
|
4336
|
+
const timeoutMs = win.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
4337
|
+
try {
|
|
4338
|
+
return target.platform === "ios" ? await iosNativeLog(target, deps, win, timeoutMs) : await androidNativeLog(target, deps, win, timeoutMs);
|
|
4339
|
+
} catch (cause) {
|
|
4340
|
+
return {
|
|
4341
|
+
files: [],
|
|
4342
|
+
problems: [`native log: ${cause instanceof Error ? cause.message : String(cause)}`],
|
|
4343
|
+
tail: []
|
|
4344
|
+
};
|
|
4345
|
+
}
|
|
4346
|
+
}
|
|
4347
|
+
|
|
4124
4348
|
// ../../packages/e2e/src/driver/ios/hid-recovery.ts
|
|
4125
4349
|
import { existsSync as existsSync2 } from "fs";
|
|
4126
4350
|
|
|
@@ -4649,7 +4873,7 @@ function socketTransport(opts) {
|
|
|
4649
4873
|
}
|
|
4650
4874
|
|
|
4651
4875
|
// ../../packages/e2e/src/driver/ios/simd-client.ts
|
|
4652
|
-
var
|
|
4876
|
+
var DEFAULT_TIMEOUT_MS4 = 1e4;
|
|
4653
4877
|
var DEFAULT_READY_TIMEOUT_MS = 15000;
|
|
4654
4878
|
var SHUTDOWN_TIMEOUT_MS = 500;
|
|
4655
4879
|
var STDERR_TAIL2 = 20;
|
|
@@ -4661,7 +4885,7 @@ function crashed(info, what) {
|
|
|
4661
4885
|
});
|
|
4662
4886
|
}
|
|
4663
4887
|
async function createSimdClient(factory, options = {}) {
|
|
4664
|
-
const defaultTimeoutMs = options.defaultTimeoutMs ??
|
|
4888
|
+
const defaultTimeoutMs = options.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS4;
|
|
4665
4889
|
const readyTimeoutMs = options.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
|
|
4666
4890
|
const maxRespawns = options.maxRespawns ?? 0;
|
|
4667
4891
|
const shutdownOnClose = options.shutdownOnClose ?? false;
|
|
@@ -5472,7 +5696,7 @@ var ENV_NAMES = {
|
|
|
5472
5696
|
a11y: "WARDEN_A11Y",
|
|
5473
5697
|
cameraFeeds: "WARDEN_CAMERA_FEEDS"
|
|
5474
5698
|
};
|
|
5475
|
-
var
|
|
5699
|
+
var DEFAULT_TIMEOUT_MS5 = 120000;
|
|
5476
5700
|
var DEFAULT_ACTION_TIMEOUT_MS = 30000;
|
|
5477
5701
|
var DEFAULT_ASSERTION_TIMEOUT_MS = 5000;
|
|
5478
5702
|
var toggle = z9.enum(["1", "true", "0", "false"]).transform((v) => v === "1" || v === "true");
|
|
@@ -5518,7 +5742,7 @@ var schema = z9.object({
|
|
|
5518
5742
|
devClientScheme: z9.string().min(1).optional(),
|
|
5519
5743
|
launchArgs: launchArgs.default([]),
|
|
5520
5744
|
out: z9.string().optional(),
|
|
5521
|
-
timeout: millis.default(
|
|
5745
|
+
timeout: millis.default(DEFAULT_TIMEOUT_MS5),
|
|
5522
5746
|
actionTimeout: millis.default(DEFAULT_ACTION_TIMEOUT_MS),
|
|
5523
5747
|
assertionTimeout: millis.default(DEFAULT_ASSERTION_TIMEOUT_MS),
|
|
5524
5748
|
specsDir: z9.string().optional(),
|
|
@@ -5614,8 +5838,8 @@ function readEnv(env, opts = {}) {
|
|
|
5614
5838
|
}
|
|
5615
5839
|
|
|
5616
5840
|
// ../../packages/e2e/src/runner/results.ts
|
|
5617
|
-
import { appendFileSync, mkdirSync } from "fs";
|
|
5618
|
-
import { dirname as
|
|
5841
|
+
import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
5842
|
+
import { dirname as dirname3 } from "path";
|
|
5619
5843
|
import { z as z10 } from "zod";
|
|
5620
5844
|
var testStatusSchema = z10.enum(["passed", "failed", "skipped", "timed-out"]);
|
|
5621
5845
|
var testResultSchema = z10.object({
|
|
@@ -5643,7 +5867,7 @@ function openResults(path) {
|
|
|
5643
5867
|
path,
|
|
5644
5868
|
append(result) {
|
|
5645
5869
|
if (!ready) {
|
|
5646
|
-
|
|
5870
|
+
mkdirSync2(dirname3(path), { recursive: true });
|
|
5647
5871
|
ready = true;
|
|
5648
5872
|
}
|
|
5649
5873
|
appendFileSync(path, `${JSON.stringify(result)}
|
|
@@ -5776,7 +6000,7 @@ function createSession(opts = {}) {
|
|
|
5776
6000
|
const resolved = resolveEnv(opts.env);
|
|
5777
6001
|
const factory = opts.driverFactory ?? defaultFactory ?? missingFactory;
|
|
5778
6002
|
const out = resolve2(resolved.out);
|
|
5779
|
-
|
|
6003
|
+
mkdirSync3(out, { recursive: true });
|
|
5780
6004
|
const results = openResults(resolve2(out, "results.jsonl"));
|
|
5781
6005
|
const idle = new AbortController().signal;
|
|
5782
6006
|
let opened;
|
|
@@ -5874,6 +6098,16 @@ function createSession(opts = {}) {
|
|
|
5874
6098
|
note(`biometrics enroll did not take after ${ENROLL_TRIES} attempts`);
|
|
5875
6099
|
return driver;
|
|
5876
6100
|
}
|
|
6101
|
+
async function nativePrivateData() {
|
|
6102
|
+
const deps = opts.nativeLog ?? defaultNativeLog;
|
|
6103
|
+
if (deps === undefined || resolved.platform !== "ios" || resolved.deviceKind === "physical")
|
|
6104
|
+
return;
|
|
6105
|
+
if (process.env[NATIVE_PRIVATE_DATA_ENV] === "0")
|
|
6106
|
+
return;
|
|
6107
|
+
const problem = await enableNativePrivateData(resolved.udid, deps.exec);
|
|
6108
|
+
if (problem !== undefined)
|
|
6109
|
+
note(problem);
|
|
6110
|
+
}
|
|
5877
6111
|
const session = {
|
|
5878
6112
|
env: resolved,
|
|
5879
6113
|
out,
|
|
@@ -5906,7 +6140,10 @@ function createSession(opts = {}) {
|
|
|
5906
6140
|
throw new E2eError2("DRIVER", `${code}: ${message}`);
|
|
5907
6141
|
}
|
|
5908
6142
|
current = cacheObservations(traceDriver(result.data, { trace: () => attempt?.trace }));
|
|
5909
|
-
return reenroll(current)
|
|
6143
|
+
return reenroll(current).then(async (driver) => {
|
|
6144
|
+
await nativePrivateData();
|
|
6145
|
+
return driver;
|
|
6146
|
+
});
|
|
5910
6147
|
}, (cause) => {
|
|
5911
6148
|
opened = undefined;
|
|
5912
6149
|
throw new E2eError2("DRIVER", cause instanceof Error ? cause.message : String(cause));
|
|
@@ -6218,7 +6455,7 @@ function expandedState(el) {
|
|
|
6218
6455
|
return "collapsed";
|
|
6219
6456
|
return;
|
|
6220
6457
|
}
|
|
6221
|
-
function
|
|
6458
|
+
function join3(parts) {
|
|
6222
6459
|
return parts.filter((p) => !!p).join(", ");
|
|
6223
6460
|
}
|
|
6224
6461
|
function announceIos(el, opts) {
|
|
@@ -6244,7 +6481,7 @@ function announceIos(el, opts) {
|
|
|
6244
6481
|
if (!el.enabled || has(el, "not-enabled"))
|
|
6245
6482
|
state.push("dimmed");
|
|
6246
6483
|
const hint = opts.hints === false ? undefined : clean(el.a11y?.hint);
|
|
6247
|
-
return build(el, "ios", { label, value, role, state, hint },
|
|
6484
|
+
return build(el, "ios", { label, value, role, state, hint }, join3([label, value, role, ...state, hint]));
|
|
6248
6485
|
}
|
|
6249
6486
|
function announceAndroid(el, opts) {
|
|
6250
6487
|
const name = accessibleName(el, "android");
|
|
@@ -6265,7 +6502,7 @@ function announceAndroid(el, opts) {
|
|
|
6265
6502
|
const role = androidRoleWord(el);
|
|
6266
6503
|
const disabled = !el.enabled;
|
|
6267
6504
|
const hint = opts.hints === false ? undefined : clean(el.a11y?.hint);
|
|
6268
|
-
const text =
|
|
6505
|
+
const text = join3([...state, name, role, disabled ? "disabled" : undefined, hint]);
|
|
6269
6506
|
return build(el, "android", { label: name, role, state: disabled ? [...state, "disabled"] : state, hint }, text);
|
|
6270
6507
|
}
|
|
6271
6508
|
function build(el, platform, parts, text) {
|
|
@@ -7012,12 +7249,12 @@ var IOS_DEVICE_CAPABILITIES = {
|
|
|
7012
7249
|
};
|
|
7013
7250
|
|
|
7014
7251
|
// ../../packages/e2e/src/conditions/device-conditions.ts
|
|
7015
|
-
import { dirname as
|
|
7252
|
+
import { dirname as dirname6, resolve as resolve3 } from "path";
|
|
7016
7253
|
|
|
7017
7254
|
// ../../packages/core/src/conditions/camera-media.ts
|
|
7018
7255
|
import { createHash } from "crypto";
|
|
7019
|
-
import { closeSync, copyFileSync, existsSync as existsSync3, mkdirSync as
|
|
7020
|
-
import { join as
|
|
7256
|
+
import { closeSync, copyFileSync as copyFileSync2, existsSync as existsSync3, mkdirSync as mkdirSync4, openSync, readFileSync, readSync, rmSync } from "fs";
|
|
7257
|
+
import { join as join4 } from "path";
|
|
7021
7258
|
var SUPPORTED = "png, jpg, heic, mp4, mov";
|
|
7022
7259
|
var FTYP_BRANDS = {
|
|
7023
7260
|
heic: { kind: "image", ext: "heic" },
|
|
@@ -7063,7 +7300,7 @@ function sniffCameraMedia(path) {
|
|
|
7063
7300
|
};
|
|
7064
7301
|
}
|
|
7065
7302
|
function cameraFeedDir(wardenHome, udid) {
|
|
7066
|
-
return
|
|
7303
|
+
return join4(wardenHome, "camera", udid);
|
|
7067
7304
|
}
|
|
7068
7305
|
function stageCameraFeed(input) {
|
|
7069
7306
|
const sniffed = sniffCameraMedia(input.source);
|
|
@@ -7071,10 +7308,10 @@ function stageCameraFeed(input) {
|
|
|
7071
7308
|
return sniffed;
|
|
7072
7309
|
const hash = createHash("sha256").update(readFileSync(input.source)).digest("hex").slice(0, 12);
|
|
7073
7310
|
const dir = cameraFeedDir(input.wardenHome, input.udid);
|
|
7074
|
-
|
|
7075
|
-
const path =
|
|
7311
|
+
mkdirSync4(dir, { recursive: true });
|
|
7312
|
+
const path = join4(dir, `${input.facing}-${hash}.${sniffed.data.ext}`);
|
|
7076
7313
|
if (!existsSync3(path))
|
|
7077
|
-
|
|
7314
|
+
copyFileSync2(input.source, path);
|
|
7078
7315
|
return ok(sniffed.data.kind === "image" ? { kind: "image", path } : { kind: "video", path, loop: input.loop });
|
|
7079
7316
|
}
|
|
7080
7317
|
function clearCameraFeeds(wardenHome, udid) {
|
|
@@ -7084,8 +7321,8 @@ function clearCameraFeeds(wardenHome, udid) {
|
|
|
7084
7321
|
// ../../packages/core/src/store.ts
|
|
7085
7322
|
import { Database } from "bun:sqlite";
|
|
7086
7323
|
import { randomUUID } from "crypto";
|
|
7087
|
-
import { mkdirSync as
|
|
7088
|
-
import { dirname as
|
|
7324
|
+
import { mkdirSync as mkdirSync5 } from "fs";
|
|
7325
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
7089
7326
|
|
|
7090
7327
|
// ../../packages/core/src/lease-events.ts
|
|
7091
7328
|
var LEASE_EVENT_TYPES = [
|
|
@@ -7213,10 +7450,10 @@ function isPhysicalIosId(id) {
|
|
|
7213
7450
|
function wardenHome(env = process.env) {
|
|
7214
7451
|
if (env.WARDEN_HOME)
|
|
7215
7452
|
return env.WARDEN_HOME;
|
|
7216
|
-
return
|
|
7453
|
+
return join5(env.HOME ?? "~", ".warden");
|
|
7217
7454
|
}
|
|
7218
7455
|
function defaultDbPath(env = process.env) {
|
|
7219
|
-
return
|
|
7456
|
+
return join5(wardenHome(env), "warden.db");
|
|
7220
7457
|
}
|
|
7221
7458
|
var MIGRATIONS = [
|
|
7222
7459
|
`CREATE TABLE leases (
|
|
@@ -7738,7 +7975,7 @@ function migrate(db) {
|
|
|
7738
7975
|
}).immediate();
|
|
7739
7976
|
}
|
|
7740
7977
|
function openStore(path = defaultDbPath()) {
|
|
7741
|
-
|
|
7978
|
+
mkdirSync5(dirname4(path), { recursive: true });
|
|
7742
7979
|
const db = new Database(path, { create: true, strict: true });
|
|
7743
7980
|
db.exec("PRAGMA busy_timeout = 15000");
|
|
7744
7981
|
db.exec("PRAGMA journal_mode = WAL");
|
|
@@ -7749,8 +7986,8 @@ function openStore(path = defaultDbPath()) {
|
|
|
7749
7986
|
}
|
|
7750
7987
|
|
|
7751
7988
|
// ../../packages/e2e/src/runner/callsite.ts
|
|
7752
|
-
import { join as
|
|
7753
|
-
var OWN_FILES = new Set(["callsite.ts", "scope.ts", "test.ts", "attempt.ts"].map((name) =>
|
|
7989
|
+
import { join as join6 } from "path";
|
|
7990
|
+
var OWN_FILES = new Set(["callsite.ts", "scope.ts", "test.ts", "attempt.ts"].map((name) => join6(import.meta.dir, name)).concat(join6(import.meta.dir, "..", "index.ts")));
|
|
7754
7991
|
var FRAME = /(?:\(|\s)((?:file:\/\/)?\/[^\s()]+?):\d+(?::\d+)?\)?\s*$/;
|
|
7755
7992
|
function callerFile(stack = new Error().stack, extraOwn = () => false) {
|
|
7756
7993
|
for (const line of (stack ?? "").split(`
|
|
@@ -7767,13 +8004,13 @@ function callerFile(stack = new Error().stack, extraOwn = () => false) {
|
|
|
7767
8004
|
}
|
|
7768
8005
|
|
|
7769
8006
|
// ../../packages/e2e/src/conditions/condition-events.ts
|
|
7770
|
-
import { appendFileSync as appendFileSync2, mkdirSync as
|
|
7771
|
-
import { dirname as
|
|
8007
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync6 } from "fs";
|
|
8008
|
+
import { dirname as dirname5 } from "path";
|
|
7772
8009
|
function openConditionSink(path) {
|
|
7773
8010
|
let ready = false;
|
|
7774
8011
|
return (event) => {
|
|
7775
8012
|
if (!ready) {
|
|
7776
|
-
|
|
8013
|
+
mkdirSync6(dirname5(path), { recursive: true });
|
|
7777
8014
|
ready = true;
|
|
7778
8015
|
}
|
|
7779
8016
|
appendFileSync2(path, `${JSON.stringify(event)}
|
|
@@ -8120,7 +8357,7 @@ function locationOf(input) {
|
|
|
8120
8357
|
var PACKAGE_SRC = `${resolve3(import.meta.dir, "..")}/`;
|
|
8121
8358
|
function callingSpecDir() {
|
|
8122
8359
|
const file = callerFile(new Error().stack, (path) => path.startsWith(PACKAGE_SRC) && !path.endsWith(".test.ts"));
|
|
8123
|
-
return file === "unknown" ? undefined :
|
|
8360
|
+
return file === "unknown" ? undefined : dirname6(file);
|
|
8124
8361
|
}
|
|
8125
8362
|
var FACINGS = {
|
|
8126
8363
|
back: ["back"],
|
|
@@ -8641,30 +8878,96 @@ the app runs without the warden network dylib: declare \`conditions.network\` fo
|
|
|
8641
8878
|
}
|
|
8642
8879
|
}
|
|
8643
8880
|
const declared = baseline.network !== undefined || baseline.location !== undefined || baseline.clock !== undefined || baseline.permissions !== undefined || baseline.locale !== undefined || baseline.timezone !== undefined || baseline.a11y !== undefined || env.cameraFeeds !== undefined;
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8881
|
+
async function applyBaselinePermissions() {
|
|
8882
|
+
if (baseline.permissions === undefined)
|
|
8883
|
+
return;
|
|
8884
|
+
for (const [name, state] of Object.entries(baseline.permissions))
|
|
8885
|
+
permissionStates.set(name, state);
|
|
8886
|
+
await applyPermissions(baseline.permissions);
|
|
8887
|
+
}
|
|
8888
|
+
const baselineSteps = [
|
|
8889
|
+
applyBaselinePermissions,
|
|
8890
|
+
async () => {
|
|
8654
8891
|
if (baseline.timezone !== undefined)
|
|
8655
8892
|
await applyTimezone(baseline.timezone);
|
|
8893
|
+
},
|
|
8894
|
+
async () => {
|
|
8656
8895
|
if (baseline.locale !== undefined)
|
|
8657
8896
|
await applyLocale(baseline.locale);
|
|
8897
|
+
},
|
|
8898
|
+
async () => {
|
|
8658
8899
|
if (baseline.a11y !== undefined)
|
|
8659
8900
|
await applyA11y(a11yOpOf(baseline.a11y));
|
|
8901
|
+
},
|
|
8902
|
+
async () => {
|
|
8660
8903
|
if (baseline.clock !== undefined)
|
|
8661
8904
|
await applyClock(baseline.clock);
|
|
8905
|
+
},
|
|
8906
|
+
async () => {
|
|
8662
8907
|
if (baseline.location !== undefined)
|
|
8663
8908
|
await applyLocation(baseline.location);
|
|
8909
|
+
},
|
|
8910
|
+
async () => {
|
|
8664
8911
|
if (baseline.network !== undefined)
|
|
8665
8912
|
await applyNetwork(baseline.network, { relaunch: true });
|
|
8913
|
+
},
|
|
8914
|
+
async () => {
|
|
8666
8915
|
if (env.cameraFeeds !== undefined)
|
|
8667
8916
|
await applyCamera(baselineCamera());
|
|
8917
|
+
}
|
|
8918
|
+
];
|
|
8919
|
+
const teardownSteps = [
|
|
8920
|
+
{ dirty: () => networkDirty, run: resetNetwork },
|
|
8921
|
+
{
|
|
8922
|
+
dirty: () => locationDirty,
|
|
8923
|
+
run: async () => {
|
|
8924
|
+
const goal = baseline.location ?? { kind: "clear" };
|
|
8925
|
+
await applyLocation(goal);
|
|
8926
|
+
locationDirty = false;
|
|
8927
|
+
recorder?.settle("location", goal, goal.kind === "clear");
|
|
8928
|
+
}
|
|
8929
|
+
},
|
|
8930
|
+
{ dirty: () => clockDirty, run: clockApi.reset },
|
|
8931
|
+
{ dirty: () => permissionsDirty, run: () => permissionsApi.reset() },
|
|
8932
|
+
{
|
|
8933
|
+
dirty: () => localeDirty,
|
|
8934
|
+
run: async () => {
|
|
8935
|
+
await applyTimezone(baseline.timezone ?? null);
|
|
8936
|
+
await applyLocale(baseline.locale ?? null);
|
|
8937
|
+
localeDirty = false;
|
|
8938
|
+
}
|
|
8939
|
+
},
|
|
8940
|
+
{
|
|
8941
|
+
dirty: () => a11yDirty,
|
|
8942
|
+
run: async () => {
|
|
8943
|
+
await applyA11y(null);
|
|
8944
|
+
if (baseline.a11y !== undefined)
|
|
8945
|
+
await applyA11y(a11yOpOf(baseline.a11y));
|
|
8946
|
+
a11yDirty = false;
|
|
8947
|
+
}
|
|
8948
|
+
},
|
|
8949
|
+
{
|
|
8950
|
+
dirty: () => batteryDirty,
|
|
8951
|
+
run: async () => {
|
|
8952
|
+
await applyBattery(null);
|
|
8953
|
+
batteryDirty = false;
|
|
8954
|
+
}
|
|
8955
|
+
},
|
|
8956
|
+
{
|
|
8957
|
+
dirty: () => cameraDirty,
|
|
8958
|
+
run: async () => {
|
|
8959
|
+
await applyCamera(baselineCamera());
|
|
8960
|
+
cameraDirty = false;
|
|
8961
|
+
}
|
|
8962
|
+
}
|
|
8963
|
+
];
|
|
8964
|
+
const internals = {
|
|
8965
|
+
declared,
|
|
8966
|
+
dirty: () => networkDirty || locationDirty || clockDirty || permissionsDirty || localeDirty || a11yDirty || batteryDirty || cameraDirty || runs.size > 0,
|
|
8967
|
+
wantsInject: () => baseline.network !== undefined || baseline.clock !== undefined || currentNetwork.kind !== "online" || currentClock.kind !== "real",
|
|
8968
|
+
async applyBaseline() {
|
|
8969
|
+
for (const step of baselineSteps)
|
|
8970
|
+
await step();
|
|
8668
8971
|
cameraDirty = false;
|
|
8669
8972
|
networkDirty = false;
|
|
8670
8973
|
locationDirty = false;
|
|
@@ -8684,46 +8987,9 @@ the app runs without the warden network dylib: declare \`conditions.network\` fo
|
|
|
8684
8987
|
}
|
|
8685
8988
|
};
|
|
8686
8989
|
await attempt(stopRuns);
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
await attempt(async () => {
|
|
8691
|
-
const goal = baseline.location ?? { kind: "clear" };
|
|
8692
|
-
await applyLocation(goal);
|
|
8693
|
-
locationDirty = false;
|
|
8694
|
-
recorder?.settle("location", goal, goal.kind === "clear");
|
|
8695
|
-
});
|
|
8696
|
-
}
|
|
8697
|
-
if (clockDirty)
|
|
8698
|
-
await attempt(clockApi.reset);
|
|
8699
|
-
if (permissionsDirty)
|
|
8700
|
-
await attempt(() => permissionsApi.reset());
|
|
8701
|
-
if (localeDirty) {
|
|
8702
|
-
await attempt(async () => {
|
|
8703
|
-
await applyTimezone(baseline.timezone ?? null);
|
|
8704
|
-
await applyLocale(baseline.locale ?? null);
|
|
8705
|
-
localeDirty = false;
|
|
8706
|
-
});
|
|
8707
|
-
}
|
|
8708
|
-
if (a11yDirty) {
|
|
8709
|
-
await attempt(async () => {
|
|
8710
|
-
await applyA11y(null);
|
|
8711
|
-
if (baseline.a11y !== undefined)
|
|
8712
|
-
await applyA11y(a11yOpOf(baseline.a11y));
|
|
8713
|
-
a11yDirty = false;
|
|
8714
|
-
});
|
|
8715
|
-
}
|
|
8716
|
-
if (batteryDirty) {
|
|
8717
|
-
await attempt(async () => {
|
|
8718
|
-
await applyBattery(null);
|
|
8719
|
-
batteryDirty = false;
|
|
8720
|
-
});
|
|
8721
|
-
}
|
|
8722
|
-
if (cameraDirty) {
|
|
8723
|
-
await attempt(async () => {
|
|
8724
|
-
await applyCamera(baselineCamera());
|
|
8725
|
-
cameraDirty = false;
|
|
8726
|
-
});
|
|
8990
|
+
for (const step of teardownSteps) {
|
|
8991
|
+
if (step.dirty())
|
|
8992
|
+
await attempt(step.run);
|
|
8727
8993
|
}
|
|
8728
8994
|
if (errors.length > 0)
|
|
8729
8995
|
throw errors[0];
|
|
@@ -8753,8 +9019,8 @@ the app runs without the warden network dylib: declare \`conditions.network\` fo
|
|
|
8753
9019
|
}
|
|
8754
9020
|
|
|
8755
9021
|
// ../../packages/e2e/src/perf/device-perf.ts
|
|
8756
|
-
import { copyFileSync as
|
|
8757
|
-
import { join as
|
|
9022
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync7, writeFileSync as writeFileSync2 } from "fs";
|
|
9023
|
+
import { join as join7 } from "path";
|
|
8758
9024
|
|
|
8759
9025
|
// ../../packages/e2e/src/perf/budgets.ts
|
|
8760
9026
|
var BUDGET_KEYS = ["startupColdMs", "jankPct", "maxCommitMs", "p95CpuPct", "peakMemoryMb"];
|
|
@@ -8849,24 +9115,24 @@ function saveReport(deps, result, report, sessionId) {
|
|
|
8849
9115
|
const attempt = deps.attemptDir();
|
|
8850
9116
|
if (attempt === undefined)
|
|
8851
9117
|
return sessionReport;
|
|
8852
|
-
const out =
|
|
8853
|
-
|
|
9118
|
+
const out = join7(attempt, PERF_DIR);
|
|
9119
|
+
mkdirSync7(out, { recursive: true });
|
|
8854
9120
|
const sessionDir = typeof result.dir === "string" ? result.dir : undefined;
|
|
8855
9121
|
const write = (name, from, fallback) => {
|
|
8856
9122
|
if (from !== undefined && existsSync4(from))
|
|
8857
|
-
|
|
9123
|
+
copyFileSync3(from, join7(out, name));
|
|
8858
9124
|
else if (fallback !== undefined)
|
|
8859
|
-
|
|
9125
|
+
writeFileSync2(join7(out, name), fallback);
|
|
8860
9126
|
else
|
|
8861
9127
|
return;
|
|
8862
9128
|
deps.addFile?.(`${PERF_DIR}/${name}`);
|
|
8863
9129
|
};
|
|
8864
9130
|
write("report.json", sessionReport, `${JSON.stringify(report, null, 2)}
|
|
8865
9131
|
`);
|
|
8866
|
-
write("report.md", sessionDir === undefined ? undefined :
|
|
9132
|
+
write("report.md", sessionDir === undefined ? undefined : join7(sessionDir, "report.md"));
|
|
8867
9133
|
write("session.json", undefined, `${JSON.stringify({ sessionId, dir: sessionDir }, null, 2)}
|
|
8868
9134
|
`);
|
|
8869
|
-
return
|
|
9135
|
+
return join7(out, "report.json");
|
|
8870
9136
|
}
|
|
8871
9137
|
function createDevicePerf(deps) {
|
|
8872
9138
|
const run = async (sub, extra) => {
|
|
@@ -8938,7 +9204,7 @@ function spawnWarden(bin) {
|
|
|
8938
9204
|
|
|
8939
9205
|
// ../../packages/e2e/src/runner/artifacts.ts
|
|
8940
9206
|
import { createHash as createHash2 } from "crypto";
|
|
8941
|
-
import { basename, extname, join as
|
|
9207
|
+
import { basename, extname, join as join8, relative, sep } from "path";
|
|
8942
9208
|
var SLUG_MAX = 60;
|
|
8943
9209
|
function slug(text, fallback = "test") {
|
|
8944
9210
|
const slugged = text.normalize("NFKD").replace(/[\u0300-\u036F]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, SLUG_MAX).replace(/-+$/g, "");
|
|
@@ -8948,10 +9214,10 @@ function hash6(...parts) {
|
|
|
8948
9214
|
return createHash2("sha1").update(parts.join("\x00")).digest("hex").slice(0, 6);
|
|
8949
9215
|
}
|
|
8950
9216
|
function attemptDir(out, specId, title, hash) {
|
|
8951
|
-
return
|
|
9217
|
+
return join8(out, specId, `${slug(title.join(" "))}-${hash.slice(0, 6)}`);
|
|
8952
9218
|
}
|
|
8953
9219
|
function screenshotPath(dir, n, name) {
|
|
8954
|
-
return
|
|
9220
|
+
return join8(dir, "screenshots", `${String(n).padStart(3, "0")}-${slug(name, "screenshot")}.png`);
|
|
8955
9221
|
}
|
|
8956
9222
|
var SPEC_EXT = /\.e2e$/;
|
|
8957
9223
|
function specIdOf(file, specsDir) {
|
|
@@ -8967,123 +9233,6 @@ function specIdOf(file, specsDir) {
|
|
|
8967
9233
|
return slug(strip(file), "spec");
|
|
8968
9234
|
}
|
|
8969
9235
|
|
|
8970
|
-
// ../../packages/e2e/src/devtools/native-log.ts
|
|
8971
|
-
import { copyFileSync as copyFileSync3, mkdirSync as mkdirSync7, readdirSync, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
8972
|
-
import { homedir } from "os";
|
|
8973
|
-
import { dirname as dirname6, join as join8 } from "path";
|
|
8974
|
-
var NATIVE_LOG = "native.log";
|
|
8975
|
-
var DEFAULT_TIMEOUT_MS5 = 1e4;
|
|
8976
|
-
var SLACK_S = 5;
|
|
8977
|
-
var MAX_BYTES = 2000000;
|
|
8978
|
-
function realNativeFs() {
|
|
8979
|
-
return {
|
|
8980
|
-
listReports: (dir) => {
|
|
8981
|
-
try {
|
|
8982
|
-
return readdirSync(dir).map((name) => ({ name, mtimeMs: statSync(join8(dir, name)).mtimeMs }));
|
|
8983
|
-
} catch {
|
|
8984
|
-
return [];
|
|
8985
|
-
}
|
|
8986
|
-
},
|
|
8987
|
-
copy: (from, to) => {
|
|
8988
|
-
mkdirSync7(dirname6(to), { recursive: true });
|
|
8989
|
-
copyFileSync3(from, to);
|
|
8990
|
-
},
|
|
8991
|
-
write: (path, text) => {
|
|
8992
|
-
mkdirSync7(dirname6(path), { recursive: true });
|
|
8993
|
-
writeFileSync2(path, text);
|
|
8994
|
-
}
|
|
8995
|
-
};
|
|
8996
|
-
}
|
|
8997
|
-
function realNativeLogDeps(exec, adb) {
|
|
8998
|
-
return { exec, adb, fs: realNativeFs(), reportsDir: join8(homedir(), "Library", "Logs", "DiagnosticReports") };
|
|
8999
|
-
}
|
|
9000
|
-
function tail(text) {
|
|
9001
|
-
return text.length > MAX_BYTES ? text.slice(text.length - MAX_BYTES) : text;
|
|
9002
|
-
}
|
|
9003
|
-
function failed(what, res) {
|
|
9004
|
-
return `${what}: exit ${res.exitCode} ${res.stderr.trim().split(`
|
|
9005
|
-
`)[0] ?? ""}`.trim();
|
|
9006
|
-
}
|
|
9007
|
-
async function iosProcessName(target, exec, timeoutMs) {
|
|
9008
|
-
const container = await exec(["xcrun", "simctl", "get_app_container", target.udid, target.bundleId, "app"], {
|
|
9009
|
-
timeoutMs
|
|
9010
|
-
});
|
|
9011
|
-
const app = container.stdout.trim();
|
|
9012
|
-
if (container.exitCode !== 0 || !app)
|
|
9013
|
-
return { error: failed(`app container of ${target.bundleId}`, container) };
|
|
9014
|
-
const name = await exec(["plutil", "-extract", "CFBundleExecutable", "raw", "-o", "-", join8(app, "Info.plist")], {
|
|
9015
|
-
timeoutMs
|
|
9016
|
-
});
|
|
9017
|
-
const exe = name.stdout.trim();
|
|
9018
|
-
return name.exitCode === 0 && exe ? { exe } : { error: failed("CFBundleExecutable", name) };
|
|
9019
|
-
}
|
|
9020
|
-
async function iosNativeLog(target, deps, win, timeoutMs) {
|
|
9021
|
-
const capture = { files: [], problems: [] };
|
|
9022
|
-
const proc = await iosProcessName(target, deps.exec, timeoutMs);
|
|
9023
|
-
if (proc.error !== undefined || proc.exe === undefined) {
|
|
9024
|
-
capture.problems.push(`native log: ${proc.error ?? "unknown process"}`);
|
|
9025
|
-
return capture;
|
|
9026
|
-
}
|
|
9027
|
-
const seconds = Math.ceil((win.nowMs - win.sinceMs) / 1000) + SLACK_S;
|
|
9028
|
-
const show = await deps.exec([
|
|
9029
|
-
"xcrun",
|
|
9030
|
-
"simctl",
|
|
9031
|
-
"spawn",
|
|
9032
|
-
target.udid,
|
|
9033
|
-
"log",
|
|
9034
|
-
"show",
|
|
9035
|
-
"--style",
|
|
9036
|
-
"ndjson",
|
|
9037
|
-
"--last",
|
|
9038
|
-
`${seconds}s`,
|
|
9039
|
-
"--predicate",
|
|
9040
|
-
`process == "${proc.exe}"`
|
|
9041
|
-
], { timeoutMs });
|
|
9042
|
-
if (show.exitCode === 0) {
|
|
9043
|
-
deps.fs.write(join8(win.dir, NATIVE_LOG), tail(show.stdout));
|
|
9044
|
-
capture.files.push(NATIVE_LOG);
|
|
9045
|
-
} else {
|
|
9046
|
-
capture.problems.push(`native log: ${failed("log show", show)}`);
|
|
9047
|
-
}
|
|
9048
|
-
for (const report of deps.fs.listReports(deps.reportsDir)) {
|
|
9049
|
-
if (!report.name.startsWith(proc.exe) || !report.name.endsWith(".ips") || report.mtimeMs < win.sinceMs)
|
|
9050
|
-
continue;
|
|
9051
|
-
deps.fs.copy(join8(deps.reportsDir, report.name), join8(win.dir, report.name));
|
|
9052
|
-
capture.files.push(report.name);
|
|
9053
|
-
}
|
|
9054
|
-
return capture;
|
|
9055
|
-
}
|
|
9056
|
-
async function androidNativeLog(target, deps, win, timeoutMs) {
|
|
9057
|
-
const capture = { files: [], problems: [] };
|
|
9058
|
-
const adb = (...args) => deps.exec([deps.adb, "-s", target.serial, ...args], { timeoutMs });
|
|
9059
|
-
const pid = await adb("shell", "pidof", target.pkg);
|
|
9060
|
-
const pidArg = pid.exitCode === 0 && /^\d+/.test(pid.stdout.trim()) ? [`--pid=${pid.stdout.trim().split(/\s+/)[0]}`] : [];
|
|
9061
|
-
const since = ((win.sinceMs - SLACK_S * 1000) / 1000).toFixed(3);
|
|
9062
|
-
const main = await adb("logcat", "-d", "-v", "epoch", ...pidArg, "-T", since);
|
|
9063
|
-
const crash = await adb("logcat", "-d", "-b", "crash", "-v", "epoch");
|
|
9064
|
-
if (main.exitCode !== 0 && crash.exitCode !== 0) {
|
|
9065
|
-
capture.problems.push(`native log: ${failed("logcat", main)}`);
|
|
9066
|
-
return capture;
|
|
9067
|
-
}
|
|
9068
|
-
const sections = [
|
|
9069
|
-
main.exitCode === 0 ? main.stdout : "",
|
|
9070
|
-
crash.exitCode === 0 ? `--- crash buffer ---
|
|
9071
|
-
${crash.stdout}` : ""
|
|
9072
|
-
];
|
|
9073
|
-
deps.fs.write(join8(win.dir, NATIVE_LOG), tail(sections.filter(Boolean).join(`
|
|
9074
|
-
`)));
|
|
9075
|
-
capture.files.push(NATIVE_LOG);
|
|
9076
|
-
return capture;
|
|
9077
|
-
}
|
|
9078
|
-
async function captureNativeLog(target, deps, win) {
|
|
9079
|
-
const timeoutMs = win.timeoutMs ?? DEFAULT_TIMEOUT_MS5;
|
|
9080
|
-
try {
|
|
9081
|
-
return target.platform === "ios" ? await iosNativeLog(target, deps, win, timeoutMs) : await androidNativeLog(target, deps, win, timeoutMs);
|
|
9082
|
-
} catch (cause) {
|
|
9083
|
-
return { files: [], problems: [`native log: ${cause instanceof Error ? cause.message : String(cause)}`] };
|
|
9084
|
-
}
|
|
9085
|
-
}
|
|
9086
|
-
|
|
9087
9236
|
// ../../packages/e2e/src/runner/scope.ts
|
|
9088
9237
|
var BUN_TIMEOUT_MARGIN_MS2 = 30000;
|
|
9089
9238
|
var hookOwners = new WeakMap;
|
|
@@ -9157,7 +9306,7 @@ function registrationDefaults(env = process.env) {
|
|
|
9157
9306
|
const read = readEnv(env);
|
|
9158
9307
|
const parsed = read.success ? read.data : undefined;
|
|
9159
9308
|
return {
|
|
9160
|
-
timeoutMs: parsed?.timeoutMs ??
|
|
9309
|
+
timeoutMs: parsed?.timeoutMs ?? DEFAULT_TIMEOUT_MS5,
|
|
9161
9310
|
actionTimeoutMs: parsed?.actionTimeoutMs ?? DEFAULT_ACTION_TIMEOUT_MS,
|
|
9162
9311
|
assertionTimeoutMs: parsed?.assertionTimeoutMs ?? DEFAULT_ASSERTION_TIMEOUT_MS,
|
|
9163
9312
|
platform: parsed?.platform,
|
|
@@ -9174,6 +9323,6 @@ function onlyWasSeen() {
|
|
|
9174
9323
|
|
|
9175
9324
|
// ../../packages/e2e/src/version.ts
|
|
9176
9325
|
var WORKSPACE_VERSION = "0.0.0-workspace";
|
|
9177
|
-
var WARDEN_E2E_VERSION2 = "0.
|
|
9326
|
+
var WARDEN_E2E_VERSION2 = "0.12.0";
|
|
9178
9327
|
|
|
9179
|
-
export { E2eError2, registerA11yTarget, a11yTargetOf, canActOnElements, noteSpanDetail, addSpanDetail, canObserve, canDetectAlerts, settleDetailOf, DEFAULT_SETTLE_QUIET_MS, DEFAULT_SETTLE_TIMEOUT_MS, settleByHash, snapshotHash, ok, err, swipeVector, screenRect, fieldValue, PINCH_MS, ROTATE_MS, PATH_MS, centreOf, pinchRadius, rotateRadius, requireGesture, assertScale, assertDegrees, isInteractiveRole, resolveRole, normalizeText, matchesText, indexSnapshot, testIdQuery, textQuery, roleQuery, selectorExpression, renderSnapshot, renderHeader, resolve, locateByTestIdViaReact, isLocator, Locator, pickOne, textOf, scrollUntilVisible, bunExec, execError, driverError, driverErr, logEventSchema, fatalEventSchema, responseSchema, mapWireError, createLineSplitter, encodeRequest, bunSpawn, stdioTransport, socketTransport, createSimdClient, spawnSimd, connectSimd, isRecoverableLoss, CAMERA_FACINGS, CONDITION_AREAS, resolveNetwork, resolveTextSize, androidFontScale, ENV_NAMES, DEFAULT_ASSERTION_TIMEOUT_MS, readEnv, runStep, setDefaultHidRecovery, setDefaultNativeLog, setDefaultDriverFactory, hasDefaultDriverFactory, setDefaultFixtureFactory, hasDefaultFixtureFactory, attemptSession, getSession, accessibleName, announce, failing, formatIssues, toE2eError, settled, unwrap, parseUiadA11yEvents, parseInjectEvents, withA11yRead, renderA11yScreen, createDeviceA11y, IOS_DEVICE_CAPABILITIES, sniffCameraMedia, cameraFeedDir, clearCameraFeeds, isLeaseAlive, processAlive, describeOwner, isPhysicalIosId, wardenHome, defaultDbPath, ownerKey, openStore, callerFile, formatCoord, DEFAULT_SPEED_MPS, DEFAULT_INTERVAL_S, realTickerClock, startRouteTicker, startFlap, registerConditions, conditionsOf, conditionSinkFor, createDeviceConditions, parseBudgets, createDevicePerf, perfStartFor, spawnWarden, hash6, attemptDir, screenshotPath, specIdOf,
|
|
9328
|
+
export { E2eError2, registerA11yTarget, a11yTargetOf, canActOnElements, noteSpanDetail, addSpanDetail, canObserve, canDetectAlerts, settleDetailOf, DEFAULT_SETTLE_QUIET_MS, DEFAULT_SETTLE_TIMEOUT_MS, settleByHash, snapshotHash, ok, err, swipeVector, screenRect, fieldValue, PINCH_MS, ROTATE_MS, PATH_MS, centreOf, pinchRadius, rotateRadius, requireGesture, assertScale, assertDegrees, isInteractiveRole, resolveRole, normalizeText, matchesText, indexSnapshot, testIdQuery, textQuery, roleQuery, selectorExpression, renderSnapshot, renderHeader, resolve, locateByTestIdViaReact, isLocator, Locator, pickOne, textOf, scrollUntilVisible, formatNativeTail, realNativeLogDeps, captureNativeLog, bunExec, execError, driverError, driverErr, logEventSchema, fatalEventSchema, responseSchema, mapWireError, createLineSplitter, encodeRequest, bunSpawn, stdioTransport, socketTransport, createSimdClient, spawnSimd, connectSimd, isRecoverableLoss, CAMERA_FACINGS, CONDITION_AREAS, resolveNetwork, resolveTextSize, androidFontScale, ENV_NAMES, DEFAULT_ASSERTION_TIMEOUT_MS, readEnv, runStep, setDefaultHidRecovery, setDefaultNativeLog, setDefaultDriverFactory, hasDefaultDriverFactory, setDefaultFixtureFactory, hasDefaultFixtureFactory, attemptSession, getSession, accessibleName, announce, failing, formatIssues, toE2eError, settled, unwrap, parseUiadA11yEvents, parseInjectEvents, withA11yRead, renderA11yScreen, createDeviceA11y, IOS_DEVICE_CAPABILITIES, sniffCameraMedia, cameraFeedDir, clearCameraFeeds, isLeaseAlive, processAlive, describeOwner, isPhysicalIosId, wardenHome, defaultDbPath, ownerKey, openStore, callerFile, formatCoord, DEFAULT_SPEED_MPS, DEFAULT_INTERVAL_S, realTickerClock, startRouteTicker, startFlap, registerConditions, conditionsOf, conditionSinkFor, createDeviceConditions, parseBudgets, createDevicePerf, perfStartFor, spawnWarden, hash6, attemptDir, screenshotPath, specIdOf, BUN_TIMEOUT_MARGIN_MS2, ownHook, currentScope, createScope, runInScope, hooksFor, resolveUse, registrationDefaults, markOnly, onlyWasSeen, WORKSPACE_VERSION, WARDEN_E2E_VERSION2 };
|