@delacour/warden-e2e 0.4.0 → 0.6.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-3874jt2j.mjs → chunk-yb1hcjqm.mjs} +78 -10
- package/index.mjs +1 -1
- package/package.json +2 -2
- package/preload.mjs +3 -1
- package/types/core/src/affected/affected.schema.d.ts +185 -0
- package/types/core/src/batch/preset.schema.d.ts +59 -0
- package/types/core/src/builds/app-option.schema.d.ts +9 -1
- package/types/core/src/builds/builds.defaults.d.ts +62 -0
- package/types/core/src/builds/config.d.ts +122 -0
- package/types/core/src/builds/config.schema.d.ts +392 -0
- package/types/core/src/builds/define-config.d.ts +719 -0
- package/types/core/src/builds/kinds.d.ts +56 -0
- package/types/core/src/builds/native-ids.d.ts +14 -0
- package/types/core/src/builds/resolve.d.ts +26 -0
- package/types/core/src/duration.d.ts +5 -0
- package/types/core/src/ports.d.ts +76 -0
- package/types/core/src/sims/slim.profile.d.ts +54 -0
- package/types/e2e/src/devtools/facet.d.ts +2 -0
- package/types/e2e/src/devtools/logbox.d.ts +27 -0
- package/types/e2e/src/devtools/logbox.script.d.ts +17 -0
- package/types/e2e/src/screen/field.d.ts +5 -3
- package/types/e2e/src/screen/locator.d.ts +3 -2
- package/types/e2e/src/session.d.ts +4 -1
|
@@ -943,7 +943,7 @@ async function focusAndClear(driver, sleep, point, entry, method = "auto") {
|
|
|
943
943
|
return prepared;
|
|
944
944
|
return prepared.data.pending === "selection" ? pressKeys(driver, sleep, "Backspace", 1) : ok(undefined);
|
|
945
945
|
}
|
|
946
|
-
async function focusClearType(driver, sleep, point, entry, text, method = "auto", env = process.env, via = "
|
|
946
|
+
async function focusClearType(driver, sleep, point, entry, text, method = "auto", env = process.env, via = "type") {
|
|
947
947
|
const wantsSetText = method === "setText" || method === "auto" && setTextOptedIn(env);
|
|
948
948
|
if (wantsSetText && entry !== undefined && fieldContent(entry).kind === "text" && canSetText(driver)) {
|
|
949
949
|
const focused = await driver.tap(point);
|
|
@@ -2107,7 +2107,7 @@ function describeUntil(until) {
|
|
|
2107
2107
|
}
|
|
2108
2108
|
function fillViaOf(locator, via) {
|
|
2109
2109
|
if (via === undefined || via === "paste" || via === "type")
|
|
2110
|
-
return via ?? "
|
|
2110
|
+
return via ?? "type";
|
|
2111
2111
|
throw new E2eError2("INVALID_ARGUMENT", `${locator}: fill via must be "paste" or "type", got ${JSON.stringify(via)}`);
|
|
2112
2112
|
}
|
|
2113
2113
|
function viaFor(attempt, via) {
|
|
@@ -2685,6 +2685,71 @@ function createConsoleCapture(options = {}) {
|
|
|
2685
2685
|
};
|
|
2686
2686
|
}
|
|
2687
2687
|
|
|
2688
|
+
// ../../packages/e2e/src/devtools/logbox.script.ts
|
|
2689
|
+
var LOGBOX_SCRIPT = `function (g) {
|
|
2690
|
+
var req = g.__r;
|
|
2691
|
+
if (typeof req !== "function" || typeof req.getModules !== "function") return "no-require";
|
|
2692
|
+
var modules = req.getModules();
|
|
2693
|
+
if (!modules || typeof modules.forEach !== "function") return "no-require";
|
|
2694
|
+
var data = null;
|
|
2695
|
+
modules.forEach(function (mod) {
|
|
2696
|
+
if (data || !mod || typeof mod.verboseName !== "string" || !mod.isInitialized) return;
|
|
2697
|
+
var name = mod.verboseName.replace(/\\\\/g, "/");
|
|
2698
|
+
if (!/(^|\\/)react-native\\/Libraries\\/LogBox\\/Data\\/LogBoxData\\.js$/.test(name)) return;
|
|
2699
|
+
var exports = mod.publicModule && mod.publicModule.exports;
|
|
2700
|
+
if (exports && typeof exports.addIgnorePatterns === "function") data = exports;
|
|
2701
|
+
});
|
|
2702
|
+
if (!data) return "not-ready";
|
|
2703
|
+
data.addIgnorePatterns([/[\\s\\S]*/]);
|
|
2704
|
+
if (typeof data.setDisabled === "function") data.setDisabled(true);
|
|
2705
|
+
if (typeof data.setSelectedLog === "function") data.setSelectedLog(-1);
|
|
2706
|
+
return "off";
|
|
2707
|
+
}`;
|
|
2708
|
+
var LOGBOX_EXPRESSION = `(${LOGBOX_SCRIPT})(typeof globalThis !== "undefined" ? globalThis : (typeof global !== "undefined" ? global : this))`;
|
|
2709
|
+
|
|
2710
|
+
// ../../packages/e2e/src/devtools/logbox.ts
|
|
2711
|
+
var INTERVAL_MS = 250;
|
|
2712
|
+
var ATTEMPTS = 80;
|
|
2713
|
+
var timerSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
2714
|
+
function muteLogBox(session, options = {}) {
|
|
2715
|
+
const sleep = options.sleep ?? timerSleep;
|
|
2716
|
+
const intervalMs = options.intervalMs ?? INTERVAL_MS;
|
|
2717
|
+
const attempts = options.attempts ?? ATTEMPTS;
|
|
2718
|
+
let generation = 0;
|
|
2719
|
+
let stopped = false;
|
|
2720
|
+
async function tryOnce() {
|
|
2721
|
+
const reply = await session.evaluate(LOGBOX_EXPRESSION);
|
|
2722
|
+
if (!reply.success)
|
|
2723
|
+
return reply.error.message;
|
|
2724
|
+
return reply.data === "off" ? undefined : String(reply.data);
|
|
2725
|
+
}
|
|
2726
|
+
async function apply(mine) {
|
|
2727
|
+
const current = () => !stopped && mine === generation;
|
|
2728
|
+
let last = "no reply";
|
|
2729
|
+
for (let attempt = 1;attempt <= attempts && current(); attempt++) {
|
|
2730
|
+
last = await tryOnce();
|
|
2731
|
+
if (last === undefined)
|
|
2732
|
+
return;
|
|
2733
|
+
if (attempt < attempts)
|
|
2734
|
+
await sleep(intervalMs);
|
|
2735
|
+
}
|
|
2736
|
+
if (current())
|
|
2737
|
+
options.log?.(`devtools: LogBox left on (${last} after ${attempts} attempts)`);
|
|
2738
|
+
}
|
|
2739
|
+
const start = () => apply(++generation);
|
|
2740
|
+
const off = session.on("reconnected", () => {
|
|
2741
|
+
start();
|
|
2742
|
+
});
|
|
2743
|
+
const settled = start();
|
|
2744
|
+
return {
|
|
2745
|
+
settled,
|
|
2746
|
+
stop() {
|
|
2747
|
+
stopped = true;
|
|
2748
|
+
off();
|
|
2749
|
+
}
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2688
2753
|
// ../../packages/e2e/src/devtools/network.ts
|
|
2689
2754
|
import { z as z3 } from "zod";
|
|
2690
2755
|
|
|
@@ -2825,10 +2890,10 @@ var pageEntrySchema = z3.looseObject({
|
|
|
2825
2890
|
responseBodyTruncated: z3.boolean().optional(),
|
|
2826
2891
|
error: z3.string().optional()
|
|
2827
2892
|
});
|
|
2828
|
-
var
|
|
2893
|
+
var timerSleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
2829
2894
|
async function attachNetwork(session, options = {}) {
|
|
2830
2895
|
const ring = options.ring ?? DEFAULT_RING2;
|
|
2831
|
-
const sleep = options.sleep ??
|
|
2896
|
+
const sleep = options.sleep ?? timerSleep2;
|
|
2832
2897
|
const pollMs = options.pollMs ?? DEFAULT_POLL_MS2;
|
|
2833
2898
|
const installExpression = networkInstallExpression({
|
|
2834
2899
|
ring,
|
|
@@ -3074,13 +3139,13 @@ var RECONNECT_BUDGET_MS = 30000;
|
|
|
3074
3139
|
var RELOAD_WAIT_MS = 5000;
|
|
3075
3140
|
var HANDSHAKE_OPTIONAL_TIMEOUT_MS = 3000;
|
|
3076
3141
|
var RELOAD_EXPRESSION = '(function(){var g=globalThis;if(g.expo&&typeof g.expo.reloadAppAsync==="function"){setTimeout(function(){g.expo.reloadAppAsync("warden e2e reloadJs")},0);return "expo"}var m=g.nativeModuleProxy&&g.nativeModuleProxy.DevSettings;if(m&&typeof m.reload==="function"){setTimeout(function(){m.reload()},0);return "devsettings"}return false})()';
|
|
3077
|
-
var
|
|
3142
|
+
var timerSleep3 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3078
3143
|
async function connectDevtools(o) {
|
|
3079
3144
|
const { metroUrl } = o;
|
|
3080
3145
|
if (!metroUrl) {
|
|
3081
3146
|
return devtoolsErr("devtools_unavailable", "no Metro URL: release builds have no devtools (start a dev client)");
|
|
3082
3147
|
}
|
|
3083
|
-
const sleep = o.sleep ??
|
|
3148
|
+
const sleep = o.sleep ?? timerSleep3;
|
|
3084
3149
|
const log = o.log ?? (() => {
|
|
3085
3150
|
return;
|
|
3086
3151
|
});
|
|
@@ -3856,7 +3921,7 @@ var scriptResultSchema = z5.union([
|
|
|
3856
3921
|
z5.object({ screen: z5.string().optional(), components: z5.array(componentSchema), truncated: z5.boolean() })
|
|
3857
3922
|
]);
|
|
3858
3923
|
var bindingPayloadSchema2 = z5.object({ requestId: z5.string(), result: z5.unknown() });
|
|
3859
|
-
var
|
|
3924
|
+
var timerSleep4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3860
3925
|
var requestCounter = 0;
|
|
3861
3926
|
function scriptError(message) {
|
|
3862
3927
|
if (message === "no-hook")
|
|
@@ -3919,7 +3984,7 @@ async function viaBinding(session, expression, requestId, timeoutMs) {
|
|
|
3919
3984
|
}
|
|
3920
3985
|
async function fetchTree(session, options = {}, deps = {}) {
|
|
3921
3986
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
3922
|
-
const resolved = { sleep: deps.sleep ??
|
|
3987
|
+
const resolved = { sleep: deps.sleep ?? timerSleep4, now: deps.now ?? Date.now };
|
|
3923
3988
|
requestCounter += 1;
|
|
3924
3989
|
const requestId = `tree-${Date.now().toString(36)}-${requestCounter}`;
|
|
3925
3990
|
const config = {
|
|
@@ -3970,6 +4035,7 @@ async function openDevtoolsFacet(o) {
|
|
|
3970
4035
|
return attached;
|
|
3971
4036
|
}
|
|
3972
4037
|
const network = attached.data;
|
|
4038
|
+
const logbox = o.muteLogBox ? muteLogBox(session, { log: o.log }) : undefined;
|
|
3973
4039
|
return ok({
|
|
3974
4040
|
evaluate: (expression, options) => session.evaluate(expression, options),
|
|
3975
4041
|
reloadJs: () => session.reloadJs(),
|
|
@@ -3995,6 +4061,7 @@ async function openDevtoolsFacet(o) {
|
|
|
3995
4061
|
return ok(paths);
|
|
3996
4062
|
},
|
|
3997
4063
|
close() {
|
|
4064
|
+
logbox?.stop();
|
|
3998
4065
|
network.stop();
|
|
3999
4066
|
session.close();
|
|
4000
4067
|
}
|
|
@@ -5203,7 +5270,8 @@ var openDevtools = (env) => openDevtoolsFacet({
|
|
|
5203
5270
|
WebSocket,
|
|
5204
5271
|
timeoutMs: 5000,
|
|
5205
5272
|
log: (line) => process.stderr.write(`[devtools] ${line}
|
|
5206
|
-
`)
|
|
5273
|
+
`),
|
|
5274
|
+
muteLogBox: true
|
|
5207
5275
|
});
|
|
5208
5276
|
var SESSION_KEY = Symbol.for("@delacour/warden-e2e/session");
|
|
5209
5277
|
var slot = () => globalThis;
|
|
@@ -5950,6 +6018,6 @@ function onlyWasSeen() {
|
|
|
5950
6018
|
|
|
5951
6019
|
// ../../packages/e2e/src/version.ts
|
|
5952
6020
|
var WORKSPACE_VERSION = "0.0.0-workspace";
|
|
5953
|
-
var WARDEN_E2E_VERSION2 = "0.
|
|
6021
|
+
var WARDEN_E2E_VERSION2 = "0.6.0";
|
|
5954
6022
|
|
|
5955
6023
|
export { E2eError2, 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, encodeRequest, bunSpawn, stdioTransport, spawnSimd, connectSimd, isHidLost, ENV_NAMES, DEFAULT_ASSERTION_TIMEOUT_MS, readEnv, runStep, setDefaultHidRecovery, setDefaultNativeLog, setDefaultDriverFactory, hasDefaultDriverFactory, setDefaultFixtureFactory, hasDefaultFixtureFactory, attemptSession, getSession, parseBudgets, createDevicePerf, perfStartFor, spawnWarden, hash6, attemptDir, screenshotPath, specIdOf, realNativeLogDeps, captureNativeLog, callerFile, BUN_TIMEOUT_MARGIN_MS2, ownHook, currentScope, createScope, runInScope, hooksFor, resolveUse, registrationDefaults, markOnly, onlyWasSeen, WORKSPACE_VERSION, WARDEN_E2E_VERSION2 };
|
package/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delacour/warden-e2e",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript spec API for `warden e2e`: test, expect, screen, device, app",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"LICENSE"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@delacour/warden": "0.
|
|
40
|
+
"@delacour/warden": "0.6.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"zod": "^4.4.3"
|
package/preload.mjs
CHANGED
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
onlyWasSeen,
|
|
69
69
|
WORKSPACE_VERSION,
|
|
70
70
|
WARDEN_E2E_VERSION2
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-yb1hcjqm.mjs";
|
|
72
72
|
|
|
73
73
|
// ../../packages/e2e/src/preload.ts
|
|
74
74
|
import { afterAll, setDefaultTimeout } from "bun:test";
|
|
@@ -3983,6 +3983,8 @@ function createApp({ session, driver, env, log = stderrLog2, clock = systemClock
|
|
|
3983
3983
|
if (options.env !== undefined)
|
|
3984
3984
|
opts.env = options.env;
|
|
3985
3985
|
await unwrap(() => driver.app.launch(bundleId, opts), `launch ${bundleId}`, session.signal);
|
|
3986
|
+
if (env.metroUrl !== undefined)
|
|
3987
|
+
session.devtools?.();
|
|
3986
3988
|
if (options.url !== undefined) {
|
|
3987
3989
|
const url = options.url;
|
|
3988
3990
|
await unwrap(() => driver.app.openUrl(url), `open ${url}`, session.signal);
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { slimConfigSchema } from "../batch/preset.schema";
|
|
3
|
+
/** `e2e.<suite>.specs.<id|glob>`: what a spec covers and whether it gates. */
|
|
4
|
+
export declare const e2eSpecEntrySchema: z.ZodObject<{
|
|
5
|
+
entries: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
6
|
+
paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
7
|
+
platforms: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
8
|
+
ios: "ios";
|
|
9
|
+
android: "android";
|
|
10
|
+
}>>>;
|
|
11
|
+
maxDepth: z.ZodOptional<z.ZodNumber>;
|
|
12
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
/** How a suite's spec processes are laid out: one per device running its share of the specs, or one per spec. */
|
|
15
|
+
export type E2eIsolation = "device" | "spec";
|
|
16
|
+
type RunSettings = {
|
|
17
|
+
isolate?: E2eIsolation | undefined;
|
|
18
|
+
passes: number;
|
|
19
|
+
count?: number | undefined;
|
|
20
|
+
profile?: string | undefined;
|
|
21
|
+
devices?: Array<{
|
|
22
|
+
profile: string;
|
|
23
|
+
default: boolean;
|
|
24
|
+
}> | undefined;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The isolation a suite runs with: what it asked for (`isolate`), else one
|
|
28
|
+
* process per device, except that `passes` > 1 needs a process per spec (a spec's passes are
|
|
29
|
+
* re-runs of that spec).
|
|
30
|
+
*/
|
|
31
|
+
export declare function suiteIsolation(suite: Pick<RunSettings, "isolate" | "passes">): E2eIsolation;
|
|
32
|
+
/** `e2e.<suite>.metro`: warden starts one Metro for the run and points the dev client at it. */
|
|
33
|
+
export declare const e2eMetroSchema: z.ZodObject<{
|
|
34
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
35
|
+
port: z.ZodDefault<z.ZodString>;
|
|
36
|
+
launchArgs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
37
|
+
open: z.ZodDefault<z.ZodBoolean>;
|
|
38
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
39
|
+
prewarm: z.ZodDefault<z.ZodBoolean>;
|
|
40
|
+
readyTimeout: z.ZodDefault<z.ZodString>;
|
|
41
|
+
}, z.core.$strict>;
|
|
42
|
+
/** `e2e.<suite>.devices[]`: one leg of the run, with its own device pool. */
|
|
43
|
+
export declare const e2eDeviceLegSchema: z.ZodObject<{
|
|
44
|
+
profile: z.ZodString;
|
|
45
|
+
count: z.ZodDefault<z.ZodNumber>;
|
|
46
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
47
|
+
default: z.ZodDefault<z.ZodBoolean>;
|
|
48
|
+
}, z.core.$strict>;
|
|
49
|
+
/** `perf` (top level, or per `e2e.<suite>`): ceilings `device.perf.stop()` holds the report to. Each is lower-is-better. */
|
|
50
|
+
export declare const perfConfigSchema: z.ZodObject<{
|
|
51
|
+
budgets: z.ZodOptional<z.ZodObject<{
|
|
52
|
+
startupColdMs: z.ZodOptional<z.ZodNumber>;
|
|
53
|
+
jankPct: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
maxCommitMs: z.ZodOptional<z.ZodNumber>;
|
|
55
|
+
p95CpuPct: z.ZodOptional<z.ZodNumber>;
|
|
56
|
+
peakMemoryMb: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
}, z.core.$strict>>;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
/** `e2e.<suite>.spec`: how warden runs the `*.e2e.ts` specs (`bun test` + `@delacour/warden-e2e`). */
|
|
60
|
+
export declare const e2eSpecSchema: z.ZodObject<{
|
|
61
|
+
bundleId: z.ZodOptional<z.ZodString>;
|
|
62
|
+
launchArgs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
63
|
+
timeout: z.ZodOptional<z.ZodString>;
|
|
64
|
+
actionTimeout: z.ZodOptional<z.ZodString>;
|
|
65
|
+
assertionTimeout: z.ZodOptional<z.ZodString>;
|
|
66
|
+
}, z.core.$strict>;
|
|
67
|
+
/**
|
|
68
|
+
* `e2e.<suite>` in `warden.config.ts`: specs under `specsDir`, how they map to source, how to run one.
|
|
69
|
+
* Paths and globs are relative to the config file's directory.
|
|
70
|
+
*/
|
|
71
|
+
export declare const e2eSuiteSchema: z.ZodObject<{
|
|
72
|
+
project: z.ZodOptional<z.ZodString>;
|
|
73
|
+
specsDir: z.ZodString;
|
|
74
|
+
spec: z.ZodOptional<z.ZodObject<{
|
|
75
|
+
bundleId: z.ZodOptional<z.ZodString>;
|
|
76
|
+
launchArgs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
77
|
+
timeout: z.ZodOptional<z.ZodString>;
|
|
78
|
+
actionTimeout: z.ZodOptional<z.ZodString>;
|
|
79
|
+
assertionTimeout: z.ZodOptional<z.ZodString>;
|
|
80
|
+
}, z.core.$strict>>;
|
|
81
|
+
isolate: z.ZodOptional<z.ZodEnum<{
|
|
82
|
+
device: "device";
|
|
83
|
+
spec: "spec";
|
|
84
|
+
}>>;
|
|
85
|
+
shutdown: z.ZodOptional<z.ZodEnum<{
|
|
86
|
+
idle: "idle";
|
|
87
|
+
always: "always";
|
|
88
|
+
}>>;
|
|
89
|
+
jobTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
90
|
+
devices: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
91
|
+
profile: z.ZodString;
|
|
92
|
+
count: z.ZodDefault<z.ZodNumber>;
|
|
93
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
94
|
+
default: z.ZodDefault<z.ZodBoolean>;
|
|
95
|
+
}, z.core.$strict>>>;
|
|
96
|
+
metro: z.ZodOptional<z.ZodObject<{
|
|
97
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
port: z.ZodDefault<z.ZodString>;
|
|
99
|
+
launchArgs: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
100
|
+
open: z.ZodDefault<z.ZodBoolean>;
|
|
101
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
102
|
+
prewarm: z.ZodDefault<z.ZodBoolean>;
|
|
103
|
+
readyTimeout: z.ZodDefault<z.ZodString>;
|
|
104
|
+
}, z.core.$strict>>;
|
|
105
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
106
|
+
routerRoot: z.ZodOptional<z.ZodString>;
|
|
107
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
108
|
+
ios: "ios";
|
|
109
|
+
android: "android";
|
|
110
|
+
}>>;
|
|
111
|
+
base: z.ZodDefault<z.ZodString>;
|
|
112
|
+
maxDepth: z.ZodOptional<z.ZodNumber>;
|
|
113
|
+
runAll: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
114
|
+
ignore: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
115
|
+
always: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
116
|
+
include: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
117
|
+
exclude: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
118
|
+
scope: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
119
|
+
unmatched: z.ZodDefault<z.ZodEnum<{
|
|
120
|
+
skip: "skip";
|
|
121
|
+
"run-all": "run-all";
|
|
122
|
+
}>>;
|
|
123
|
+
unmapped: z.ZodDefault<z.ZodEnum<{
|
|
124
|
+
run: "run";
|
|
125
|
+
skip: "skip";
|
|
126
|
+
}>>;
|
|
127
|
+
passes: z.ZodDefault<z.ZodNumber>;
|
|
128
|
+
retry: z.ZodDefault<z.ZodNumber>;
|
|
129
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
130
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
131
|
+
app: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
132
|
+
installMode: z.ZodOptional<z.ZodEnum<{
|
|
133
|
+
clean: "clean";
|
|
134
|
+
reinstall: "reinstall";
|
|
135
|
+
}>>;
|
|
136
|
+
resetKeychain: z.ZodOptional<z.ZodBoolean>;
|
|
137
|
+
clean: z.ZodOptional<z.ZodBoolean>;
|
|
138
|
+
variant: z.ZodOptional<z.ZodString>;
|
|
139
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
140
|
+
release: "release";
|
|
141
|
+
dev: "dev";
|
|
142
|
+
simulator: "simulator";
|
|
143
|
+
}>>;
|
|
144
|
+
}, z.core.$strict>]>>;
|
|
145
|
+
ports: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
146
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
147
|
+
serve: z.ZodOptional<z.ZodString>;
|
|
148
|
+
serveReady: z.ZodOptional<z.ZodString>;
|
|
149
|
+
serveTimeout: z.ZodOptional<z.ZodString>;
|
|
150
|
+
setup: z.ZodOptional<z.ZodString>;
|
|
151
|
+
slim: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
152
|
+
except: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
153
|
+
keep: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
154
|
+
}, z.core.$strict>]>>;
|
|
155
|
+
warmRunners: z.ZodOptional<z.ZodUndefined>;
|
|
156
|
+
warmDrivers: z.ZodOptional<z.ZodBoolean>;
|
|
157
|
+
headless: z.ZodOptional<z.ZodBoolean>;
|
|
158
|
+
perf: z.ZodOptional<z.ZodObject<{
|
|
159
|
+
budgets: z.ZodOptional<z.ZodObject<{
|
|
160
|
+
startupColdMs: z.ZodOptional<z.ZodNumber>;
|
|
161
|
+
jankPct: z.ZodOptional<z.ZodNumber>;
|
|
162
|
+
maxCommitMs: z.ZodOptional<z.ZodNumber>;
|
|
163
|
+
p95CpuPct: z.ZodOptional<z.ZodNumber>;
|
|
164
|
+
peakMemoryMb: z.ZodOptional<z.ZodNumber>;
|
|
165
|
+
}, z.core.$strict>>;
|
|
166
|
+
}, z.core.$strict>>;
|
|
167
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
168
|
+
specs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
169
|
+
entries: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
170
|
+
paths: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
171
|
+
platforms: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
172
|
+
ios: "ios";
|
|
173
|
+
android: "android";
|
|
174
|
+
}>>>;
|
|
175
|
+
maxDepth: z.ZodOptional<z.ZodNumber>;
|
|
176
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
177
|
+
}, z.core.$strict>>>;
|
|
178
|
+
}, z.core.$strict>;
|
|
179
|
+
export type E2eSpecConfig = z.infer<typeof e2eSpecSchema>;
|
|
180
|
+
export type E2eMetroConfig = z.infer<typeof e2eMetroSchema>;
|
|
181
|
+
export type E2eDeviceLeg = z.infer<typeof e2eDeviceLegSchema>;
|
|
182
|
+
export type E2eSpecEntryConfig = z.infer<typeof e2eSpecEntrySchema>;
|
|
183
|
+
export type E2eSlimConfig = z.infer<typeof slimConfigSchema>;
|
|
184
|
+
export type E2eSuiteConfig = z.infer<typeof e2eSuiteSchema>;
|
|
185
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** `slim`: on/off, or the categories (`except`, ids) and single labels (`keep`) to leave running. */
|
|
3
|
+
export declare const slimConfigSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
4
|
+
except: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
5
|
+
keep: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
6
|
+
}, z.core.$strict>]>;
|
|
7
|
+
export declare const duration: z.ZodString;
|
|
8
|
+
export declare const portSpec: z.ZodString;
|
|
9
|
+
/** `batches.<name>` in `warden.config.ts`: a saved `warden batch` invocation. */
|
|
10
|
+
export declare const batchPresetSchema: z.ZodObject<{
|
|
11
|
+
project: z.ZodOptional<z.ZodString>;
|
|
12
|
+
platform: z.ZodEnum<{
|
|
13
|
+
ios: "ios";
|
|
14
|
+
android: "android";
|
|
15
|
+
}>;
|
|
16
|
+
count: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
19
|
+
runtime: z.ZodOptional<z.ZodString>;
|
|
20
|
+
label: z.ZodOptional<z.ZodString>;
|
|
21
|
+
ttl: z.ZodOptional<z.ZodString>;
|
|
22
|
+
wait: z.ZodOptional<z.ZodString>;
|
|
23
|
+
ports: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
24
|
+
app: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
25
|
+
installMode: z.ZodOptional<z.ZodEnum<{
|
|
26
|
+
clean: "clean";
|
|
27
|
+
reinstall: "reinstall";
|
|
28
|
+
}>>;
|
|
29
|
+
resetKeychain: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
clean: z.ZodOptional<z.ZodBoolean>;
|
|
31
|
+
variant: z.ZodOptional<z.ZodString>;
|
|
32
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
33
|
+
release: "release";
|
|
34
|
+
dev: "dev";
|
|
35
|
+
simulator: "simulator";
|
|
36
|
+
}>>;
|
|
37
|
+
}, z.core.$strict>]>>;
|
|
38
|
+
headless: z.ZodOptional<z.ZodBoolean>;
|
|
39
|
+
slim: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
40
|
+
except: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
41
|
+
keep: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
42
|
+
}, z.core.$strict>]>>;
|
|
43
|
+
retry: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
passes: z.ZodOptional<z.ZodNumber>;
|
|
45
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
46
|
+
serve: z.ZodOptional<z.ZodString>;
|
|
47
|
+
serveReady: z.ZodOptional<z.ZodString>;
|
|
48
|
+
serveTimeout: z.ZodOptional<z.ZodString>;
|
|
49
|
+
jobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
jobsFrom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
51
|
+
command: z.ZodString;
|
|
52
|
+
}, z.core.$strict>]>>;
|
|
53
|
+
record: z.ZodOptional<z.ZodString>;
|
|
54
|
+
logs: z.ZodOptional<z.ZodString>;
|
|
55
|
+
cmd: z.ZodArray<z.ZodString>;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
export type BatchPresetConfig = z.infer<typeof batchPresetSchema>;
|
|
58
|
+
/** Preset names that would shadow the platform operand of `warden batch`. */
|
|
59
|
+
export declare const RESERVED_PRESET_NAMES: readonly string[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { type BuildKind } from "./kinds";
|
|
2
3
|
/**
|
|
3
4
|
* What to do with the app's installed state before a run:
|
|
4
5
|
* - unset: install only when the device lacks this build; a different build is installed over the old one.
|
|
@@ -14,7 +15,8 @@ export type InstallMode = z.infer<typeof installModeSchema>;
|
|
|
14
15
|
* `app` on a batch preset / e2e suite: `true` installs the project's app on every device first;
|
|
15
16
|
* `{ installMode }` also resets the installed app (see {@link InstallMode}); `{ resetKeychain: true }`
|
|
16
17
|
* (needs `installMode`) also resets the iOS simulator's keychain;
|
|
17
|
-
* `{ variant }` installs that `projects[].variants` build instead of the project's default one
|
|
18
|
+
* `{ variant }` installs that `projects[].variants` build instead of the project's default one;
|
|
19
|
+
* `{ kind }` installs that build kind (`dev` | `simulator` | `release`) instead (not together with `variant`).
|
|
18
20
|
* `{ clean: true }` is the deprecated spelling of `{ installMode: "reinstall" }`.
|
|
19
21
|
*/
|
|
20
22
|
export declare const appOptionSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
@@ -25,6 +27,11 @@ export declare const appOptionSchema: z.ZodUnion<readonly [z.ZodBoolean, z.ZodOb
|
|
|
25
27
|
resetKeychain: z.ZodOptional<z.ZodBoolean>;
|
|
26
28
|
clean: z.ZodOptional<z.ZodBoolean>;
|
|
27
29
|
variant: z.ZodOptional<z.ZodString>;
|
|
30
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
31
|
+
release: "release";
|
|
32
|
+
dev: "dev";
|
|
33
|
+
simulator: "simulator";
|
|
34
|
+
}>>;
|
|
28
35
|
}, z.core.$strict>]>;
|
|
29
36
|
export type AppOption = z.infer<typeof appOptionSchema>;
|
|
30
37
|
export type AppSwitches = {
|
|
@@ -32,6 +39,7 @@ export type AppSwitches = {
|
|
|
32
39
|
installMode?: InstallMode;
|
|
33
40
|
resetKeychain?: true;
|
|
34
41
|
variant?: string;
|
|
42
|
+
kind?: BuildKind;
|
|
35
43
|
};
|
|
36
44
|
/** The switches `app` stands for. An object means install (`app: {}` = `app: true`). */
|
|
37
45
|
export declare function appSwitches(app: AppOption | undefined): AppSwitches;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Platform } from "../types";
|
|
2
|
+
import type { AppFramework } from "./native-ids";
|
|
3
|
+
/** EAS build profile searched when the project config names none. */
|
|
4
|
+
export declare const DEFAULT_EAS_PROFILE = "development-simulator";
|
|
5
|
+
/** Xcode / Gradle build configuration the local build produces (`build.configuration`). */
|
|
6
|
+
export type BuildConfiguration = "Debug" | "Release";
|
|
7
|
+
/**
|
|
8
|
+
* Makes a fresh (CNG) checkout buildable: `expo run:ios --no-install` skips CocoaPods, so generate
|
|
9
|
+
* `ios/` when it has no Podfile and run `pod install` when the Pods sandbox is missing or out of sync
|
|
10
|
+
* with `Podfile.lock` (the check Xcode's own build phase makes). A no-op on a prepared project.
|
|
11
|
+
*/
|
|
12
|
+
export declare const IOS_NATIVE_PREPARE: string;
|
|
13
|
+
/** Local build command (run in the project root) when `build.<platform>` is not configured. */
|
|
14
|
+
export declare function defaultBuildCommand(platform: Platform, configuration: BuildConfiguration, framework?: AppFramework): string;
|
|
15
|
+
/** Android twin of `IOS_NATIVE_PREPARE`: generate `android/` when a CNG checkout has none. */
|
|
16
|
+
export declare const ANDROID_NATIVE_PREPARE = "{ [ -f android/gradlew ] || bunx expo prebuild --platform android --no-install; }";
|
|
17
|
+
/**
|
|
18
|
+
* Local build command of the `simulator` kind: the Release configuration for a simulator / emulator; a repack swaps the
|
|
19
|
+
* JS in. iOS: Xcode's bundling phase is skipped with `SKIP_BUNDLING=1`. Android: plain `assembleRelease`. Excluding
|
|
20
|
+
* `createBundleReleaseJsAndAssets` (`-x`) fails on RN 0.86 / AGP 9 ("Querying the mapped value ... before task ... has
|
|
21
|
+
* completed"), and the bundler's `drawable-*` / `raw` images are compiled into the APK's resource table by that task:
|
|
22
|
+
* without them the Android repack finds no image in the base and always falls back to a full build.
|
|
23
|
+
*/
|
|
24
|
+
export declare function simulatorBuildCommand(platform: Platform, framework?: AppFramework): string;
|
|
25
|
+
/**
|
|
26
|
+
* What a kind's JS key (and a `release` kind's build key) covers when `kinds.<kind>.jsInputs` is not set: every file git
|
|
27
|
+
* tracks (or would) under the project root except the native projects and dependencies. A monorepo workspace package the
|
|
28
|
+
* bundle embeds is not under the root: list it (`../../packages/ui/src/**`) in `jsInputs`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const DEFAULT_JS_INPUTS: readonly string[];
|
|
31
|
+
/** The Debug defaults. */
|
|
32
|
+
export declare const DEFAULT_BUILD_COMMAND: Record<Platform, string>;
|
|
33
|
+
/** `warden prune` default budget. */
|
|
34
|
+
export declare const DEFAULT_MAX_CACHE_SIZE = "20G";
|
|
35
|
+
/** EAS poll interval while a build for the hash is in flight. */
|
|
36
|
+
export declare const EAS_POLL_MS = 30000;
|
|
37
|
+
/** Give up waiting on EAS after this long (then fall through to a local build). */
|
|
38
|
+
export declare const EAS_TIMEOUT_MS: number;
|
|
39
|
+
/** With `eas.trigger`, wait this long for a build to appear before triggering the workflow. */
|
|
40
|
+
export declare const EAS_TRIGGER_GRACE_MS: number;
|
|
41
|
+
/** Local native build timeout. */
|
|
42
|
+
export declare const LOCAL_BUILD_TIMEOUT_MS: number;
|
|
43
|
+
/** Fingerprint command timeout. */
|
|
44
|
+
export declare const FINGERPRINT_TIMEOUT_MS: number;
|
|
45
|
+
/** Build-lock lease ttl; the lease also carries the holder's pid so it lives as long as the process. */
|
|
46
|
+
export declare const BUILD_LOCK_TTL_MS: number;
|
|
47
|
+
/** How long a resolver waits for another process's build/download of the same hash. */
|
|
48
|
+
export declare const BUILD_LOCK_WAIT_MS: number;
|
|
49
|
+
export declare const BUILD_LOCK_POLL_MS = 2000;
|
|
50
|
+
/**
|
|
51
|
+
* Pre-warden cache roots (`<dir>/<hash>/*.app|*.apk`) by project name, used when the project config
|
|
52
|
+
* sets no `cacheDirs`. Builds found there are copied into the warden cache on first use.
|
|
53
|
+
*/
|
|
54
|
+
export declare const LEGACY_CACHE_DIRS: Readonly<Record<string, readonly string[]>>;
|
|
55
|
+
/** ccache sloppiness for Xcode/clang builds: lets worktrees with different mtimes/PCH state still hit. */
|
|
56
|
+
export declare const CCACHE_SLOPPINESS = "clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros";
|
|
57
|
+
/** Subdirectory of WARDEN_HOME holding the shared ccache. */
|
|
58
|
+
export declare const CCACHE_DIR_NAME = "ccache";
|
|
59
|
+
/** First Xcode major with compilation caching (`COMPILATION_CACHE_ENABLE_CACHING`). */
|
|
60
|
+
export declare const XCODE_COMPILATION_CACHE_MIN_MAJOR = 26;
|
|
61
|
+
/** Timeout for the quick `git` / `xcodebuild -version` probes before a build. */
|
|
62
|
+
export declare const PROBE_TIMEOUT_MS = 10000;
|