@verirun/cli 0.2.4 → 0.2.5

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 CHANGED
@@ -147,6 +147,20 @@ what you recorded is what runs.
147
147
  into a field and close the browser without clicking or tabbing away, that last
148
148
  value is not recorded. Tab out before closing.
149
149
 
150
+ **Dialogs.** Answer `alert` / `confirm` / `prompt` boxes in the recording
151
+ browser as you normally would. Codegen notes *that* a step opened one but not
152
+ which button you pressed, so after you close the browser `record` asks, per such
153
+ step, `[O]K / [c]ancel` (Enter = OK; without a terminal every answer is OK). The
154
+ answer is saved on the step and `run` replays it:
155
+
156
+ ```json
157
+ { "index": 4, "action": "click", "selector": "…", "dialog": { "action": "dismiss" } }
158
+ ```
159
+
160
+ `action` is `accept` (OK) or `dismiss` (Cancel). For a `prompt()`, add
161
+ `"promptText": "…"` — without it, accepting submits the prompt's default value.
162
+ Every dialog the step opens gets the same answer.
163
+
150
164
  **Nothing recorded.** If you close the browser without doing anything, nothing
151
165
  is saved and the command says so.
152
166
 
@@ -217,6 +231,7 @@ and writes `.verirun/runs/<name>-<timestamp>/logs.json`.
217
231
  | `--user-data-dir <dir>` | Replay in a persistent profile directory, so it runs already logged in. The profile must not be open in another browser. |
218
232
  | `--cdp <url>` | Attach to a browser already running with remote debugging and drive it. See below. |
219
233
  | `--user <id>` | Keep only log entries whose message or raw payload contains this string, case-insensitive — e.g. a user's email. Overrides `config.userFilter`. Recorded in `logs.json` as `"filter": { "user": … }`; `entries` and the per-source counts are post-filter. If everything is filtered out, `run` warns. |
234
+ | `--dialog <answer>` | How to answer a browser dialog opened by a step with no saved `dialog` answer: `accept` (OK, the default) or `dismiss` (Cancel). A step's own `dialog` always wins. |
220
235
 
221
236
  **Where the user filter runs.** For **Supabase** it goes into the log query's
222
237
  `WHERE` (matched against the rendered message and the JSON of `metadata`), so
@@ -263,6 +278,11 @@ frontmost.
263
278
  whatever logs already landed are still written, and the exit code is non-zero.
264
279
  - Popups and newly opened tabs become the active target as they open. A workflow
265
280
  that drives several tabs at once is not supported yet.
281
+ - Browser dialogs (`alert`, `confirm`, `prompt`, `beforeunload`) are answered
282
+ automatically: with the step's saved `dialog` if it has one, otherwise with
283
+ `--dialog` (default `accept`). Each one is printed under its step and listed
284
+ in `logs.json` `dialogs`. With `--cdp`, only tabs the run itself drives or
285
+ opens are touched.
266
286
 
267
287
  ### Sequencing
268
288
 
@@ -282,6 +302,9 @@ warned about and contributes no entries.
282
302
  "window": { "startedAt": "2026-08-31T13:01:50.998Z", "endedAt": "2026-08-31T13:01:51.499Z" },
283
303
  "steps": { "total": 12, "replayed": 12 },
284
304
  "filter": { "user": "ada@example.com" },
305
+ "dialogs": [
306
+ { "step": 7, "type": "confirm", "message": "Delete this item?", "action": "accept", "at": "2026-08-31T13:01:51.102Z" }
307
+ ],
285
308
  "sources": [{ "id": "vercel", "name": "Vercel", "entries": 8 }],
286
309
  "entries": [
287
310
  {
@@ -300,6 +323,10 @@ warned about and contributes no entries.
300
323
  (the step index) and the file carries a top-level `error` string.
301
324
  - `filter` is present only when `--user` / `config.userFilter` was in effect;
302
325
  `entries` and every `sources[].entries` count are then post-filter.
326
+ - `dialogs` lists every browser dialog the replay answered, in order: the
327
+ `step` running when it opened, its `type` and `message`, the prompt's
328
+ `defaultValue` (prompts only), the `action` taken, and the `promptText`
329
+ submitted to an accepted prompt. Empty when none opened.
303
330
  - `entries` merges every source, sorted by `timestamp`. `stream` is the
304
331
  sub-stream within a source (`lambda`, `edge`, `postgres_logs`, …). `raw` is
305
332
  the provider's untouched payload (for Supabase that now includes the row's
@@ -422,11 +449,25 @@ element that gets you there:
422
449
  $ verirun map --bfs /account --depth 2
423
450
  page:/account
424
451
  └─ nav "verirun" → page:/
425
- └─ effect "revoke" [if !(tokens.length === 0)] → effect:POST ?
452
+ └─ effect "revoke" [if window.confirm("Revoke this terminal's access? …")] → effect:POST ?
453
+ opens confirm "Revoke this terminal's access? …" — the answer decides what the click does
426
454
  └─ nav "Log in" → page:/login
427
455
  # frontier at depth 2: page:/login, page:/signup
428
456
  ```
429
457
 
458
+ **Browser dialogs.** An element whose handler calls the native `alert()`,
459
+ `confirm()` or `prompt()` (bare, or on `window` / `globalThis`; a locally
460
+ imported `confirm` is a custom modal, not a dialog) carries
461
+ `dialogs: [{ type, message, messageStatic, gates, … }]` in `--json`. `gates` is
462
+ true when the handler reads the answer, so OK and Cancel lead to different
463
+ outcomes. An early `if (!window.confirm(…)) return;` also shows up as the
464
+ `guardSource` of every backend call after it, which is how you see that Cancel
465
+ skips the `POST`. The per-page summary counts the elements that open a dialog,
466
+ `--bfs` prints each one under its edge, and `coverage.md` lists them all. A
467
+ workflow step that clicks one answers it with its `dialog` field (see
468
+ [`verirun run`](#verirun-run-name)); `workflow check` warns when that field is
469
+ missing (see below).
470
+
430
471
  **Limits, honestly.** It is static analysis: a target computed at runtime shows
431
472
  as `unresolved`, an endpoint passed through a variable as `?`, and Supabase
432
473
  `.auth.*` / `.storage.*` calls are not yet classified as effects. `--reach`
@@ -451,6 +492,15 @@ verirun workflow check login --json # machine-readable findings
451
492
  verirun workflow check ./some/file.json
452
493
  ```
453
494
 
495
+ If `verirun map --report` has saved `.verirun/map/interaction-tree.json`,
496
+ `check` also warns about a step that clicks an element the graph says opens a
497
+ browser dialog but has no `dialog` answer. Replay would press OK, which is
498
+ usually what you want, but when the handler reads the answer, Cancel is a
499
+ different path and should be chosen on purpose. Matching is by exact selector, so it catches
500
+ workflows written from `map --json`. A selector that elements *without* a dialog
501
+ also match (a bare `role=button`) is skipped rather than guessed at. Re-run
502
+ `map --report` when the app changes; the saved graph goes stale.
503
+
454
504
  Static only: it never opens a browser, so it cannot tell you whether a selector
455
505
  matches the live page. Only `verirun run` can. Non-zero exit if anything is an
456
506
  error.
@@ -477,7 +527,9 @@ an agent — to write `.verirun/workflows/<name>.json` directly:
477
527
  Actions and required `params`: `navigate` (`url`, absolute), `click` /
478
528
  `dblclick`, `fill` (`text`), `press` (`key`), `check` / `uncheck`, `select`
479
529
  (`values`), `setInputFiles` (`files`). Everything but `navigate` needs a
480
- `selector`, which is handed to `page.locator()` verbatim.
530
+ `selector`, which is handed to `page.locator()` verbatim. A step that opens a
531
+ browser dialog can carry `"dialog": { "action": "accept" | "dismiss",
532
+ "promptText"?: "…" }`; without it `run` accepts.
481
533
 
482
534
  A recorded workflow is ground truth; a written one is a guess until `run`
483
535
  confirms it. Don't overwrite a recording with a generated file — use a new name.
@@ -663,6 +715,30 @@ run this often.
663
715
 
664
716
  ## Changelog
665
717
 
718
+ ### 0.2.5
719
+
720
+ - **`verirun run` answers browser dialogs instead of cancelling them.** With no
721
+ handler, Playwright dismissed every `alert` / `confirm` / `prompt`, so each
722
+ `confirm()` in a workflow came back as Cancel and the action it guarded
723
+ quietly never happened. Replay now answers each one: with the step's saved
724
+ `dialog` (`accept` / `dismiss`, plus `promptText` for a prompt), otherwise
725
+ with the new `--dialog accept|dismiss` (default `accept`). Each dialog is
726
+ printed under its step and listed in `logs.json` under `dialogs`. With
727
+ `--cdp`, only the tabs the run drives are touched.
728
+ - **`verirun record` asks which button you pressed.** Playwright's recorder notes
729
+ that a step opened a dialog but not the answer, so after you close the
730
+ browser `record` asks `[O]K / [c]ancel` for each such step and saves it on the
731
+ step.
732
+ - **`verirun map` shows the dialogs an element opens.** `--json` carries a
733
+ `dialogs` list per element (`type`, `message`, and `gates` when the handler
734
+ reads the answer). An early `if (!window.confirm(…)) return;` now shows up as
735
+ the `guardSource` of the backend calls after it, so you can see that Cancel
736
+ skips them. The summary counts them, `--bfs` prints them under their edge,
737
+ and `coverage.md` lists them.
738
+ - **`verirun workflow check` validates the `dialog` field.** After `map
739
+ --report`, it also warns about a step that clicks a dialog-opening element
740
+ without saying OK or Cancel.
741
+
666
742
  ### 0.2.4
667
743
 
668
744
  - **`verirun map` reads the import aliases your project actually declares.**