@unrulysystems/rn-playwright-driver-runner 0.1.0 → 0.1.1

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/dist/index.d.mts CHANGED
@@ -90,6 +90,8 @@ interface AndroidConfig {
90
90
  packageName: string;
91
91
  /** Launch activity, e.g. `.MainActivity`. */
92
92
  activity: string;
93
+ /** App URL scheme used for Expo dev-client deep links, e.g. `myapp`. */
94
+ scheme?: string;
93
95
  /** Gradle tasks that build the app + androidTest APKs. */
94
96
  gradleTasks?: string[];
95
97
  /** Built app APK path. Defaults to the standard debug output path. */
package/dist/index.d.ts CHANGED
@@ -90,6 +90,8 @@ interface AndroidConfig {
90
90
  packageName: string;
91
91
  /** Launch activity, e.g. `.MainActivity`. */
92
92
  activity: string;
93
+ /** App URL scheme used for Expo dev-client deep links, e.g. `myapp`. */
94
+ scheme?: string;
93
95
  /** Gradle tasks that build the app + androidTest APKs. */
94
96
  gradleTasks?: string[];
95
97
  /** Built app APK path. Defaults to the standard debug output path. */
package/dist/index.js CHANGED
@@ -204,9 +204,10 @@ function planAndroid(input) {
204
204
  }
205
205
  }
206
206
  });
207
- const launchCommand = launchCommandFor(android, serial);
208
- push(launchStep("android.launch-1", android, serial));
209
- push(hermesStep("android.hermes-1", android, metro, resolved, hermesDeviceName, launchCommand));
207
+ const launch1Command = launchCommandFor(android, resolved, serial, { forceStopBefore: true });
208
+ const launch2Command = launchCommandFor(android, resolved, serial, { forceStopBefore: false });
209
+ push(launchStep("android.launch-1", android, launch1Command));
210
+ push(hermesStep("android.hermes-1", android, metro, resolved, hermesDeviceName, launch1Command));
210
211
  push({
211
212
  id: "android.forward-clean",
212
213
  stage: "companion",
@@ -263,8 +264,8 @@ function planAndroid(input) {
263
264
  }
264
265
  }
265
266
  });
266
- push(launchStep("android.launch-2", android, serial));
267
- push(hermesStep("android.hermes-2", android, metro, resolved, hermesDeviceName, launchCommand));
267
+ push(launchStep("android.launch-2", android, launch2Command));
268
+ push(hermesStep("android.hermes-2", android, metro, resolved, hermesDeviceName, launch2Command));
268
269
  const cleanup = [
269
270
  {
270
271
  type: "kill-process",
@@ -319,22 +320,34 @@ function planAndroid(input) {
319
320
  playwright: playwrightCommand(playwright, specs, passthrough)
320
321
  };
321
322
  }
322
- function launchCommandFor(android, serial) {
323
- return adb(serial, [
324
- "shell",
325
- "am",
326
- "start",
327
- "-W",
328
- "-n",
329
- `${android.packageName}/${android.activity}`
330
- ]);
323
+ function launchCommandFor(android, resolved, serial, opts) {
324
+ if (android.launch.kind === "plain") {
325
+ return adb(serial, [
326
+ "shell",
327
+ "am",
328
+ "start",
329
+ "-W",
330
+ "-n",
331
+ `${android.packageName}/${android.activity}`
332
+ ]);
333
+ }
334
+ if (!android.scheme) {
335
+ throw new Error('android.scheme is required when android.launch.kind is "expo-dev-client"');
336
+ }
337
+ const launchScript = `am start -a android.intent.action.VIEW -d ${shellSingleQuote(
338
+ devClientUrl(android.scheme, resolved.initialUrl)
339
+ )}`;
340
+ return adbShellScript(
341
+ serial,
342
+ opts.forceStopBefore ? `am force-stop ${android.packageName} && ${launchScript}` : launchScript
343
+ );
331
344
  }
332
- function launchStep(id, android, serial) {
345
+ function launchStep(id, android, command) {
333
346
  return {
334
347
  id,
335
348
  stage: "app-launch",
336
349
  description: `Launch ${android.packageName}/${android.activity}`,
337
- action: { type: "command", command: launchCommandFor(android, serial) }
350
+ action: { type: "command", command }
338
351
  };
339
352
  }
340
353
  function hermesStep(id, android, metro, resolved, deviceNameMatch, launchCommand) {
@@ -368,6 +381,12 @@ function debugHostXml(host) {
368
381
  function adb(serial, args) {
369
382
  return { command: "adb", args: ["-s", serial, ...args] };
370
383
  }
384
+ function devClientUrl(scheme, initialUrl) {
385
+ return `${scheme}://expo-development-client/?url=${initialUrl}`;
386
+ }
387
+ function shellSingleQuote(value) {
388
+ return `'${value.replaceAll("'", "'\\''")}'`;
389
+ }
371
390
  function adbShellScript(serial, remote) {
372
391
  return { command: "adb", args: ["-s", serial, "shell", remote] };
373
392
  }
@@ -413,8 +432,7 @@ function planIos(input) {
413
432
  // Pass the resolved UI-test scheme so a custom `ios.uitestScheme` scaffolds
414
433
  // the SAME target that companion startup later builds (default is
415
434
  // `${appScheme}UITests`).
416
- command: npx([
417
- "rn-driver-xctest-scaffold",
435
+ command: cmd("node_modules/.bin/rn-driver-xctest-scaffold", [
418
436
  "--ios-dir",
419
437
  "ios",
420
438
  "--project-name",
@@ -708,7 +726,7 @@ function placeholderIos(ios, metro) {
708
726
  initialUrl: ios.launch.initialUrl ?? metro.url
709
727
  };
710
728
  }
711
- function placeholderAndroid(android, _metro) {
729
+ function placeholderAndroid(android, metro) {
712
730
  return {
713
731
  serial: "<android-serial>",
714
732
  touchPort: android.companion?.port ?? DEFAULTS.companionPort,
@@ -716,7 +734,8 @@ function placeholderAndroid(android, _metro) {
716
734
  hermesTimeoutMs: DEFAULTS.hermesTargetTimeoutMs,
717
735
  tokenFile: SECRET_PLACEHOLDER,
718
736
  deviceTokenFileName: DEFAULTS.androidTokenFileName,
719
- instrumentationTarget: instrumentationTarget(android)
737
+ instrumentationTarget: instrumentationTarget(android),
738
+ initialUrl: android.launch.initialUrl ?? metro.url
720
739
  };
721
740
  }
722
741
 
@@ -743,7 +762,7 @@ function buildDryRunPlan(config, platform, opts = {}) {
743
762
  return planAndroid({
744
763
  android,
745
764
  metro,
746
- resolved: placeholderAndroid(android),
765
+ resolved: placeholderAndroid(android, metro),
747
766
  playwright: config.playwright,
748
767
  timeoutMs: config.timeoutMs,
749
768
  specs,
@@ -852,6 +871,7 @@ var IOS_KEYS = /* @__PURE__ */ new Set([
852
871
  var ANDROID_KEYS = /* @__PURE__ */ new Set([
853
872
  "packageName",
854
873
  "activity",
874
+ "scheme",
855
875
  "gradleTasks",
856
876
  "appApkPath",
857
877
  "testApkPath",
@@ -953,6 +973,8 @@ function validateAndroid(android, errors) {
953
973
  reportUnknownKeys("config.android", android, ANDROID_KEYS, errors);
954
974
  requireAndroidPackage("config.android.packageName", android.packageName, errors);
955
975
  requireAndroidActivity("config.android.activity", android.activity, errors);
976
+ if (android.scheme !== void 0)
977
+ requireAppScheme("config.android.scheme", android.scheme, errors);
956
978
  optionalString("config.android.appApkPath", android.appApkPath, errors);
957
979
  optionalString("config.android.testApkPath", android.testApkPath, errors);
958
980
  if (android.instrumentationTarget !== void 0)
@@ -965,7 +987,10 @@ function validateAndroid(android, errors) {
965
987
  errors.push("config.android.gradleTasks: expected an array of strings");
966
988
  }
967
989
  validateCompanion("config.android.companion", android.companion, errors);
968
- validateLaunch("config.android.launch", android.launch, errors);
990
+ const launch = validateLaunch("config.android.launch", android.launch, errors);
991
+ if (launch?.kind === "expo-dev-client" && android.scheme === void 0) {
992
+ errors.push('config.android.scheme: required when android.launch.kind is "expo-dev-client"');
993
+ }
969
994
  }
970
995
  function validateCompanion(path, companion, errors) {
971
996
  if (companion === void 0) return;
@@ -1011,6 +1036,7 @@ function requireString(path, value, errors) {
1011
1036
  }
1012
1037
  var ANDROID_PACKAGE_RE = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)+$/;
1013
1038
  var ANDROID_ACTIVITY_RE = /^\.?[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)*$/;
1039
+ var APP_SCHEME_RE = /^[a-z][a-z0-9+.-]*$/;
1014
1040
  function requireAndroidPackage(path, value, errors) {
1015
1041
  if (typeof value !== "string" || value.trim() === "") {
1016
1042
  errors.push(`${path}: required non-empty string`);
@@ -1027,6 +1053,17 @@ function requireAndroidActivity(path, value, errors) {
1027
1053
  if (!ANDROID_ACTIVITY_RE.test(value))
1028
1054
  errors.push(`${path}: expected an activity name (e.g. .MainActivity)`);
1029
1055
  }
1056
+ function requireAppScheme(path, value, errors) {
1057
+ if (typeof value !== "string" || value.trim() === "") {
1058
+ errors.push(`${path}: required non-empty string`);
1059
+ return;
1060
+ }
1061
+ if (!APP_SCHEME_RE.test(value)) {
1062
+ errors.push(
1063
+ `${path}: expected a valid URL scheme (lowercase letter, then lowercase letters, digits, +, ., or -)`
1064
+ );
1065
+ }
1066
+ }
1030
1067
  var ANDROID_INSTRUMENTATION_RE = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)*\/[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)*$/;
1031
1068
  function requireInstrumentationTarget(path, value, errors) {
1032
1069
  if (typeof value !== "string" || value.trim() === "") {