A coding agent could develop this repo's Go packages and could not develop the application: every path to running YellowJacket ended in a blocking GTK window, so 265 bound methods, 46 events, 33 component directories and 13 stores had exactly one form of verification available — `tsc --noEmit`. The unlock is that `wails dev`'s dev server on :34115 serves the real frontend with the real generated bindings against the same Go backend a desktop window attaches to, so a plain Chromium under Xvfb gets a fully functional app. Four test tiers now exist, cheapest first: - `make ui-test` — 313 Vitest tests in a real browser in ~2 s, no app, no backend, no display. Works because `frontend/wailsjs/` is a pure passthrough to `window.go`/`window.runtime`, so faking just those two globals runs the real bindings and the real store code. - `make test` — services in-process, asserting on the payload the frontend would receive, via a new `events.Emit` wrapper. - `make dev-headless` + `playwright-cli` — the real app, driven interactively, with an event bridge on `window.__yjEvents` and a dev-only control surface at `/__test/`. - `make e2e` — 19 of those flows frozen as Playwright specs. `events.Emit(ctx, …)` replaces all 35 direct `runtime.EventsEmit` call sites: wails' `getEvents` `log.Fatalf`s on any context without its runtime, so those paths could not run under test and a background worker could take the app down. Four packages had each hand-rolled the same guard; nine more guarded on `ctx != nil`, which does not help. `TestNoDirectRuntimeEmits` fails the build on a new one. Fixtures are generated, not committed (`make testdata`), and seeds are built by *running the app* — never by hand-writing config and DB rows, which would be a second description of a valid YJ_HOME. `.gitea/workflows/ci.yml` is the first workflow here that tests anything; the other three only package, so `gitea_ci` reported only packaging jobs and misled anyone asking whether a push was healthy. Both jobs were prototyped to green in a bare ubuntu:24.04 container before the YAML was written, which immediately caught `make lint` linting three configurations that nothing builds: all three passes omitted `webkit2_41`, so wails resolved webkit2gtk-4.0 — which Arch still ships and Ubuntu 24.04 dropped. Operational instructions live in `.pi/skills/yellowjacket-dev/`, measured discoveries in `.planning/NOTES.md`, and architecture in `CLAUDE.md` — split by tense, not by topic, because a topical split gives every new fact two plausible homes. `make skill-check` fails a commit if the skill cites a make target that does not exist.
276 lines
5.1 KiB
Markdown
276 lines
5.1 KiB
Markdown
# Storage Management
|
|
|
|
Manage cookies, localStorage, sessionStorage, and browser storage state.
|
|
|
|
## Storage State
|
|
|
|
Save and restore complete browser state including cookies and storage.
|
|
|
|
### Save Storage State
|
|
|
|
```bash
|
|
# Save to auto-generated filename (storage-state-{timestamp}.json)
|
|
playwright-cli state-save
|
|
|
|
# Save to specific filename
|
|
playwright-cli state-save my-auth-state.json
|
|
```
|
|
|
|
### Restore Storage State
|
|
|
|
```bash
|
|
# Load storage state from file
|
|
playwright-cli state-load my-auth-state.json
|
|
|
|
# Reload page to apply cookies
|
|
playwright-cli open https://example.com
|
|
```
|
|
|
|
### Storage State File Format
|
|
|
|
The saved file contains:
|
|
|
|
```json
|
|
{
|
|
"cookies": [
|
|
{
|
|
"name": "session_id",
|
|
"value": "abc123",
|
|
"domain": "example.com",
|
|
"path": "/",
|
|
"expires": 1893456000,
|
|
"httpOnly": true,
|
|
"secure": true,
|
|
"sameSite": "Lax"
|
|
}
|
|
],
|
|
"origins": [
|
|
{
|
|
"origin": "https://example.com",
|
|
"localStorage": [
|
|
{ "name": "theme", "value": "dark" },
|
|
{ "name": "user_id", "value": "12345" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Cookies
|
|
|
|
### List All Cookies
|
|
|
|
```bash
|
|
playwright-cli cookie-list
|
|
```
|
|
|
|
### Filter Cookies by Domain
|
|
|
|
```bash
|
|
playwright-cli cookie-list --domain=example.com
|
|
```
|
|
|
|
### Filter Cookies by Path
|
|
|
|
```bash
|
|
playwright-cli cookie-list --path=/api
|
|
```
|
|
|
|
### Get Specific Cookie
|
|
|
|
```bash
|
|
playwright-cli cookie-get session_id
|
|
```
|
|
|
|
### Set a Cookie
|
|
|
|
```bash
|
|
# Basic cookie
|
|
playwright-cli cookie-set session abc123
|
|
|
|
# Cookie with options
|
|
playwright-cli cookie-set session abc123 --domain=example.com --path=/ --httpOnly --secure --sameSite=Lax
|
|
|
|
# Cookie with expiration (Unix timestamp)
|
|
playwright-cli cookie-set remember_me token123 --expires=1893456000
|
|
```
|
|
|
|
### Delete a Cookie
|
|
|
|
```bash
|
|
playwright-cli cookie-delete session_id
|
|
```
|
|
|
|
### Clear All Cookies
|
|
|
|
```bash
|
|
playwright-cli cookie-clear
|
|
```
|
|
|
|
### Advanced: Multiple Cookies or Custom Options
|
|
|
|
For complex scenarios like adding multiple cookies at once, use `run-code`:
|
|
|
|
```bash
|
|
playwright-cli run-code "async page => {
|
|
await page.context().addCookies([
|
|
{ name: 'session_id', value: 'sess_abc123', domain: 'example.com', path: '/', httpOnly: true },
|
|
{ name: 'preferences', value: JSON.stringify({ theme: 'dark' }), domain: 'example.com', path: '/' }
|
|
]);
|
|
}"
|
|
```
|
|
|
|
## Local Storage
|
|
|
|
### List All localStorage Items
|
|
|
|
```bash
|
|
playwright-cli localstorage-list
|
|
```
|
|
|
|
### Get Single Value
|
|
|
|
```bash
|
|
playwright-cli localstorage-get token
|
|
```
|
|
|
|
### Set Value
|
|
|
|
```bash
|
|
playwright-cli localstorage-set theme dark
|
|
```
|
|
|
|
### Set JSON Value
|
|
|
|
```bash
|
|
playwright-cli localstorage-set user_settings '{"theme":"dark","language":"en"}'
|
|
```
|
|
|
|
### Delete Single Item
|
|
|
|
```bash
|
|
playwright-cli localstorage-delete token
|
|
```
|
|
|
|
### Clear All localStorage
|
|
|
|
```bash
|
|
playwright-cli localstorage-clear
|
|
```
|
|
|
|
### Advanced: Multiple Operations
|
|
|
|
For complex scenarios like setting multiple values at once, use `run-code`:
|
|
|
|
```bash
|
|
playwright-cli run-code "async page => {
|
|
await page.evaluate(() => {
|
|
localStorage.setItem('token', 'jwt_abc123');
|
|
localStorage.setItem('user_id', '12345');
|
|
localStorage.setItem('expires_at', Date.now() + 3600000);
|
|
});
|
|
}"
|
|
```
|
|
|
|
## Session Storage
|
|
|
|
### List All sessionStorage Items
|
|
|
|
```bash
|
|
playwright-cli sessionstorage-list
|
|
```
|
|
|
|
### Get Single Value
|
|
|
|
```bash
|
|
playwright-cli sessionstorage-get form_data
|
|
```
|
|
|
|
### Set Value
|
|
|
|
```bash
|
|
playwright-cli sessionstorage-set step 3
|
|
```
|
|
|
|
### Delete Single Item
|
|
|
|
```bash
|
|
playwright-cli sessionstorage-delete step
|
|
```
|
|
|
|
### Clear sessionStorage
|
|
|
|
```bash
|
|
playwright-cli sessionstorage-clear
|
|
```
|
|
|
|
## IndexedDB
|
|
|
|
### List Databases
|
|
|
|
```bash
|
|
playwright-cli run-code "async page => {
|
|
return await page.evaluate(async () => {
|
|
const databases = await indexedDB.databases();
|
|
return databases;
|
|
});
|
|
}"
|
|
```
|
|
|
|
### Delete Database
|
|
|
|
```bash
|
|
playwright-cli run-code "async page => {
|
|
await page.evaluate(() => {
|
|
indexedDB.deleteDatabase('myDatabase');
|
|
});
|
|
}"
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Authentication State Reuse
|
|
|
|
```bash
|
|
# Step 1: Login and save state
|
|
playwright-cli open https://app.example.com/login
|
|
playwright-cli snapshot
|
|
playwright-cli fill e1 "user@example.com"
|
|
playwright-cli fill e2 "password123"
|
|
playwright-cli click e3
|
|
|
|
# Save the authenticated state
|
|
playwright-cli state-save auth.json
|
|
|
|
# Step 2: Later, restore state and skip login
|
|
playwright-cli state-load auth.json
|
|
playwright-cli open https://app.example.com/dashboard
|
|
# Already logged in!
|
|
```
|
|
|
|
### Save and Restore Roundtrip
|
|
|
|
```bash
|
|
# Set up authentication state
|
|
playwright-cli open https://example.com
|
|
playwright-cli eval "() => { document.cookie = 'session=abc123'; localStorage.setItem('user', 'john'); }"
|
|
|
|
# Save state to file
|
|
playwright-cli state-save my-session.json
|
|
|
|
# ... later, in a new session ...
|
|
|
|
# Restore state
|
|
playwright-cli state-load my-session.json
|
|
playwright-cli open https://example.com
|
|
# Cookies and localStorage are restored!
|
|
```
|
|
|
|
## Security Notes
|
|
|
|
- Never commit storage state files containing auth tokens
|
|
- Add `*.auth-state.json` to `.gitignore`
|
|
- Delete state files after automation completes
|
|
- Use environment variables for sensitive data
|
|
- By default, sessions run in-memory mode which is safer for sensitive operations
|