Skip to content

Commit ffc30d9

Browse files
committed
Add seeders, wait helpers, click() debug recipe, and screenshot details
Document the empty-DB seeding pattern for visual review of feed/list pages, the HasWaitCapabilities helpers for SPA/Inertia transitions, the click() timeout splitting recipe, the screenshot signature with fullPage caveat, the resize() vs on()->mobile() precedence, and script() return-value debugging. Correct the screenshot output path to tests/Browser/Screenshots/ and soften the blanket delete-screenshots rule for design-review workflows.
1 parent 8417316 commit ffc30d9

1 file changed

Lines changed: 54 additions & 5 deletions

File tree

  • resources/boost/skills/pest-plugin-ai

resources/boost/skills/pest-plugin-ai/SKILL.md

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ It then runs with the project's normal Pest configuration (Feature and Browser n
2929
- **Use the documented browser API exactly.** Methods like `onMobile()` or `mobileView()` do not exist — the chain is `->on()->mobile()`, `->on()->iPhone14Pro()`, or `->resize(w, h)`. If a method is not shown in this skill, do not invent it.
3030
- **Do not replace real tests with `--ai`.** This is a verification probe, not a way to skip writing tests. If the behavior is worth a regression guard, write a proper test file.
3131
- **Do not paper over missing setup.** If a check fails because a factory, seeder, or migration is missing, stop and ask the user to add it. Do not bend `--ai` invocations into fixtures.
32-
- **Delete screenshots after reviewing them.** They land in the project root and clutter the repo if left behind.
33-
- **Quote the snippet so the shell preserves PHP syntax.** Use double quotes outside, single quotes inside, and escape `$` as `\$` so the shell does not interpolate variables.
32+
- **Manage screenshot churn.** Screenshots land in `tests/Browser/Screenshots/`. Delete throwaway smoke screenshots once you've eyeballed them; for design-review workflows, keep them in a gitignored folder under that directory if you'll reference them across runs.
33+
- **Quote the snippet so the shell preserves PHP syntax.** Use double quotes outside, single quotes inside, and escape `$` as `\$` so the shell does not interpolate variables. For snippets with JS template literals or nested quotes, write a `.php` file under `/tmp` and run `vendor/bin/pest /tmp/foo.php` instead — the `--ai` shell-quoting wall hits fast.
3434

3535
## Backend verification
3636

@@ -54,6 +54,16 @@ Mail, notifications, and queued jobs work via the standard fakes:
5454
vendor/bin/pest --ai="\Illuminate\Support\Facades\Mail::fake(); \App\Models\User::factory()->create()->notify(new \App\Notifications\Welcome()); \Illuminate\Support\Facades\Notification::assertSentTo(...);"
5555
```
5656

57+
### Seeding for pages that need data
58+
59+
The in-memory test DB starts empty on every run, so visual review of feed/list/dashboard pages will render the empty state unless you seed first. Run a seeder inline before visiting:
60+
61+
```bash
62+
vendor/bin/pest --ai="\$this->seed(\Database\Seeders\DemoSeeder::class); visit('/')->screenshot(filename: 'home');"
63+
```
64+
65+
If the page still looks empty after seeding, the seeder probably isn't writing to the same connection the test sees — check `phpunit.xml` for the test DB configuration.
66+
5767
## Frontend and browser verification
5868

5969
Browser features come from `pestphp/pest-plugin-browser`. Full API reference: https://pestphp.com/docs/browser-testing. If `visit()` is undefined, install it first:
@@ -64,9 +74,20 @@ npm install playwright@latest
6474
npx playwright install
6575
```
6676

67-
Use relative paths in `visit()`. Pest resolves them against the app URL. Always pass a descriptive `filename:` to screenshots so the file is easy to locate (and delete) afterwards. After any Blade, Livewire, CSS, or JS change, reach for these to visually confirm the result.
77+
Use relative paths in `visit()`. Pest resolves them against the app URL. Always pass a descriptive `filename:` to screenshots so the file is easy to locate afterwards — without it, the file defaults to `it_verify.png` and gets overwritten on every run. After any Blade, Livewire, CSS, or JS change, reach for these to visually confirm the result.
78+
79+
**Screenshot signature: `screenshot(bool $fullPage = true, ?string $filename = null)`.** First positional arg is `$fullPage`, not the filename. Passing a path as the first arg throws `Argument #1 ($fullPage) must be of type bool, string given`. Always use named args, and note that `fullPage: true` (the default) produces very tall captures on long pages — pass `fullPage: false` for above-the-fold review.
6880

69-
**`screenshot()`'s first positional argument is `$fullPage` (bool), not the filename.** `screenshot('/tmp/foo.png')` throws `Argument #1 ($fullPage) must be of type bool, string given`. Always pass the filename as a named argument: `screenshot(filename: 'foo')`. You cannot redirect screenshots to an arbitrary path — they always land in the project root with the given filename.
81+
```php
82+
// ✓ named args
83+
visit('/')->screenshot(filename: 'home'); // → tests/Browser/Screenshots/home.png
84+
visit('/')->screenshot(fullPage: false, filename: 'home'); // viewport only
85+
86+
// ✗ positional path — runtime TypeError
87+
visit('/')->screenshot('/tmp/home.png');
88+
```
89+
90+
You cannot redirect screenshots to an arbitrary path — they always land in `tests/Browser/Screenshots/` with the given filename.
7091

7192
### Smoke screenshots
7293

@@ -96,13 +117,41 @@ vendor/bin/pest --ai="visit('/')->on()->iPhone14Pro()->screenshot(filename: 'hom
96117
vendor/bin/pest --ai="visit('/')->resize(375, 812)->screenshot(filename: 'home-375x812');"
97118
```
98119

120+
`resize()` after `on()->mobile()` overrides the device's width — pick one. Use `on()->...()` for device emulation (user agent, touch, DPR), `resize()` for raw viewport sizing.
121+
99122
### Interaction flows
100123

101124
```bash
102125
vendor/bin/pest --ai="visit('/')->click('Login')->assertPathIs('/login');"
103126
vendor/bin/pest --ai="visit('/contact')->type('email', 'test@example.com')->press('Send')->assertSee('Message sent');"
104127
```
105128

129+
#### Debugging a `click()` timeout
130+
131+
If `click()` times out, the click likely succeeded but Pest is waiting for a navigation that didn't happen — for example, a guarded route that bounced you back. Don't reach for a longer wait. Split the chain and inspect where you actually landed:
132+
133+
```bash
134+
vendor/bin/pest --ai="\$page = visit('/'); \$page->click('Open dashboard'); \$page->screenshot(filename: 'after-click'); dump(\$page->script('location.href'));"
135+
```
136+
137+
### Waiting for SPA / Inertia transitions
138+
139+
For Inertia, Livewire, or other client-rendered transitions, the page may not be ready when the next assertion runs. Use the wait helpers from `HasWaitCapabilities` instead of bare assertions:
140+
141+
```bash
142+
vendor/bin/pest --ai="visit('/')->click('Open dashboard')->waitForLocation('/dashboard')->assertSee('Welcome');"
143+
vendor/bin/pest --ai="visit('/feed')->waitForText('Latest posts')->screenshot(filename: 'feed');"
144+
vendor/bin/pest --ai="visit('/feed')->waitFor('[data-feed-loaded]')->screenshot(filename: 'feed');"
145+
```
146+
147+
### Reading values back from the page
148+
149+
`$page->script('<expr>')` evaluates JavaScript in the page and returns the JSON-decoded result as `mixed` — useful for debugging:
150+
151+
```bash
152+
vendor/bin/pest --ai="\$page = visit('/'); dump(\$page->script('document.title')); dump(\$page->script('location.href'));"
153+
```
154+
106155
### Health checks
107156

108157
JavaScript errors, accessibility, and visual drift:
@@ -143,7 +192,7 @@ If a check fails with "no such table" or similar, look in `tests/Pest.php` for a
143192
- **Every failure reports the test name as `verify`.** If you batch checks into one snippet, the failure will not tell you which one broke. Keep snippets focused on a single behavior.
144193
- **Traits cannot be added inline.** `RefreshDatabase`, `WithFaker`, and similar traits must be wired through `tests/Pest.php` `uses()`. The snippet inherits whatever is already configured.
145194
- **Browser tests need a reachable app.** `visit('/foo')` hits the configured app URL, so make sure `php artisan serve` (or your usual dev server) is running, or the browser plugin's built-in server is configured.
146-
- **Screenshots persist on failure too.** A failed assertion still leaves the PNG in the project root. Sweep them up regardless of outcome.
195+
- **Screenshots persist on failure too.** A failed assertion still leaves the PNG in `tests/Browser/Screenshots/`. Sweep them up regardless of outcome. Without `filename:`, they overwrite each other as `it_verify.png`.
147196
- **Shell escaping bites.** Backticks, `!` (in zsh history), and `$` are all interpreted before PHP sees them. Escape `$` as `\$`, avoid `!`, and prefer single quotes inside the snippet (`'foo'`) over double.
148197

149198
## When NOT to use

0 commit comments

Comments
 (0)