You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
description: One-shot Pest verification CLI for Laravel/PHP agents. Use whenever the user wants to quickly check that a change actually works — hitting a route, asserting a model relationship or factory, checking a queued job/mail/notification fires, screenshotting a page, asserting visible content, testing a click or form submission, checking for JavaScript errors, asserting accessibility, doing visual regression, or testing responsive layouts. Triggers include "verify this works", "did my change break X", "screenshot the homepage", "check this route returns 200", "make sure the mail fires", "test the login form", "see if the page renders", "check it on mobile", "is the form working", or any one-off behavioral check on a Laravel app that does not warrant a permanent test file. Also use after any Blade/Livewire/CSS/JS change to visually confirm the result. opening tinker for behavioral checks, hitting endpoints with curl, or eyeballing the browser yourself.
3
+
description: One-shot Pest verification CLI for Laravel and PHP agents. Use whenever the user wants to quickly check that a change actually works, including hitting a route, asserting a model relationship or factory, checking a queued job, mail, or notification fires, screenshotting a page, asserting visible content, testing a click or form submission, checking for JavaScript errors, asserting accessibility, doing visual regression, or testing responsive layouts. Triggers include "verify this works", "did my change break X", "screenshot the homepage", "check this route returns 200", "make sure the mail fires", "test the login form", "see if the page renders", "check it on mobile", "is the form working", or any one-off behavioral check on a Laravel app that does not warrant a permanent test file. Also use after any Blade, Livewire, CSS, or JS change to visually confirm the result. Prefer `vendor/bin/pest --ai="<code>"` over writing throwaway test files, opening tinker for behavioral checks, hitting endpoints with curl, or eyeballing the browser manually.
4
4
---
5
5
6
6
# pest-plugin-ai
7
7
8
-
One-shot Pest verification for AI agents. Wrap any PHP snippet in
9
-
`vendor/bin/pest --ai="<code>"` and Pest creates a temporary test, runs it,
10
-
and deletes it. The snippet lives inside `it('verify', function () { ... })`,
11
-
so use Pest's expectation API and any helpers available in the test suite
One-shot Pest verification for AI agents. Wrap any PHP snippet in `vendor/bin/pest --ai="<code>"`. Pest creates a temporary test, runs it, and deletes it. The snippet lives inside `it('verify', function () { ... })`, so use Pest's expectation API and any helpers available in the test suite (`visit()`, `actingAs()`, `Mail::fake()`, factories, and so on).
13
9
14
10
## How it works
15
11
16
-
`pest --ai="<code>"` writes a temp file like:
12
+
`pest --ai="<code>"` writes a temp file shaped like this:
17
13
18
14
```php
19
15
<?php
16
+
20
17
it('verify', function () {
21
-
<code>
18
+
/* your snippet goes here */
22
19
});
23
20
```
24
21
25
-
Then runs it with the project's normal Pest configuration (Feature/Browser
26
-
namespace `uses`, traits applied via `tests/Pest.php`, etc.) and cleans up
27
-
afterwards. Because the file has **no `use` imports**, every class must be
28
-
fully qualified.
22
+
It then runs with the project's normal Pest configuration (Feature and Browser namespace `uses`, traits applied via `tests/Pest.php`) and cleans up afterwards. The file has **no `use` imports**, so every class must be fully qualified.
29
23
30
24
## Critical rules
31
25
32
-
-**Always use `vendor/bin/pest`**, never bare `pest`. The bare command often
33
-
isn't on `PATH` and you'll get "command not found" instead of a real result.
34
-
-**Always fully qualify class names**: `\App\Models\User`, `\Illuminate\Support\Facades\Mail`,
35
-
`\App\Notifications\WelcomeNotification`. The generated test has no
36
-
`use` statements, so unqualified names will throw `Class "User" not found`.
37
-
-**Don't replace real tests with `--ai`**. This is a verification probe, not a
38
-
way to skip writing tests. If the behavior is worth keeping a regression
39
-
guard on, write a proper test file.
40
-
-**Don't paper over missing setup.** If a check fails because a factory,
41
-
seeder, or migration is missing, stop and ask the user to add it. Don't
42
-
bend `--ai` invocations into fixtures.
43
-
-**Delete screenshots after reviewing them.** They land in the project root
44
-
and clutter the repo if left behind.
45
-
-**Quote the snippet so the shell preserves PHP syntax.** Use double quotes
46
-
on the outside and single quotes inside (or escape `$` as `\$` if you need
47
-
shell interpolation suppressed).
26
+
-**Use `vendor/bin/pest`, never bare `pest`.** The bare command often is not on `PATH` and produces "command not found" instead of a real result.
27
+
-**Fully qualify every class name:**`\App\Models\User`, `\Illuminate\Support\Facades\Mail`, `\App\Notifications\WelcomeNotification`. The generated test has no `use` statements, so unqualified names throw `Class "User" not found`.
28
+
-**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.
29
+
-**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.
30
+
-**Delete screenshots after reviewing them.** They land in the project root and clutter the repo if left behind.
31
+
-**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.
48
32
49
33
## Backend verification
50
34
51
-
Use factories to seed state inside the snippet — don't rely on existing data.
35
+
Seed state with factories inside the snippet. Do not rely on existing data.
Use relative paths in `visit()` — Pest resolves them against the app URL.
83
-
Always pass a descriptive `filename:` to screenshots so the file is easy to
84
-
locate (and delete) afterwards. After any Blade/Livewire/CSS/JS change,
85
-
reach for these to visually confirm the result.
65
+
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.
The most powerful pattern: drive the UI, then assert the side effect. Always
129
-
assert a frontend signal first (`assertSee`, `assertPathIs`) so you know the
130
-
action was processed before checking what it touched on the backend.
112
+
Drive the UI, then assert the side effect. Always assert a frontend signal first (`assertSee`, `assertPathIs`) so you know the action was processed before checking what it touched on the backend.
If a check fails with "no such table" or similar, look in `tests/Pest.php` for a commented `RefreshDatabase` line, for example `// uses(RefreshDatabase::class)->in('Feature');`.
149
129
150
-
**Do not silently uncomment it.** Ask the user first. If the project's test
151
-
database is persistent (anything other than SQLite `:memory:`), enabling
152
-
`RefreshDatabase` will wipe it on every run. Confirm the test DB is in-memory
153
-
or otherwise expendable before flipping the switch.
130
+
**Do not silently uncomment it.** Ask the user first. If the project's test database is persistent (anything other than SQLite `:memory:`), enabling `RefreshDatabase` wipes it on every run. Confirm the test database is in-memory or otherwise expendable before flipping the switch.
154
131
155
132
## Pitfalls
156
133
157
-
-**`use` inside the snippet is invalid.** The code runs inside a closure body — namespace imports must happen at file top, which you don't control. Always FQCN.
158
-
-**`__DIR__`/`__FILE__` resolve to `/tmp`**, not your tests folder. Don't read fixtures by relative path; pass absolute paths or use `base_path()`/`storage_path()`.
159
-
-**One `--ai` per invocation.**You can't chain multiple verifications in a single command. Run them separately.
160
-
-**Every failure reports the test name as `verify`.** If you batch checks into one snippet, the failure won't tell you which one broke. Keep snippets focused on a single behavior.
161
-
-**Traits can't be added inline.**`RefreshDatabase`, `WithFaker`, etc. must be wired through `tests/Pest.php``uses()`; the snippet inherits whatever is already configured.
162
-
-**Browser tests need a reachable app.**`visit('/foo')` hits the configured app URL — make sure `php artisan serve` (or your usual dev server) is running, or the browser plugin's built-in server is configured.
134
+
-**`use` inside the snippet is invalid.** The code runs inside a closure body, so namespace imports must happen at file top, which you do not control. Always use fully qualified class names.
135
+
-**`__DIR__`and`__FILE__` resolve to `/tmp`**, not the tests folder. Do not read fixtures by relative path. Pass absolute paths or use `base_path()`and`storage_path()`.
136
+
-**One `--ai` per invocation.**Multiple verifications cannot be chained in a single command. Run them separately.
137
+
-**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.
138
+
-**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.
139
+
-**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.
163
140
-**Screenshots persist on failure too.** A failed assertion still leaves the PNG in the project root. Sweep them up regardless of outcome.
164
-
-**Shell escaping bites.** Backticks, `!` (in zsh), and `$`will all be interpreted before PHP sees them. Escape `$` as `\$`, avoid `!`, and prefer single quotes inside the snippet (`'foo'`) over double.
141
+
-**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.
165
142
166
143
## When NOT to use
167
144
168
-
- The behavior deserves a permanent regression guard → write a real test file
169
-
in `tests/Feature` or `tests/Browser`.
170
-
- The check needs more than ~3 statements or any helper function → write a
171
-
real test file; long shell-quoted snippets are painful to read and edit.
172
-
- The user is asking for a fix or refactor, not a verification → use the
173
-
appropriate edit/test workflow, not `--ai`.
145
+
- The behavior deserves a permanent regression guard. Write a real test file in `tests/Feature` or `tests/Browser` instead.
146
+
- The check needs more than roughly three statements or any helper function. Long shell-quoted snippets are painful to read and edit; write a real test file.
147
+
- The user is asking for a fix or refactor, not a verification. Use the appropriate edit and test workflow, not `--ai`.
0 commit comments