@unrulysystems/rn-playwright-driver-runner 0.1.1 → 0.2.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/CHANGELOG.md +12 -0
- package/dist/cli.js +77 -20
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +77 -20
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +16 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -47,6 +47,10 @@ var DEFAULTS = {
|
|
|
47
47
|
androidTokenFileName: "rn-driver-touch-token"
|
|
48
48
|
};
|
|
49
49
|
var SECRET_PLACEHOLDER = "<token-file>";
|
|
50
|
+
var COMPANION_FAILURE_MARKERS = {
|
|
51
|
+
ios: ["** BUILD FAILED **", "** TEST FAILED **"],
|
|
52
|
+
android: ["INSTRUMENTATION_FAILED", "Process crashed"]
|
|
53
|
+
};
|
|
50
54
|
|
|
51
55
|
// src/plan/env.ts
|
|
52
56
|
function buildIosDriverEnv(resolved, metro, timeoutMs) {
|
|
@@ -266,7 +270,10 @@ function planAndroid(input) {
|
|
|
266
270
|
port: resolved.touchPort,
|
|
267
271
|
tokenFile: resolved.tokenFile,
|
|
268
272
|
timeoutMs: resolved.companionReadyTimeoutMs
|
|
269
|
-
}
|
|
273
|
+
},
|
|
274
|
+
// Abort early if `am instrument` reports the companion failed to start (crash / missing
|
|
275
|
+
// androidTest target) instead of waiting out the readiness budget.
|
|
276
|
+
failureMarkers: COMPANION_FAILURE_MARKERS.android
|
|
270
277
|
}
|
|
271
278
|
});
|
|
272
279
|
push(launchStep("android.launch-2", android, launch2Command));
|
|
@@ -597,7 +604,10 @@ function planIos(input) {
|
|
|
597
604
|
port: resolved.touchPort,
|
|
598
605
|
tokenFile: resolved.tokenFile,
|
|
599
606
|
timeoutMs: resolved.companionReadyTimeoutMs
|
|
600
|
-
}
|
|
607
|
+
},
|
|
608
|
+
// Abort early if `xcodebuild test` reports a build/test failure (it lingers "alive" after, so
|
|
609
|
+
// the 300s readiness budget would otherwise be burnt waiting for a companion that cannot bind).
|
|
610
|
+
failureMarkers: COMPANION_FAILURE_MARKERS.ios
|
|
601
611
|
}
|
|
602
612
|
});
|
|
603
613
|
if (isDevClient) {
|
|
@@ -853,8 +863,10 @@ function renderAction(action) {
|
|
|
853
863
|
return `write ${action.path}${action.mode ? ` (mode ${action.mode.toString(8)})` : ""}`;
|
|
854
864
|
case "free-port":
|
|
855
865
|
return `free-port ${action.port}`;
|
|
856
|
-
case "probe":
|
|
857
|
-
|
|
866
|
+
case "probe": {
|
|
867
|
+
const fastFail = action.failureMarkers?.length ? ` [fast-fail on: ${action.failureMarkers.join(", ")}]` : "";
|
|
868
|
+
return `probe ${renderProbe(action.probe)}${fastFail}`;
|
|
869
|
+
}
|
|
858
870
|
default: {
|
|
859
871
|
const _exhaustive = action;
|
|
860
872
|
throw new Error(`unhandled action: ${JSON.stringify(_exhaustive)}`);
|
|
@@ -900,6 +912,25 @@ function renderProbe(probe) {
|
|
|
900
912
|
}
|
|
901
913
|
}
|
|
902
914
|
|
|
915
|
+
// src/runner/probe-failure.ts
|
|
916
|
+
var ProbeFailure = class extends Error {
|
|
917
|
+
marker;
|
|
918
|
+
constructor(marker, detail) {
|
|
919
|
+
super(
|
|
920
|
+
`companion process reported a terminal failure ("${marker}") \u2014 aborting the readiness wait. The build/test failed; it will not become ready.${detail ? `
|
|
921
|
+
${detail}` : ""}`
|
|
922
|
+
);
|
|
923
|
+
this.name = "ProbeFailure";
|
|
924
|
+
this.marker = marker;
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
function findFailureMarker(log, markers) {
|
|
928
|
+
for (const marker of markers) {
|
|
929
|
+
if (log.includes(marker)) return marker;
|
|
930
|
+
}
|
|
931
|
+
return null;
|
|
932
|
+
}
|
|
933
|
+
|
|
903
934
|
// src/runner/execute.ts
|
|
904
935
|
var StageError = class extends Error {
|
|
905
936
|
stage;
|
|
@@ -967,22 +998,30 @@ async function runStep(step, runner, opts, processes, isAlive) {
|
|
|
967
998
|
case "probe": {
|
|
968
999
|
const key = processKeyForProbe(action.probe);
|
|
969
1000
|
const aliveFn = key === null ? () => true : () => isAlive(key);
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
remaining
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1001
|
+
const watch = key !== null && action.failureMarkers && action.failureMarkers.length > 0 ? { logPath: logPathFor(opts.logDir, key), failureMarkers: action.failureMarkers } : void 0;
|
|
1002
|
+
try {
|
|
1003
|
+
let ready = await runner.probe(action.probe, aliveFn, watch);
|
|
1004
|
+
let remaining = action.retry?.max ?? 0;
|
|
1005
|
+
while (!ready && remaining > 0) {
|
|
1006
|
+
remaining -= 1;
|
|
1007
|
+
if (action.retry) {
|
|
1008
|
+
runner.log(`retry ${step.id}: re-running launch (${remaining} attempt(s) left)`);
|
|
1009
|
+
await runner.exec(action.retry.command);
|
|
1010
|
+
}
|
|
1011
|
+
ready = await runner.probe(action.probe, aliveFn, watch);
|
|
977
1012
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1013
|
+
if (!ready) {
|
|
1014
|
+
throw new StageError(
|
|
1015
|
+
step.stage,
|
|
1016
|
+
step.id,
|
|
1017
|
+
`readiness timed out after ${action.probe.timeoutMs}ms`
|
|
1018
|
+
);
|
|
1019
|
+
}
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
if (error instanceof ProbeFailure) {
|
|
1022
|
+
throw new StageError(step.stage, step.id, error.message);
|
|
1023
|
+
}
|
|
1024
|
+
throw error;
|
|
986
1025
|
}
|
|
987
1026
|
return;
|
|
988
1027
|
}
|
|
@@ -1121,10 +1160,15 @@ var NodeProcessRunner = class {
|
|
|
1121
1160
|
}
|
|
1122
1161
|
if (pids.length > 0) await delay(1e3);
|
|
1123
1162
|
}
|
|
1124
|
-
probe(probe, isAlive) {
|
|
1163
|
+
probe(probe, isAlive, watch) {
|
|
1125
1164
|
const deadline = Date.now() + probe.timeoutMs;
|
|
1126
1165
|
const attempt = async () => {
|
|
1127
1166
|
for (; ; ) {
|
|
1167
|
+
if (watch) {
|
|
1168
|
+
const log = await readWatchedLog(watch.logPath);
|
|
1169
|
+
const marker = findFailureMarker(log, watch.failureMarkers);
|
|
1170
|
+
if (marker) throw new ProbeFailure(marker, lastLines(log));
|
|
1171
|
+
}
|
|
1128
1172
|
if (!isAlive()) return false;
|
|
1129
1173
|
if (await probeOnce(probe)) return true;
|
|
1130
1174
|
if (Date.now() >= deadline) return false;
|
|
@@ -1169,6 +1213,19 @@ function delay(ms) {
|
|
|
1169
1213
|
setTimeout(resolve, ms);
|
|
1170
1214
|
});
|
|
1171
1215
|
}
|
|
1216
|
+
async function readWatchedLog(path4) {
|
|
1217
|
+
try {
|
|
1218
|
+
return await readFile(path4, "utf8");
|
|
1219
|
+
} catch (error) {
|
|
1220
|
+
throw new Error(
|
|
1221
|
+
`cannot read companion log for fast-fail marker detection (${path4}): ${String(error)}`,
|
|
1222
|
+
{ cause: error }
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
function lastLines(text, n) {
|
|
1227
|
+
return text.split("\n").filter((line) => line.trim().length > 0).slice(-12).join("\n");
|
|
1228
|
+
}
|
|
1172
1229
|
async function probeOnce(probe) {
|
|
1173
1230
|
switch (probe.kind) {
|
|
1174
1231
|
case "metro-status":
|