@asrunjs/asrun 0.2.0 → 0.5.3
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/.claude/commands/explore-case.md +18 -15
- package/.claude/commands/gen-spec.md +16 -13
- package/.claude/commands/heal-spec.md +26 -23
- package/.claude/commands/make-case.md +11 -8
- package/.claude/skills/exploring-cases/SKILL.md +146 -132
- package/.claude/skills/exploring-cases/references/open-questions.md +116 -112
- package/.claude/skills/exploring-cases/references/readiness.md +146 -137
- package/.claude/skills/exploring-cases/references/user-handoff.md +157 -147
- package/.claude/skills/generating-specs/SKILL.md +219 -207
- package/.claude/skills/generating-specs/references/conventions.md +148 -148
- package/.claude/skills/making-cases/SKILL.md +72 -64
- package/.claude/skills/making-cases/references/normalizing.md +39 -38
- package/.claude/skills/making-cases/references/writes-and-email.md +37 -36
- package/AGENTS.md +169 -154
- package/CLAUDE.md +2 -1
- package/README.md +221 -410
- package/dist/lib/build-artifacts.d.ts +8 -0
- package/dist/lib/build-artifacts.js +10 -0
- package/dist/lib/case-doc.d.ts +311 -0
- package/dist/lib/case-doc.js +1117 -0
- package/dist/lib/cases.d.ts +2 -15
- package/dist/lib/cases.js +5 -78
- package/dist/lib/command.d.ts +24 -0
- package/dist/lib/command.js +90 -0
- package/dist/lib/fixtures.js +2 -2
- package/dist/lib/login-card.d.ts +22 -0
- package/dist/lib/login-card.js +183 -0
- package/dist/lib/node-cli.d.ts +6 -2
- package/dist/lib/node-cli.js +16 -6
- package/dist/lib/profiles.d.ts +25 -1
- package/dist/lib/profiles.js +54 -1
- package/dist/lib/run-filters.js +10 -2
- package/dist/lib/session.d.ts +13 -1
- package/dist/lib/session.js +73 -7
- package/dist/lib/targets.d.ts +5 -13
- package/dist/lib/targets.js +4 -29
- package/dist/lib/values.js +2 -2
- package/dist/scripts/build.js +2 -1
- package/dist/scripts/check-cases.js +74 -6
- package/dist/scripts/doctor.js +115 -4
- package/dist/scripts/explore.js +22 -1
- package/dist/scripts/go.mjs +188 -188
- package/dist/scripts/init.d.ts +7 -1
- package/dist/scripts/init.js +62 -14
- package/dist/scripts/lint-specs.js +4 -1
- package/dist/scripts/login.js +30 -2
- package/dist/ui/server/actions.d.ts +4 -0
- package/dist/ui/server/actions.js +25 -12
- package/dist/ui/server/ai-models.d.ts +3 -0
- package/dist/ui/server/ai-models.js +347 -0
- package/dist/ui/server/ai-stream.d.ts +34 -9
- package/dist/ui/server/ai-stream.js +283 -77
- package/dist/ui/server/app.js +74 -12
- package/dist/ui/server/jobs.d.ts +7 -1
- package/dist/ui/server/jobs.js +69 -15
- package/dist/ui/server/profiles.d.ts +20 -1
- package/dist/ui/server/profiles.js +214 -38
- package/dist/ui/shared/ai-commands.d.ts +16 -6
- package/dist/ui/shared/ai-commands.js +35 -12
- package/dist/ui/shared/types.d.ts +114 -0
- package/docs/agents/case-format.md +193 -0
- package/docs/agents/framework-dev.md +167 -0
- package/docs/ai-workflow.md +235 -0
- package/docs/cases.md +189 -0
- package/docs/commands.md +175 -0
- package/docs/install.md +174 -0
- package/docs/profiles.md +139 -0
- package/docs/theme-guide.html +922 -692
- package/docs/troubleshooting.md +101 -0
- package/docs/web-ui.md +139 -0
- package/package.json +20 -1
- package/templates/.claude/commands/explore-case.md +22 -21
- package/templates/.claude/commands/gen-spec.md +21 -20
- package/templates/.claude/commands/heal-spec.md +31 -30
- package/templates/.claude/commands/make-case.md +13 -12
- package/templates/.mcp.json +8 -8
- package/templates/AGENTS.md +66 -45
- package/templates/cases/_template.md +57 -63
- package/templates/opencode.jsonc +16 -11
- package/templates/profiles.yaml +42 -29
- package/ui/dist/assets/{dist-D_I45xgJ.js → dist-BudNAjOv.js} +1 -1
- package/ui/dist/assets/{dist-CBV7_vDN.js → dist-C-eCSFja.js} +1 -1
- package/ui/dist/assets/{dist-gF2bFn-5.js → dist-CO4heSzh.js} +1 -1
- package/ui/dist/assets/{dist-DX8knLVr.js → dist-CPLhRzom.js} +1 -1
- package/ui/dist/assets/{dist-BqAROxzI.js → dist-DEPJZ3Me.js} +1 -1
- package/ui/dist/assets/{dist-BwYRbe5s.js → dist-DZ7RiqmA.js} +1 -1
- package/ui/dist/assets/{dist-BHaIOZdW.js → dist-LixzGniF.js} +1 -1
- package/ui/dist/assets/{dist-DHCY9KpV.js → dist-O_RVi4tP.js} +1 -1
- package/ui/dist/assets/{dist-BiE4suo9.js → dist-jPS6HCJ5.js} +1 -1
- package/ui/dist/assets/{dist-BSJMM_jp.js → dist-vmf3fnkM.js} +1 -1
- package/ui/dist/assets/index-BIGt8Hfz.js +338 -0
- package/ui/dist/assets/index-CTmnF0Wp.css +2 -0
- package/ui/dist/help/ai-tools.png +0 -0
- package/ui/dist/help/case-explore.png +0 -0
- package/ui/dist/help/case-generate.png +0 -0
- package/ui/dist/help/cases-memo.png +0 -0
- package/ui/dist/help/profile-form.png +0 -0
- package/ui/dist/help/profiles-login.png +0 -0
- package/ui/dist/help/reports.png +0 -0
- package/ui/dist/help/run-tests.png +0 -0
- package/ui/dist/index.html +22 -16
- package/ui/dist/assets/index-DmasQ6Rq.css +0 -2
- package/ui/dist/assets/index-I7uU93kk.js +0 -294
package/docs/install.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Installing AsRun
|
|
2
|
+
|
|
3
|
+
AsRun is a normal devDependency. A **workspace** is the folder that owns `profiles.yaml`, `cases/` and `tests/`;
|
|
4
|
+
everything AsRun needs at run time is read through it. The framework itself lives in `node_modules/@asrunjs/asrun`
|
|
5
|
+
and is never edited: a project commits only its own test content.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- **Node.js 22 or newer** and **pnpm**.
|
|
10
|
+
- **ffmpeg** joins the recordings of one test (a new browser tab has its own video) into one video for the report.
|
|
11
|
+
`pnpm go` installs it with Homebrew on macOS or winget on Windows; on Linux run `sudo apt install ffmpeg`. When it
|
|
12
|
+
is missing, the optional `ffmpeg-static` package is used instead; if neither works, the report lists the videos
|
|
13
|
+
separately. Not fatal.
|
|
14
|
+
- **Claude Code or OpenCode** for the AI steps (make cases, explore, generate, heal). Everything else works without
|
|
15
|
+
them; `pnpm go` warns when neither command is found.
|
|
16
|
+
|
|
17
|
+
## Install in a project
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm dlx @asrunjs/asrun init --install
|
|
21
|
+
pnpm go
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`init --install` scaffolds the workspace and then adds the dependency. Running `init` first matters on pnpm 12: it
|
|
25
|
+
writes `pnpm-workspace.yaml` with the `allowBuilds` entry (`esbuild` through `tsx`, `ffmpeg-static`), and without it
|
|
26
|
+
`pnpm add` exits with `ERR_PNPM_IGNORED_BUILDS`. An existing `pnpm-workspace.yaml` that lacks the entry gets a note
|
|
27
|
+
instead: add the block by hand (see "Manual install").
|
|
28
|
+
|
|
29
|
+
`pnpm go` then does the rest and is the command to remember:
|
|
30
|
+
|
|
31
|
+
1. checks Node (22+) and ffmpeg, and warns when no AI CLI is installed;
|
|
32
|
+
2. installs the dependencies and the Chromium browser (`pnpm install` + `playwright install chromium`);
|
|
33
|
+
3. runs `asrun init` (workspace files and `.env`) and `asrun doctor`;
|
|
34
|
+
4. starts the web UI at http://127.0.0.1:4173 and opens it.
|
|
35
|
+
|
|
36
|
+
Run it again on any day: the install step then takes seconds, and if the UI is already running it only opens it.
|
|
37
|
+
`pnpm go --no-open` does not open a browser. Set `ASRUN_UI_PORT` to change the port.
|
|
38
|
+
|
|
39
|
+
The UI is optional: all commands in [commands.md](./commands.md) work without it.
|
|
40
|
+
|
|
41
|
+
### Manual install
|
|
42
|
+
|
|
43
|
+
Same result, step by step:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm add -D @asrunjs/asrun
|
|
47
|
+
pnpm asrun init
|
|
48
|
+
pnpm go
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If pnpm refuses the build scripts of `esbuild` / `ffmpeg-static`, add this to `pnpm-workspace.yaml` and run the
|
|
52
|
+
install again:
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
allowBuilds:
|
|
56
|
+
esbuild: true
|
|
57
|
+
ffmpeg-static: true
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
To pin a version:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm add -D @asrunjs/asrun@<version>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`pnpm asrun init` is safe to run many times: it never overwrites a file the project owns.
|
|
67
|
+
|
|
68
|
+
## What `init` writes
|
|
69
|
+
|
|
70
|
+
| Kind | Files | On `--update` |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| Generated | `playwright.config.ts`, `tests/seed.spec.ts`, `.claude/commands/*`, `.opencode/commands/*` | rewritten |
|
|
73
|
+
| Once | `AGENTS.md`, `CLAUDE.md`, `.mcp.json`, `opencode.jsonc`, `.claude/settings.json`, `tsconfig.json`, `pnpm-workspace.yaml`, `profiles.yaml`, `cases/_template.md`, `package.json` (scripts and devDependencies merged in) | kept |
|
|
74
|
+
|
|
75
|
+
It also writes the asrun block in `.gitignore`, the `ASRUN_ROOT` line in `.env`, and `.asrun.json` (the marker with
|
|
76
|
+
the framework version and the generated file list).
|
|
77
|
+
|
|
78
|
+
Flags:
|
|
79
|
+
|
|
80
|
+
| Flag | Meaning |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `--root <dir>` | initialize that folder instead of the current one |
|
|
83
|
+
| `--update` | refresh only the generated files |
|
|
84
|
+
| `--force <path>` | overwrite one file init owns (repeatable) |
|
|
85
|
+
| `--reset-rules` | allow `--force` on `AGENTS.md`, `CLAUDE.md` or `.claude/skills/**` |
|
|
86
|
+
| `--no-env` | do not write `.env` |
|
|
87
|
+
| `--install [spec]` | also add the dependency (default `@asrunjs/asrun`) |
|
|
88
|
+
|
|
89
|
+
`AGENTS.md`, `CLAUDE.md` and `.claude/skills/**` belong to the project. `init --force` refuses them without
|
|
90
|
+
`--reset-rules`, so a framework update can never replace a project's rules.
|
|
91
|
+
|
|
92
|
+
## Update
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pnpm add -D @asrunjs/asrun@latest
|
|
96
|
+
pnpm asrun init --update
|
|
97
|
+
pnpm asrun doctor
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`init --update` rewrites only the generated files and leaves project rules, case files, values and baselines alone.
|
|
101
|
+
`doctor` tells you when the workspace is behind the installed version.
|
|
102
|
+
|
|
103
|
+
There is no folder to move: the framework lives in `node_modules`, which the package manager owns. To change the
|
|
104
|
+
framework itself, `pnpm patch @asrunjs/asrun` (a committed patch).
|
|
105
|
+
|
|
106
|
+
## `pnpm asrun doctor`
|
|
107
|
+
|
|
108
|
+
Run it after changing profiles, rules or overrides, and after an update. It checks:
|
|
109
|
+
|
|
110
|
+
- every entry in `profiles.yaml` (ids, environments, URLs, session check settings);
|
|
111
|
+
- `tsconfig.json`, `playwright.config.ts` (its re-export of the framework config) and the generated files;
|
|
112
|
+
- that `.gitignore` ignores `.auth/` and `reports/`;
|
|
113
|
+
- whether the installed version is behind the package's templates, and whether `dist/` is out of date;
|
|
114
|
+
- the project rule table in `AGENTS.md` §2 (unknown ids, a missing `Effect`, a non-negotiable rule);
|
|
115
|
+
- the framework skills and the project overrides under `.claude/skills/<skill>.md`, and lists the ones it sees.
|
|
116
|
+
|
|
117
|
+
## Which workspace a command runs against
|
|
118
|
+
|
|
119
|
+
The order is:
|
|
120
|
+
|
|
121
|
+
1. a real environment variable `ASRUN_ROOT` (it wins over everything);
|
|
122
|
+
2. `ASRUN_ROOT` in the `.env` next to the command, or in the framework package's own `.env` (relative to that file);
|
|
123
|
+
3. otherwise the nearest folder at or above the working directory that has `profiles.yaml` or `.asrun.json`;
|
|
124
|
+
4. in the framework repository, the framework's own `.env` points at `examples/demo`.
|
|
125
|
+
|
|
126
|
+
A real environment variable always wins, so one checkout can point at another project for a single command:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
ASRUN_ROOT=../my-real-project pnpm asrun --env staging --read-only
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Workspace layout
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
profiles.yaml one entry per environment: URL, account label, tags, environment (no expected values)
|
|
136
|
+
cases/ human-written cases (+ _template.md); optional group folders: cases/<group>/<name>.md
|
|
137
|
+
tests/ generated specs (same folders as cases/) and *-snapshots/ baselines per profile
|
|
138
|
+
playwright.config.ts re-exports node_modules/@asrunjs/asrun/dist/playwright.config.js
|
|
139
|
+
tsconfig.json plain compiler options (specs import the framework by package name)
|
|
140
|
+
AGENTS.md project rules: they point at the framework baseline; §2 says what differs
|
|
141
|
+
CLAUDE.md imports AGENTS.md for Claude Code
|
|
142
|
+
.claude/commands/ /make-case, /explore-case, /gen-spec, /heal-spec (thin shells that load the framework skill)
|
|
143
|
+
.claude/skills/ optional project overrides of a skill: <skill>.md
|
|
144
|
+
.opencode/commands/ the same commands for OpenCode (it does not read .claude/commands)
|
|
145
|
+
.mcp.json the playwright-test MCP server for Claude Code
|
|
146
|
+
opencode.jsonc the same for OpenCode, plus an optional model
|
|
147
|
+
.asrun.json marker: framework version and the generated file list
|
|
148
|
+
package.json the workspace scripts (`asrun`, `signin`, ...) and devDependencies
|
|
149
|
+
.env ASRUN_ROOT (which workspace the commands use) and local settings
|
|
150
|
+
node_modules/@asrunjs/asrun/ the framework (installed dependency; never edited)
|
|
151
|
+
.auth/ saved logins, one per profile
|
|
152
|
+
reports/ one folder per run; reports/latest points at the newest
|
|
153
|
+
.tmp/ .explore/ job logs, hints, reference screenshots (local state)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The framework repository's own layout is in [agents/framework-dev.md](./agents/framework-dev.md).
|
|
157
|
+
|
|
158
|
+
## What to commit
|
|
159
|
+
|
|
160
|
+
Commit `profiles.yaml`, `cases/`, `tests/` (with `*-snapshots/`), `AGENTS.md`, `CLAUDE.md`, `.claude/`,
|
|
161
|
+
`.opencode/commands/`, `.mcp.json`, `opencode.jsonc`, `.asrun.json`, the generated files, `package.json`, `tsconfig.json`
|
|
162
|
+
and `pnpm-workspace.yaml`.
|
|
163
|
+
|
|
164
|
+
Never commit or share `.auth/` (one saved login per profile, as sensitive as a password), `reports/`, `.tmp/`,
|
|
165
|
+
`.explore/`, `.env` or `node_modules/`. The asrun block of `.gitignore` covers them.
|
|
166
|
+
|
|
167
|
+
## Uninstall
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
pnpm remove @asrunjs/asrun
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Then delete the workspace files you no longer want (`profiles.yaml`, `cases/`, `tests/`, the generated commands and
|
|
174
|
+
configs, `.asrun.json`). They are ordinary files: keep them if another tool still uses them.
|
package/docs/profiles.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Profiles and environments
|
|
2
|
+
|
|
3
|
+
A **profile** is one environment of the system under test: a URL, an account label, optional tags and the environment
|
|
4
|
+
name. Each entry in `profiles.yaml` becomes one Playwright project named after its `id`, and every spec runs once per
|
|
5
|
+
profile. Two profiles of the same site give you two independent views, logins and baselines.
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
profiles:
|
|
9
|
+
- id: example-staging
|
|
10
|
+
name: Example (staging)
|
|
11
|
+
env: staging
|
|
12
|
+
baseURL: https://staging.example.com
|
|
13
|
+
account: qa@example.com
|
|
14
|
+
tags: [core, us]
|
|
15
|
+
email: false
|
|
16
|
+
startPath: /app/home
|
|
17
|
+
sessionCheckPath: /settings
|
|
18
|
+
sessionCheck:
|
|
19
|
+
loggedOutUrl: /login
|
|
20
|
+
loggedInSelector: "input[name='username']"
|
|
21
|
+
timeoutMs: 5000
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Fields
|
|
25
|
+
|
|
26
|
+
| Field | Meaning |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `id` | Lowercase words with single dashes. It names the Playwright project, the saved session (`.auth/<id>.json`) and the baseline files. |
|
|
29
|
+
| `name` | What people see in the UI and the reports. |
|
|
30
|
+
| `env` | The environment this profile points at (`production`, `staging`, ...). `--env <env>` selects the profiles of one environment. Any environment except `staging` protects writing: a case that writes there needs a person's confirmation on every run. |
|
|
31
|
+
| `baseURL` | The site address, without a path. Must be a full `http(s)` URL. |
|
|
32
|
+
| `account` | A label for humans (a mailbox or username). Never a password: logins live in `.auth/`. |
|
|
33
|
+
| `tags` | Optional lowercase words, for grouping and `pnpm asrun --tag <tag>`. Duplicates are refused. |
|
|
34
|
+
| `email` | `true` only when a real mailbox is connected, so tests may send email. Defaults to `false`; `true` is refused for `production`. |
|
|
35
|
+
| `startPath` | The page "Visit" opens after a login, for example `/app/home`. Empty (the default) opens the site root. A path on the site: one leading `/`, no spaces, never another host. |
|
|
36
|
+
| `sessionCheckPath` | A page a signed-in visitor sees (default `/account/`). "Verify" and the pre-run check use it to tell whether a saved login still works. |
|
|
37
|
+
| `sessionCheck` | How that page shows a missing login. See below. |
|
|
38
|
+
|
|
39
|
+
Expected values are **not** here. They live in each case's `## Values` block: `profiles.yaml` holds connection
|
|
40
|
+
settings only, so adding a profile never touches a case and two profiles can never fight over one case's values.
|
|
41
|
+
|
|
42
|
+
## There is no default environment
|
|
43
|
+
|
|
44
|
+
`pnpm asrun` and every AI command require `--env <env>`; the Run tests page requires one radio button. A run selects
|
|
45
|
+
the profiles whose `env` matches.
|
|
46
|
+
|
|
47
|
+
`pnpm signin <profile-id>` and `pnpm explore <profile-id>` take no `--env`: the profile already names its environment.
|
|
48
|
+
|
|
49
|
+
## Logins
|
|
50
|
+
|
|
51
|
+
Sessions are saved per profile in `.auth/<profile-id>.json`, one file per profile, and are as sensitive as passwords.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm signin example-staging
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A normal browser opens with a small card in its bottom-left corner. Log in yourself, including 2FA, wait for the
|
|
58
|
+
logged-in page, then press **Done, save the session** on the card (or press Enter in the terminal, which does the
|
|
59
|
+
same). The session is saved and verified. Nothing about 2FA is automated.
|
|
60
|
+
|
|
61
|
+
`pnpm status` shows the login state of every profile; `pnpm status --env staging` only of one environment.
|
|
62
|
+
|
|
63
|
+
Before every run, `pnpm asrun` checks the session of each profile in the chosen environment. A profile without a
|
|
64
|
+
saved session, or with an expired one, fails right away (no retries) and the run prints what to do:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Not logged in (tests for these profiles will FAIL):
|
|
68
|
+
example-production expired -> pnpm signin example-production
|
|
69
|
+
Or skip them for this run: pnpm asrun --env production --skip-profile example-production
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Either log in or leave the profile out (`--skip-profile`, or `--logged-in` to keep only the working ones). If a
|
|
73
|
+
session expires in the middle of a run, the failed test is marked "session expired".
|
|
74
|
+
|
|
75
|
+
Login itself is not a test case. Never write a spec for the login page or the login flow.
|
|
76
|
+
|
|
77
|
+
### Making the session check fit your site
|
|
78
|
+
|
|
79
|
+
The defaults fit a site that redirects a signed-out visitor to `/login`. Sites differ: a single-page app redirects
|
|
80
|
+
after it has started, some answer `401` or `403`, some show the login form at the same address. `sessionCheck` names
|
|
81
|
+
what your site does:
|
|
82
|
+
|
|
83
|
+
| Key | What it says |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `loggedOutUrl` | Where a signed-out visitor ends up (default `/login`): a path on the site or a full URL for single sign-on. A `401`/`403` response counts too. |
|
|
86
|
+
| `loggedInSelector` | A selector that only exists while signed in, for example `"input[name='username']"`. |
|
|
87
|
+
| `loggedOutSelector` | A selector that proves the visitor is signed out, for example the password field of a login form shown at the same address. |
|
|
88
|
+
| `timeoutMs` | How long to wait for one of those signals (default 3000, 500–60000). |
|
|
89
|
+
|
|
90
|
+
Without a `loggedInSelector`, "not sent to the login page" counts as signed in, which can mislead on a slow
|
|
91
|
+
single-page app.
|
|
92
|
+
|
|
93
|
+
## Visit and explore
|
|
94
|
+
|
|
95
|
+
**Visit** (Profiles page, or `pnpm explore <profile-id> [path]`) opens a logged-in browser window at the profile's
|
|
96
|
+
`startPath`, or at the site root when it is empty. Files downloaded in that window go to `~/Downloads` (an existing
|
|
97
|
+
file is never overwritten; a ` (1)` is added) and the saved path is printed in the terminal or the job log.
|
|
98
|
+
|
|
99
|
+
Use it when you need to see what a logged-in person sees, without writing anything. The exploring agent uses the same
|
|
100
|
+
mechanism, with the Playwright MCP server and the profile's project.
|
|
101
|
+
|
|
102
|
+
## Adding a profile
|
|
103
|
+
|
|
104
|
+
1. Add an entry to `profiles.yaml` (or use **Add a new profile** on the Profiles page, which appends it for you).
|
|
105
|
+
2. `pnpm signin <id>` and log in.
|
|
106
|
+
3. Add the values for that profile to the cases it runs: a column in each `## Values` block, or nothing when
|
|
107
|
+
`default` already fits.
|
|
108
|
+
|
|
109
|
+
Deleting a profile removes its entry and its saved login; screenshot baselines and old reports keep the id in their
|
|
110
|
+
file names and stay on disk. Duplicating one copies the settings under a new id and does **not** copy the saved login.
|
|
111
|
+
|
|
112
|
+
## How a profile becomes a test
|
|
113
|
+
|
|
114
|
+
The profile id is the Playwright project name. The `profile` fixture exposes the running profile to a spec:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// case: cases/example.md
|
|
118
|
+
import {caseTags} from '@asrunjs/asrun/cases';
|
|
119
|
+
import {configureCase, expect, test} from '@asrunjs/asrun/fixtures';
|
|
120
|
+
import {requireValues} from '@asrunjs/asrun/values';
|
|
121
|
+
|
|
122
|
+
test.describe('Example', {tag: caseTags('example')}, () => {
|
|
123
|
+
configureCase('example');
|
|
124
|
+
test('one outcome', async ({page, profile}) => {
|
|
125
|
+
// profile.id, profile.env, profile.baseURL, profile.account, profile.tags, profile.email
|
|
126
|
+
const expected = requireValues<{homeTitle: string}>('example', profile);
|
|
127
|
+
await test.step('1. Open the home page', async () => {
|
|
128
|
+
await page.goto('/');
|
|
129
|
+
await expect(page).toHaveTitle(expected.homeTitle);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Expected values come from the case document through `requireValues(caseId, profile)`: its `## Values` block with
|
|
136
|
+
`default` deep-merged under the profile's own entry. A case with no values for the running profile, or with empty or
|
|
137
|
+
`TODO` values, fails with a plain-language message instead of a crash.
|
|
138
|
+
|
|
139
|
+
See [cases.md](./cases.md) for the document format and [commands.md](./commands.md) for the run filters.
|