@unrulysystems/rn-playwright-driver-runner 0.1.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 ADDED
@@ -0,0 +1,9 @@
1
+ # @unrulysystems/rn-playwright-driver-runner
2
+
3
+ ## 0.1.0
4
+
5
+ ### Initial Release
6
+
7
+ - Add the config-backed `rn-driver` native e2e lifecycle runner for iOS and Android.
8
+ - Add typed `rn-driver.config.ts` support through `defineRnDriverConfig`.
9
+ - Add pure iOS/Android lifecycle planning, runner execution, dry-run output, and release-shape tests.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Unruly Systems LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # @unrulysystems/rn-playwright-driver-runner
2
+
3
+ A config-backed, cross-platform CLI that owns the **native e2e lifecycle** for
4
+ [`@unrulysystems/rn-playwright-driver`](https://www.npmjs.com/package/@unrulysystems/rn-playwright-driver)
5
+ tests on iOS and Android.
6
+
7
+ Instead of copying ~400-line per-app shell recipes, you describe your app's facts
8
+ once in `rn-driver.config.ts` and run:
9
+
10
+ ```bash
11
+ rn-driver test --platform ios
12
+ rn-driver test --platform android
13
+ rn-driver test --platform all
14
+ ```
15
+
16
+ The runner owns the generic lifecycle — simulator/emulator selection, Metro
17
+ ownership, touch-companion startup, secure token passing, cold-launch semantics,
18
+ Hermes target wait, and cleanup — and then sets the driver's environment-variable
19
+ contract and invokes Playwright. The dependency direction is one-way at the
20
+ **contract** level: the runner targets the driver's `RN_*` env-var contract and
21
+ drives its companions, while the core driver stays orchestration-free and never
22
+ references the runner. (The runner does not import driver code, so it carries no
23
+ npm dependency on it — install `@unrulysystems/rn-playwright-driver` alongside
24
+ this package; your Playwright specs import the driver directly.)
25
+
26
+ > See `SPEC.md` (the contract) and `BRIEF.md` (the quality bar) in this package
27
+ > for the full design.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ bun add -d @unrulysystems/rn-playwright-driver-runner
33
+ ```
34
+
35
+ This package orchestrates the platform companions; install and configure them per
36
+ their own READMEs:
37
+
38
+ - `@unrulysystems/rn-playwright-driver-xctest-companion` (iOS)
39
+ - `@unrulysystems/rn-playwright-driver-instrumentation-companion` (Android)
40
+
41
+ ## Configure
42
+
43
+ Create `rn-driver.config.ts` in your test workspace:
44
+
45
+ ```ts
46
+ import { defineRnDriverConfig } from '@unrulysystems/rn-playwright-driver-runner'
47
+
48
+ export default defineRnDriverConfig({
49
+ metro: {
50
+ command: 'npx expo start --localhost --port 8081',
51
+ // reuseExisting: true, // attach to an already-running packager
52
+ },
53
+ ios: {
54
+ bundleId: 'com.company.app',
55
+ workspace: 'ios/App.xcworkspace',
56
+ appScheme: 'App',
57
+ // uitestScheme defaults to `${appScheme}UITests`
58
+ launch: {
59
+ // expo-dev-client REQUIRES attach mode: the host owns the launch and
60
+ // hands the dev launcher the Metro URL via `simctl launch --initialUrl`.
61
+ mode: 'attach',
62
+ kind: 'expo-dev-client',
63
+ // initialUrl defaults to the resolved Metro URL
64
+ },
65
+ // App-specific pre-launch seeds (simctl defaults write):
66
+ // defaults: { EXDevMenuIsOnboardingFinished: true },
67
+ },
68
+ android: {
69
+ packageName: 'com.company.app',
70
+ activity: '.MainActivity',
71
+ launch: { mode: 'launch', kind: 'plain' },
72
+ },
73
+ playwright: {
74
+ config: 'playwright.config.ts',
75
+ },
76
+ })
77
+ ```
78
+
79
+ A plain (non dev-client) Expo app uses `launch: { mode: 'launch', kind: 'plain' }`
80
+ on iOS — the companion launches the app itself.
81
+
82
+ ## Run
83
+
84
+ ```bash
85
+ # Inspect the exact plan without touching a device (no side effects):
86
+ rn-driver test --platform ios --dry-run
87
+
88
+ # Run the full lifecycle + Playwright:
89
+ rn-driver test --platform ios
90
+ rn-driver test --platform android
91
+
92
+ # Reuse an already-built native project (skip prebuild/pods/gradle/install):
93
+ rn-driver test --platform ios --skip-build
94
+
95
+ # Forward specs / Playwright args:
96
+ rn-driver test --platform ios e2e/integration/counter.spec.ts
97
+ rn-driver test --platform android -- --grep @smoke
98
+ ```
99
+
100
+ ### Options
101
+
102
+ | Option | Description |
103
+ | ---------------- | ------------------------------------------------------ |
104
+ | `-p, --platform` | `ios` \| `android` \| `all` (required) |
105
+ | `-c, --config` | Path to the config (default: searched upward from cwd) |
106
+ | `-d, --device` | Simulator udid / emulator serial override |
107
+ | `--dry-run` | Print the resolved plan and exit; no side effects |
108
+ | `--skip-build` | Reuse an already-built native project |
109
+ | `--verbose` | Stream per-step progress |
110
+
111
+ On failure before Playwright, the runner names the stage that broke
112
+ (`config` / `metro` / `device` / `build` / `companion` / `app-launch` /
113
+ `hermes-target`) and exits with a distinct code per stage, so a failure tells you
114
+ _where_ it failed.
115
+
116
+ ## How it works
117
+
118
+ ```
119
+ rn-driver.config.ts
120
+ └─ load + validate ──► RnDriverConfig
121
+ └─ resolve ──► simulator/emulator, ports, 0600 token file, Metro url
122
+ └─ plan ──► an ordered, pure list of lifecycle Steps (--dry-run shows this)
123
+ └─ execute ──► run steps, gate on readiness probes, run Playwright, clean up
124
+ ```
125
+
126
+ Token material always travels by `0600` file path (the driver's
127
+ `RN_TOUCH_*_TOKEN_FILE` contract); the value never enters argv, env, logs, or
128
+ `--dry-run` output. Cleanup is defensive and idempotent — a crashed prior run
129
+ never wedges the next (stale companion ports are freed at startup and teardown).
130
+
131
+ ## Requirements
132
+
133
+ - The `rn-driver` CLI runs under **bun**. The `bin` is a thin bun shim (mirroring
134
+ the driver's `rn-inspect`) so a TypeScript `rn-driver.config.ts` loads without a
135
+ separate compile step. Install bun: <https://bun.sh>.
136
+ - The readiness probes use the global `WebSocket`/`fetch`, so embedding the
137
+ library API (the `.` export) standalone requires **bun** or **Node >= 22**.
138
+ - The platform companion packages installed and their Expo config plugins added.
139
+ - `xcrun`/`xcodebuild`/`pod` (iOS) and `adb`/`gradle` (Android) on `PATH`.
140
+
141
+ ## License
142
+
143
+ [MIT](../../LICENSE) © Unruly Systems LLC
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * rn-driver CLI entry. Ships as a thin bun-run shim that loads the built CLI
4
+ * from dist (mirroring the driver's rn-inspect bin), so the published package
5
+ * stays Node/bun-runnable without a separate compiled bin.
6
+ */
7
+ // Import from dist (built output) since src is not shipped in the package.
8
+ import { run } from '../dist/cli.mjs'
9
+
10
+ run(process.argv.slice(2))
11
+ .then((code) => {
12
+ process.exit(code)
13
+ })
14
+ .catch((error: unknown) => {
15
+ console.error(error)
16
+ process.exit(1)
17
+ })
package/dist/cli.d.mts ADDED
@@ -0,0 +1,3 @@
1
+ declare function run(argv: string[]): Promise<number>;
2
+
3
+ export { run };
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ declare function run(argv: string[]): Promise<number>;
2
+
3
+ export { run };