ravensight-playtest 0.2.8 → 0.3.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/README.md +98 -9
- package/docs/ADAPTERS.md +2 -0
- package/docs/NATIVE_RUNNER.md +243 -0
- package/package.json +2 -1
- package/src/cli.js +6 -0
- package/src/commands/check.js +330 -106
- package/src/commands/run.js +104 -8
- package/src/run/aggregate.js +97 -33
- package/src/run/args.js +2 -0
- package/src/run/drivers/driver.js +7 -0
- package/src/run/drivers/web.js +559 -34
- package/src/run/drivers/webdriver-probe.js +353 -0
- package/src/run/dropped.js +7 -7
- package/src/run/heartbeat.js +8 -1
- package/src/run/personaLoop.js +326 -62
- package/src/run/regenerate.js +24 -4
- package/src/run/report.js +93 -2
- package/src/run/resume.js +16 -1
- package/src/run/state.js +4 -1
- package/src/run/tools.js +31 -10
- package/src/run/usage.js +19 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ which is why a machine with no keychain still installs cleanly.
|
|
|
35
35
|
ravensight-playtest login # device code, approved in the browser
|
|
36
36
|
cd path/to/your/game
|
|
37
37
|
ravensight-playtest init --game <gameId> # links this repo
|
|
38
|
-
ravensight-playtest check #
|
|
38
|
+
ravensight-playtest check # one row per setup step, reserves nothing
|
|
39
39
|
ravensight-playtest brief # four questions, two minutes
|
|
40
40
|
ravensight-playtest run # prints the price, asks, then plays
|
|
41
41
|
```
|
|
@@ -81,11 +81,57 @@ with other jobs.
|
|
|
81
81
|
|
|
82
82
|
### check
|
|
83
83
|
|
|
84
|
-
The doctor.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
The doctor. Each setup question is its own row, so a problem in one is never
|
|
85
|
+
reported as another: `node`, `api reachable`, `cli version` (the installed
|
|
86
|
+
version against the server's `latest` and `min_supported`), `credential store`,
|
|
87
|
+
`login` (a token is present, the server accepts it, and which games it is scoped
|
|
88
|
+
to), `project binding` (the game and environment this directory is linked to,
|
|
89
|
+
and whether that game is in the token's scope), `brief` (present, complete, and
|
|
90
|
+
which of goals, success criteria, controls and how to start are empty), `build`
|
|
91
|
+
(the URL, Godot project or native build a run would use), `automation server`
|
|
92
|
+
(native drivers only, see below), then the balance against the next job's price,
|
|
93
|
+
the content pack verified by sha256, disk, recommended concurrency, and the two
|
|
94
|
+
optional tools.
|
|
95
|
+
|
|
96
|
+
Every row is `pass`, `warn` or `fail`, and every row that is not `pass` prints
|
|
97
|
+
its fix. Exit code 3 when any row fails; a warning never fails, so CI does not
|
|
98
|
+
break on a missing optional tool or a newer release. `check` reserves no units
|
|
99
|
+
and starts no job, and says so at the end of its output: everything it asks the
|
|
100
|
+
server is a read, including the price estimate.
|
|
101
|
+
|
|
102
|
+
For a native driver (`ios_driver`, `android_driver`, `desktop_driver`,
|
|
103
|
+
`unity_driver`, `unreal_driver`) the `build` row reads the driver config and
|
|
104
|
+
confirms the app it names exists on disk (an app named by bundle id or package
|
|
105
|
+
can only be confirmed by the server, so that is a warning), and the
|
|
106
|
+
`automation server` row is the free capability probe: `GET /status` on the
|
|
107
|
+
config's loopback endpoint, `POST /session` with the run's own capabilities,
|
|
108
|
+
`GET /session/:id/source` to confirm the app opened and answers, then
|
|
109
|
+
`DELETE /session/:id`. The detail names the step that failed. A session the
|
|
110
|
+
probe could not close is a warning. This talks only to your own local server.
|
|
111
|
+
[docs/NATIVE_RUNNER.md](docs/NATIVE_RUNNER.md) walks through an iOS simulator
|
|
112
|
+
setup with the expected rows at each step.
|
|
113
|
+
|
|
114
|
+
`check --json` prints one object:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"ok": true,
|
|
119
|
+
"reserves_units": false,
|
|
120
|
+
"note": "check reserves no units and starts no job: ...",
|
|
121
|
+
"cli": { "installed": "0.3.0", "latest": "0.3.0", "min_supported": "0.1.0" },
|
|
122
|
+
"login": { "present": true, "valid": true, "games": [{ "gameId": "g1", "name": "Pocket Knight" }] },
|
|
123
|
+
"project": { "game": "g1", "environment": null, "in_scope": true },
|
|
124
|
+
"brief": { "present": true, "complete": true, "missing": [] },
|
|
125
|
+
"build": { "driver": "ios_driver", "ref": "/absolute/path/PocketKnight.app" },
|
|
126
|
+
"automation": { "endpoint": "http://127.0.0.1:4723", "reachable": true, "session": true, "app": true },
|
|
127
|
+
"checks": [{ "name": "login", "status": "pass", "detail": "...", "fix": null }]
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`automation` is null for a driver that is not native. A value of null inside it
|
|
132
|
+
means that step was not reached because an earlier one failed. `environment`
|
|
133
|
+
comes from the server when it reports one, otherwise from an `environment` key
|
|
134
|
+
in `.ravensight/config.json`, otherwise null.
|
|
89
135
|
|
|
90
136
|
For a web game there is also a `browser` row: `check` imports Playwright,
|
|
91
137
|
launches a headless Chromium and closes it, which is exactly how a web run
|
|
@@ -114,6 +160,8 @@ automatically. `check` shows that same warning as a row when it applies.
|
|
|
114
160
|
| `--personas <list>` | Price this persona list. Without it the balance row prices no personas, so the quote is lower than a real job's. |
|
|
115
161
|
| `--godot-path <path>` | Where Godot is, if it is not on the PATH. |
|
|
116
162
|
| `--web` | Check the browser even when this repo is not linked to a web build. |
|
|
163
|
+
| `--driver <name>` | Check the setup for this driver instead of the configured one. |
|
|
164
|
+
| `--driver-config <file>` | The native driver config to probe, instead of the configured build. |
|
|
117
165
|
|
|
118
166
|
### init
|
|
119
167
|
|
|
@@ -184,6 +232,14 @@ run options below.
|
|
|
184
232
|
Registers a job, plays it, writes the reports, uploads them, finishes the job.
|
|
185
233
|
Prints the price and asks before spending.
|
|
186
234
|
|
|
235
|
+
With a native driver, `run` first runs the `build` and `automation server` rows
|
|
236
|
+
of `check`. When either fails it exits 1 before the estimate, the confirmation
|
|
237
|
+
and the register, so no job exists and nothing is reserved, and the message
|
|
238
|
+
names the failing row and its fix. `--skip-preflight` registers without the
|
|
239
|
+
probe, and then the job is registered and charged even if the automation server
|
|
240
|
+
turns out to be down. The probe prints `probing <endpoint>, this can take up to
|
|
241
|
+
3 minutes on a fresh simulator` before it starts, and each row as it completes.
|
|
242
|
+
|
|
187
243
|
There is no product limit on how many personas one job can name; an unplayed
|
|
188
244
|
run is refunded automatically when the job settles, so a large job never costs
|
|
189
245
|
more than what actually got played. `--personas` past 100, or the same slug
|
|
@@ -197,9 +253,11 @@ splitting the job in two is what gets everything played.
|
|
|
197
253
|
|---|---|
|
|
198
254
|
| `--game <gameId>` | The game, when this repo is not linked. |
|
|
199
255
|
| `--personas <list>` | Comma separated persona slugs. Defaults to the pack's set. |
|
|
200
|
-
| `--driver <name>` | `playwright_web` or `
|
|
256
|
+
| `--driver <name>` | `playwright_web`, `godot_driver`, `cli_stdio`, or a native driver: `desktop_driver`, `unity_driver`, `unreal_driver`, `android_driver`, `ios_driver`. |
|
|
201
257
|
| `--build-url <url>` | The web build to play. |
|
|
202
258
|
| `--godot-project <dir>` | The Godot project directory. |
|
|
259
|
+
| `--driver-config <file>` | The native driver config, or the JSON-RPC bridge config for `cli_stdio`. |
|
|
260
|
+
| `--skip-preflight` | Native drivers only: register without running the free automation probe first. The job is registered and charged even if the automation server turns out to be down. |
|
|
203
261
|
| `--cli <command>` | The command that starts a text build. |
|
|
204
262
|
| `--max-actions <n>` | Lower the actions one persona may take. It can only lower the persona's own patience (and the server's per run ceiling), never raise it. |
|
|
205
263
|
| `--concurrency <n>` | Personas at once. Default 2; `check` recommends a number for this machine. |
|
|
@@ -254,7 +312,15 @@ How the report step reads what happened:
|
|
|
254
312
|
- Every note carries `after`, the URL and title of the screen that followed
|
|
255
313
|
it. A blocker or major finding has to cite the observation where the failure
|
|
256
314
|
is visible and must not be contradicted by that next screen or by a later
|
|
257
|
-
persona note.
|
|
315
|
+
persona note. It also has to cite the screenshot taken at or after that
|
|
316
|
+
observation (the prompt says which observation each screenshot followed),
|
|
317
|
+
and that screenshot must not show what the finding says is missing.
|
|
318
|
+
- Every evidence entry is `{"type": ..., "ref": ...}`. A screenshot path the
|
|
319
|
+
model put under `path` or `file` is moved to `ref` before the report is
|
|
320
|
+
checked; the file still has to exist in the run directory. If the server
|
|
321
|
+
still refuses `report.json` at `complete`, the CLI prints every validation
|
|
322
|
+
message it sent, the run is not counted as succeeded or in the aggregate,
|
|
323
|
+
and the job exits 1.
|
|
258
324
|
- The model is told never to write calendar dates. `report.md` carries the
|
|
259
325
|
CLI's own `Generated at` timestamp under its title, and the aggregate report's
|
|
260
326
|
header uses its `generated_at`.
|
|
@@ -285,6 +351,23 @@ macOS, Windows and Linux; ordinary typing is keystrokes. An editing shortcut
|
|
|
285
351
|
such as select all uses the platform's own modifier (Command on a Mac, Control
|
|
286
352
|
elsewhere, or `--key-modifier`).
|
|
287
353
|
|
|
354
|
+
On the web each button, link and field the persona sees carries a short ref
|
|
355
|
+
such as `[e12]`, and its centre `@(x,y)` when it is on screen. The persona
|
|
356
|
+
clicks and types by ref, which names exactly one element even when two share
|
|
357
|
+
a name; two such elements are both shown, each with where it is ("in header
|
|
358
|
+
strip", "in main"). A name that matches twice is answered with the refs to
|
|
359
|
+
choose from, and a target written as locator code (`getByRole(...)`,
|
|
360
|
+
`page.locator(...)`, `css=`, `xpath=`) is refused at once. Failures like these
|
|
361
|
+
are the driver's, not the game's: they are recorded as `driver_error`, and a
|
|
362
|
+
blocker or major resting only on them is dropped before upload, as is any
|
|
363
|
+
finding resting only on the persona's "waiting for X to finish" notes.
|
|
364
|
+
|
|
365
|
+
On a long web page the persona's text view of the screen is capped at 4,000
|
|
366
|
+
characters. Over the cap, buttons, links and fields are kept first, a long run
|
|
367
|
+
of look-alike items (a list of 249 cards) is shown as its first two and "and
|
|
368
|
+
247 more like it", and what changed since the last look comes next, so a form
|
|
369
|
+
after a long list still reaches the persona.
|
|
370
|
+
|
|
288
371
|
Each persona starts at the game's URL as a fresh player with no account, so a
|
|
289
372
|
sign-up form with validation can use up a whole unit before the game itself is
|
|
290
373
|
reached. Point `--build-url` at a guest or demo path, or say where to start in
|
|
@@ -440,6 +523,10 @@ lost to it. The CLI lints locally first and feeds any miss back into one repair
|
|
|
440
523
|
turn, which costs a model turn; a report written with the four headings from the
|
|
441
524
|
start avoids that.
|
|
442
525
|
|
|
526
|
+
The repository's tests check rendered reports against `test/fixtures/server/`, a
|
|
527
|
+
byte copy of the server's report schema from game_tracker commit 864027e,
|
|
528
|
+
which has to be refreshed by hand whenever the server's schema changes.
|
|
529
|
+
|
|
443
530
|
## Exit codes
|
|
444
531
|
|
|
445
532
|
| Code | Meaning |
|
|
@@ -581,6 +668,8 @@ import { createClient, packs, uploadRunDir } from 'ravensight-playtest';
|
|
|
581
668
|
|---|---|
|
|
582
669
|
| `docs/api-contract.md` | Every server route this CLI calls, with the headers it sends and the status codes it handles. The list to check a server change against. |
|
|
583
670
|
| `docs/godot-driver.md` | The Godot driver protocol, its method set, its error codes and its safety rules. |
|
|
671
|
+
| `docs/ADAPTERS.md` | Every driver, its target and how far it has been validated. |
|
|
672
|
+
| `docs/NATIVE_RUNNER.md` | A minimal iOS simulator runner through a local W3C automation server, step by step, with the `check` rows expected at each step. |
|
|
584
673
|
| `src/api/README.md` | The module other code may import, and what the runner half expects from it. |
|
|
585
674
|
|
|
586
675
|
## License
|
|
@@ -611,4 +700,4 @@ feedback and timing-sensitive gameplay.
|
|
|
611
700
|
|
|
612
701
|
## Build adapters
|
|
613
702
|
|
|
614
|
-
Browser and Godot runners share the paid playtest lifecycle with desktop, Unity/Unreal export, Android/iOS and custom JSON-RPC adapters. Native adapters require a locally configured automation server and remain experimental until validated against your build. See [adapter setup and validation boundaries](docs/ADAPTERS.md).
|
|
703
|
+
Browser and Godot runners share the paid playtest lifecycle with desktop, Unity/Unreal export, Android/iOS and custom JSON-RPC adapters. Native adapters require a locally configured automation server and remain experimental until validated against your build. See [adapter setup and validation boundaries](docs/ADAPTERS.md) and the [native runner starter](docs/NATIVE_RUNNER.md); `check` probes the automation server for free before a paid native run.
|
package/docs/ADAPTERS.md
CHANGED
|
@@ -24,6 +24,8 @@ ravensight-playtest run --driver godot_driver --godot-project ./your-game
|
|
|
24
24
|
|
|
25
25
|
## Desktop and mobile
|
|
26
26
|
|
|
27
|
+
Before anything else, `ravensight-playtest check --driver <name> --driver-config <file>` probes the automation server for free (status, a session with your capabilities, the app answering, the session closed), and `run` repeats that probe before it registers a paid native job. [NATIVE_RUNNER.md](NATIVE_RUNNER.md) is a step by step iOS simulator starter with the expected `check` rows.
|
|
28
|
+
|
|
27
29
|
Install and configure an Appium-compatible driver for your platform. Start its server locally. Supply `ravensight-driver.json` with a loopback endpoint and capabilities appropriate to the installed driver:
|
|
28
30
|
|
|
29
31
|
```json
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Native runner starter: an iOS simulator app
|
|
2
|
+
|
|
3
|
+
The smallest setup that lets a persona play a native or engine-exported iOS
|
|
4
|
+
game on a simulator through `ios_driver`. Each step ends with the
|
|
5
|
+
`ravensight-playtest check` rows you should see before moving on. `check` never
|
|
6
|
+
reserves units or starts a job, so you can run it as often as you like.
|
|
7
|
+
|
|
8
|
+
## Read this first: what is and is not validated
|
|
9
|
+
|
|
10
|
+
Native persona playtesting needs a local W3C automation server, and it is
|
|
11
|
+
**not yet validated on real hardware or a real simulator session**. A game that
|
|
12
|
+
already sends events through a Ravensight SDK is not, by that alone, something a
|
|
13
|
+
persona can play: the SDK token covers telemetry, and the persona needs the
|
|
14
|
+
automation server to see the screen and tap it.
|
|
15
|
+
|
|
16
|
+
| Step | Status on the machine this guide was written on |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `check` rows for CLI version, login, project binding and brief | Tested by the CLI's own test suite against an in process server. |
|
|
19
|
+
| `build` row reading a driver config and finding the `.app` on disk | Tested, including by running the CLI. |
|
|
20
|
+
| `automation server` row with nothing listening | Tested by running the CLI. The output below is copied from that run. |
|
|
21
|
+
| `automation server` row against a server that refuses the session, and against one that opens it | Tested by running the CLI against a small stub that answers the W3C endpoints the probe calls. **Not** tested against a real automation server. |
|
|
22
|
+
| `run` refusing to register when the probe fails | Tested by the CLI's test suite. |
|
|
23
|
+
| Building the app, booting the simulator, installing and starting a real automation server with its iOS driver | **Untested.** The commands are the standard ones, and they were not run for this guide. |
|
|
24
|
+
| A persona actually playing an iOS app to a finished report | **Untested.** No paid native job has been run for this guide. |
|
|
25
|
+
|
|
26
|
+
Treat the untested steps as a starting point, and tell us what you had to change.
|
|
27
|
+
|
|
28
|
+
## What a persona can and cannot do on iOS
|
|
29
|
+
|
|
30
|
+
The persona sees two things after every action: a screenshot (PNG) and the
|
|
31
|
+
page source the automation server returns, cut to the model's text limit. On iOS
|
|
32
|
+
that source is built from the accessibility tree, so a control with an
|
|
33
|
+
accessibility label shows up by name and one without shows up as an unnamed
|
|
34
|
+
element the persona can only find in the screenshot.
|
|
35
|
+
|
|
36
|
+
It can:
|
|
37
|
+
|
|
38
|
+
- tap a point on the screen (a W3C touch pointer: move, down, up);
|
|
39
|
+
- swipe from one point to another with a single finger, 100 ms to 2 seconds;
|
|
40
|
+
- type text into whatever already has focus, and press Enter, Escape, Tab,
|
|
41
|
+
Backspace, Space and the arrow keys;
|
|
42
|
+
- wait up to 5 seconds.
|
|
43
|
+
|
|
44
|
+
It cannot:
|
|
45
|
+
|
|
46
|
+
- read engine logs, console output or crash logs (the native driver reports
|
|
47
|
+
none, so a crash is only seen as a screen that changed or stopped answering);
|
|
48
|
+
- record video (screenshots only);
|
|
49
|
+
- clear a text field before typing, or type into a field it has not tapped;
|
|
50
|
+
- long press, pinch, rotate, use two fingers, shake the device, or press the
|
|
51
|
+
hardware buttons;
|
|
52
|
+
- run more than one persona on the device at a time (native runs are
|
|
53
|
+
concurrency 1);
|
|
54
|
+
- navigate by URL, install anything, or change the server, the capabilities or
|
|
55
|
+
the app: those come only from your driver config.
|
|
56
|
+
|
|
57
|
+
Every device command times out after 30 seconds and responses are capped at
|
|
58
|
+
8 MB. See [ADAPTERS.md](ADAPTERS.md) for the other drivers.
|
|
59
|
+
|
|
60
|
+
## Step 1: the account side
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install -g ravensight-playtest@0.3.0
|
|
64
|
+
ravensight-playtest login
|
|
65
|
+
cd path/to/your/game
|
|
66
|
+
ravensight-playtest init --game <gameId>
|
|
67
|
+
ravensight-playtest check --driver ios_driver
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Expected rows (your email, game and version differ):
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
pass cli version installed 0.3.0; server latest 0.3.0, min_supported 0.1.0
|
|
74
|
+
pass login you@example.com, valid, scoped to 1 game: Pocket Knight (g1)
|
|
75
|
+
pass project binding linked to Pocket Knight (g1), in the token's scope
|
|
76
|
+
fail brief this game has no expectations brief, and a persona run needs one
|
|
77
|
+
fail build no driver config: a native run has nothing to open
|
|
78
|
+
fail automation server no driver config, so there is no automation server to probe for ios_driver
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`cli version` warns when the server lists a newer release and fails only below
|
|
82
|
+
`min_supported`. `login` passing means the stored token is valid; it does not
|
|
83
|
+
mean the game can be played. If `login` passes and `project binding` fails,
|
|
84
|
+
the token is valid but was not approved for this game: run `login` again and
|
|
85
|
+
approve it, rather than looking for a login problem.
|
|
86
|
+
|
|
87
|
+
## Step 2: the brief
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ravensight-playtest brief
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
A run needs four fields; for a native game these are the ones that decide
|
|
94
|
+
whether a persona gets anywhere:
|
|
95
|
+
|
|
96
|
+
| Field | What to write for a native game |
|
|
97
|
+
|---|---|
|
|
98
|
+
| `goals` | One or two. `onboarding` and `find_bugs` suit a first native run. |
|
|
99
|
+
| `success_criteria` | Something visible on screen, one per line: "Reaches the map screen", "Finishes the tutorial battle". The persona has no logs to prove anything else. |
|
|
100
|
+
| `build_notes.controls` | Taps and swipes only, named by what is on screen: "Tap a tile to move. Swipe left or right on the deck to pick a card." Say if anything needs a long press or two fingers, since the persona cannot do it. |
|
|
101
|
+
| `build_notes.how_to_start` | The first screen after launch and what to tap: "Launches to the title screen; tap Start, then skip the intro with the X in the top right." Mention any system prompt (notifications, tracking) the persona will meet. |
|
|
102
|
+
| `known_issues` | Anything already known, so it is not reported again. |
|
|
103
|
+
| `design_intent_notes` | Choices that look like bugs: a deliberately hidden menu, an unskippable intro. |
|
|
104
|
+
|
|
105
|
+
Expected after saving it:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
pass brief version 1, complete (goals, success criteria, controls, how to start)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Step 3: a simulator build (untested here)
|
|
112
|
+
|
|
113
|
+
Build for the simulator and note the path of the `.app` it produces:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
xcodebuild -scheme <YourScheme> -sdk iphonesimulator -configuration Debug \
|
|
117
|
+
-derivedDataPath build
|
|
118
|
+
ls build/Build/Products/Debug-iphonesimulator/
|
|
119
|
+
xcrun simctl list devices available
|
|
120
|
+
xcrun simctl boot "<simulator name>"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Step 4: the driver config
|
|
124
|
+
|
|
125
|
+
Save `ravensight-driver.json` in the game's directory. The endpoint must be a
|
|
126
|
+
loopback URL with no credentials; `check` and `run` refuse anything else. Use
|
|
127
|
+
an absolute path for the app so `check` can confirm it exists:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"endpoint": "http://127.0.0.1:4723",
|
|
132
|
+
"capabilities": {
|
|
133
|
+
"platformName": "iOS",
|
|
134
|
+
"appium:automationName": "XCUITest",
|
|
135
|
+
"appium:deviceName": "<simulator name>",
|
|
136
|
+
"appium:platformVersion": "<simulator iOS version>",
|
|
137
|
+
"appium:app": "/absolute/path/to/build/Build/Products/Debug-iphonesimulator/YourGame.app"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For an app already installed on the simulator, use `"appium:bundleId":
|
|
143
|
+
"com.example.yourgame"` in place of `appium:app`. Then `check` cannot confirm
|
|
144
|
+
it on disk, so the `build` row is a warning and the `automation server` row is
|
|
145
|
+
what confirms it.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
ravensight-playtest check --driver ios_driver --driver-config ravensight-driver.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
With no automation server running yet, this is the output copied from running
|
|
152
|
+
the CLI (paths shortened):
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
pass build appium:app /.../PocketKnight.app (from /.../ravensight-driver.json)
|
|
156
|
+
fail automation server nothing answered at http://127.0.0.1:4723 (ECONNREFUSED)
|
|
157
|
+
|
|
158
|
+
automation server: start your local W3C automation server (see docs/NATIVE_RUNNER.md) and confirm the endpoint in the driver config
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
A missing app reads `fail build appium:app /.../YourGame.app does not exist`.
|
|
162
|
+
|
|
163
|
+
## Step 5: the automation server (untested here)
|
|
164
|
+
|
|
165
|
+
Install a W3C automation server and its iOS simulator driver (the one that
|
|
166
|
+
accepts `"appium:automationName": "XCUITest"`), following that server's own
|
|
167
|
+
documentation, and start it listening on `127.0.0.1:4723`. ravensight-playtest
|
|
168
|
+
does not install, bundle or start one. Do not expose it beyond loopback. The
|
|
169
|
+
first session on a fresh simulator builds and installs the server's on device
|
|
170
|
+
agent, which can take several minutes; the probe waits up to 3 minutes for a
|
|
171
|
+
session.
|
|
172
|
+
|
|
173
|
+
Run the same `check` again. If the server answers but cannot drive the
|
|
174
|
+
simulator, the output is (copied from a run against the stub):
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
fail automation server the server did not create a session: session not created: Unknown device or simulator UDID
|
|
178
|
+
|
|
179
|
+
automation server: boot the simulator and check the capabilities: platformName, deviceName, platformVersion and automationName must match a device the server can drive
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
When the server opens a session, launches the app and closes the session again
|
|
183
|
+
(copied from a run against the stub, not a real server):
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
pass build appium:app /.../PocketKnight.app (from /.../ravensight-driver.json)
|
|
187
|
+
pass automation server http://127.0.0.1:4723 reachable, session created and closed, app /.../PocketKnight.app opened
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
and `check --json` includes:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
"automation": { "endpoint": "http://127.0.0.1:4723", "reachable": true, "session": true, "app": true }
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The other failures you may see, each naming its step: `... answered but says
|
|
197
|
+
it is not ready`, `the capabilities name no app`, `... did not answer in the
|
|
198
|
+
session` (the session opened but the app did not), and a `warn` reading
|
|
199
|
+
`session created and NOT closed` when the probe could not close its session. If creating the session takes longer than 3 minutes the row
|
|
200
|
+
says `a session may still be open on the server; restart it or wait before
|
|
201
|
+
retrying`: when the server lists its sessions the probe asks it to close any that
|
|
202
|
+
appeared meanwhile, and otherwise it cannot tell which one is its own.
|
|
203
|
+
|
|
204
|
+
## Step 6: link the native build to the repo
|
|
205
|
+
|
|
206
|
+
So `run` and `check` need no flags, set these in `.ravensight/config.json`:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"driver": "ios_driver",
|
|
211
|
+
"build": { "kind": "driver_config", "ref": "ravensight-driver.json" }
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`run` resolves a relative `ref` against the directory you run it from, so run it
|
|
216
|
+
from the game's directory. Now plain `ravensight-playtest check` should end with
|
|
217
|
+
every row `pass` or `warn` and exit 0.
|
|
218
|
+
|
|
219
|
+
## Step 7: the run (untested here)
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
ravensight-playtest run --personas curious-kid --max-actions 15
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Before it asks the server for a price, `run` repeats the `build` and
|
|
226
|
+
`automation server` rows as a free preflight, printing each row as it completes
|
|
227
|
+
and a line before the slow step:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
preflight pass build: appium:app /.../YourGame.app (from /.../ravensight-driver.json)
|
|
231
|
+
probing http://127.0.0.1:4723, this can take up to 3 minutes on a fresh simulator
|
|
232
|
+
preflight pass automation server: http://127.0.0.1:4723 reachable, session created and closed, app /.../YourGame.app opened
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
If either row fails, `run` exits 1 with `Preflight failed at "<row>": ...` and
|
|
236
|
+
`No job was registered and nothing was reserved.` Only after the preflight
|
|
237
|
+
passes does it print the price and ask. `--skip-preflight` registers without the
|
|
238
|
+
probe: the job is then registered and charged even if the automation server
|
|
239
|
+
turns out to be down, so use it only when you know the server is up and the
|
|
240
|
+
probe's own session would get in the way.
|
|
241
|
+
|
|
242
|
+
One persona and a low `--max-actions` keep the first native run cheap while you
|
|
243
|
+
find out what the persona can reach.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ravensight-playtest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "AI personas play your game and file reports to Ravensight.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://ravensight.io/docs/#playtest",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"src",
|
|
27
27
|
"addons",
|
|
28
28
|
"docs/ADAPTERS.md",
|
|
29
|
+
"docs/NATIVE_RUNNER.md",
|
|
29
30
|
"README.md",
|
|
30
31
|
"LICENSE",
|
|
31
32
|
"!src/**/*.test.js",
|
package/src/cli.js
CHANGED
|
@@ -67,6 +67,8 @@ Run options (parsed by the runner, see src/run/args.js):
|
|
|
67
67
|
--headed show the browser
|
|
68
68
|
--headless hide it
|
|
69
69
|
--verbose print each turn
|
|
70
|
+
--skip-preflight native drivers: register without probing the automation server first;
|
|
71
|
+
the job is registered and charged even if the server turns out to be down
|
|
70
72
|
|
|
71
73
|
Accepted and reported as not applied by this release:
|
|
72
74
|
--quality, --offline-upload, --build-dir
|
|
@@ -162,10 +164,14 @@ export function buildProgram() {
|
|
|
162
164
|
.addOption(new Option('--personas <list>', 'price this persona list').argParser(list))
|
|
163
165
|
.option('--godot-path <path>', 'where Godot is, if it is not on the PATH')
|
|
164
166
|
.option('--web', 'check the browser even when this repo is not linked to a web build')
|
|
167
|
+
.option('--driver <name>', 'check the setup for this driver instead of the configured one')
|
|
168
|
+
.option('--driver-config <file>', 'the native driver config to probe instead of the configured one')
|
|
165
169
|
.action(capture(slot, async options => {
|
|
166
170
|
const { check } = await import('./commands/check.js');
|
|
167
171
|
return check(flagsFrom(options, {
|
|
168
172
|
game: options.game,
|
|
173
|
+
driver: options.driver,
|
|
174
|
+
driverConfig: options.driverConfig,
|
|
169
175
|
modules: options.modules,
|
|
170
176
|
personas: options.personas,
|
|
171
177
|
godotPath: options.godotPath,
|