Output:
Chunk ID: 8e504f
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 156
Output:
[2026-05-04-codex-5-5-goal fbfedc5c] Add admin catalog API endpoints
 10 files changed, 592 insertions(+), 5 deletions(-)
 create mode 100644 app/Http/Controllers/Api/Admin/V1/CustomerController.php
 create mode 100644 app/Http/Controllers/Api/Admin/V1/ProductController.php
 create mode 100644 app/Http/Controllers/Api/Apps/V1/DeferredEndpointController.php
 create mode 100644 app/Http/Controllers/Api/OAuthController.php
 create mode 100644 app/Http/Resources/Admin/V1/CustomerResource.php
 create mode 100644 app/Http/Resources/Admin/V1/ProductResource.php
 create mode 100644 tests/Feature/Api/AdminCatalogApiTest.php


The admin catalog API slice is committed as `fbfedc5c`. I’m checking the remaining gaps again and will pick the next one that can reduce the open issue list without destabilizing the finished paths.


rg -n "browser tests|tests/Browser|Pest browser|visit\(|assertNoJavaScriptErrors|Playwright|Dusk|e2e" composer.json phpunit.xml tests specs/08-PLAYWRIGHT-E2E-PLAN.md


/bin/zsh
-lc
sed -n '381,395p' specs/progress.md

- Outbound webhook delivery jobs are forced onto the database queue and `webhooks` queue name so domain events enqueue delivery work instead of making external HTTP requests inline when the default queue connection is `sync`.
- Webhook signatures follow the security spec message shape of `{timestamp}.{json_body}` with HMAC-SHA256, while the delivery payload is wrapped with `id`, `api_version`, `event_type`, `store_id`, `occurred_at`, and `data`.
- Webhook circuit breaker state is derived from the latest five delivery rows for a subscription because the schema does not include a dedicated consecutive-failure counter column.
- Customer password resets use a custom store-scoped service instead of Laravel's stock password broker token repository because the `customer_password_reset_tokens` table includes `store_id` in the primary key and the stock repository does not write tenant columns.
- Customer password reset pages are routed under `/account/forgot-password` and `/account/reset-password/{token}` so the existing Fortify starter/admin root routes (`/forgot-password`, `/reset-password/{token}`) remain intact.
- Product media uploads use Livewire temporary file uploads on the existing product form, create `ProductMedia` rows in `processing` status, and dispatch the existing `ProcessMediaUpload` job instead of adding a second media-processing path.
- Resource policies now type concrete model parameters for Product, Collection, Customer, Discount, Order, Fulfillment, Refund, Page, and Theme actions; `ChecksStoreRole::storeIdForModel()` stays generic because it is the shared store-id extraction helper.

## Open Issues

- Customer password reset is implemented under `/account/forgot-password` and `/account/reset-password/{token}`; the exact spec root paths remain occupied by the existing Fortify starter/admin reset routes.
- `php artisan route:list --except-vendor` hides Livewire full-page routes because their controller is vendor-provided; path-filtered route-list commands are used as evidence for those routes.
- Non-order admin REST write endpoints and the larger admin REST surfaces for collections, discounts, settings, themes, content, search, analytics, and exports are still missing; outbound webhook subscription management is implemented through the admin UI only, as specified for the initial implementation.
- Automated browser tests from Spec 08 are still missing; current browser coverage is manual Playwright MCP smoke verification.
- SQLite enum/check constraints from the schema spec are not yet explicitly enforced as database `CHECK` constraints; enum validation is currently enforced through casts/services/model invariants.


Output:
Chunk ID: 26cc27
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 0
Output:


Output:
Chunk ID: f4d922
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 669
Output:
- Outbound webhook delivery jobs are forced onto the database queue and `webhooks` queue name so domain events enqueue delivery work instead of making external HTTP requests inline when the default queue connection is `sync`.
- Webhook signatures follow the security spec message shape of `{timestamp}.{json_body}` with HMAC-SHA256, while the delivery payload is wrapped with `id`, `api_version`, `event_type`, `store_id`, `occurred_at`, and `data`.
- Webhook circuit breaker state is derived from the latest five delivery rows for a subscription because the schema does not include a dedicated consecutive-failure counter column.
- Customer password resets use a custom store-scoped service instead of Laravel's stock password broker token repository because the `customer_password_reset_tokens` table includes `store_id` in the primary key and the stock repository does not write tenant columns.
- Customer password reset pages are routed under `/account/forgot-password` and `/account/reset-password/{token}` so the existing Fortify starter/admin root routes (`/forgot-password`, `/reset-password/{token}`) remain intact.
- Product media uploads use Livewire temporary file uploads on the existing product form, create `ProductMedia` rows in `processing` status, and dispatch the existing `ProcessMediaUpload` job instead of adding a second media-processing path.
- Resource policies now type concrete model parameters for Product, Collection, Customer, Discount, Order, Fulfillment, Refund, Page, and Theme actions; `ChecksStoreRole::storeIdForModel()` stays generic because it is the shared store-id extraction helper.

## Open Issues

- Customer password reset is implemented under `/account/forgot-password` and `/account/reset-password/{token}`; the exact spec root paths remain occupied by the existing Fortify starter/admin reset routes.
- `php artisan route:list --except-vendor` hides Livewire full-page routes because their controller is vendor-provided; path-filtered route-list commands are used as evidence for those routes.
- Non-order admin REST write endpoints and the larger admin REST surfaces for collections, discounts, settings, themes, content, search, analytics, and exports are still missing; outbound webhook subscription management is implemented through the admin UI only, as specified for the initial implementation.
- Automated browser tests from Spec 08 are still missing; current browser coverage is manual Playwright MCP smoke verification.
- SQLite enum/check constraints from the schema spec are not yet explicitly enforced as database `CHECK` constraints; enum validation is currently enforced through casts/services/model invariants.


rg -n "browser tests|tests/Browser|Pest browser|visit\(|assertNoJavaScriptErrors|Playwright|Dusk|e2e" composer.json phpunit.xml tests specs/08-PLAYWRIGHT-E2E-PLAN.md

rg -n "browser tests|tests/Browser|Pest browser|visit\\(|assertNoJavaScriptErrors|Playwright|Dusk|e2e" composer.json phpunit.xml tests specs/08-PLAYWRIGHT-E2E-PLAN.md

Question: browser tests|tests/Browser|Pest browser|visit\(|assertNoJavaScriptErrors|Playwright|Dusk|e2e

specs/08-PLAYWRIGHT-E2E-PLAN.md:1:# 08 - Playwright E2E Test Plan
specs/08-PLAYWRIGHT-E2E-PLAN.md:3:> Complete end-to-end browser test specification for the e-commerce platform using Pest v4 browser testing (Playwright-backed). All tests verify the entire application works through a real browser. This document defines requirements and specifications for the coding agent to implement.
specs/08-PLAYWRIGHT-E2E-PLAN.md:11:| 1 - Smoke Tests | `tests/Browser/SmokeTest.php` | 10 | Hit every major page, assert HTTP 200 and no JS errors | Store 1, Products, Collections, Pages |
specs/08-PLAYWRIGHT-E2E-PLAN.md:12:| 2 - Admin Authentication | `tests/Browser/Admin/AuthenticationTest.php` | 10 | Admin login, logout, invalid credentials, session access control | Admin user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:13:| 3 - Admin Product Management | `tests/Browser/Admin/ProductManagementTest.php` | 7 | Product CRUD: listing, creating, editing, archiving, filtering | Admin user, Products (incl. #15 draft) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:14:| 4 - Admin Order Management | `tests/Browser/Admin/OrderManagementTest.php` | 11 | Order listing, filtering, detail view, fulfillment, refund, confirm payment, fulfillment guard, mark shipped/delivered | Admin user, Orders (#1001, #1005), Customer |
specs/08-PLAYWRIGHT-E2E-PLAN.md:15:| 5 - Admin Discount Management | `tests/Browser/Admin/DiscountManagementTest.php` | 6 | Discount code listing, creation, editing | Admin user, Discounts |
specs/08-PLAYWRIGHT-E2E-PLAN.md:16:| 6 - Admin Settings | `tests/Browser/Admin/SettingsTest.php` | 7 | Store settings, shipping zones, tax config, domains | Admin user, Shipping zones, Store 1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:17:| 7 - Storefront Browsing | `tests/Browser/Storefront/BrowsingTest.php` | 15 | Home page, collections, product detail, variants, search, pages | Products, Collections, Pages, Products #15/#17/#18 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:18:| 8 - Cart Flow | `tests/Browser/Storefront/CartTest.php` | 12 | Cart lifecycle: add, update qty, remove, discounts, totals | Products, Discounts (all codes) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:19:| 9 - Checkout Flow | `tests/Browser/Storefront/CheckoutTest.php` | 13 | Full checkout: contact, address, shipping, payment method selection, payment, confirmation, magic card decline, bank transfer flow | Products, Shipping zones, Discounts |
specs/08-PLAYWRIGHT-E2E-PLAN.md:20:| 10 - Customer Account | `tests/Browser/Storefront/CustomerAccountTest.php` | 12 | Registration, login, order history, addresses, logout | Customer user, Orders (#1001/#1002/#1004) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:21:| 11 - Inventory Enforcement | `tests/Browser/Storefront/InventoryTest.php` | 4 | Inventory policy enforcement: deny vs. continue | Products #17 (deny), #18 (continue), #1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:22:| 12 - Tenant Isolation | `tests/Browser/Storefront/TenantIsolationTest.php` | 5 | Multi-store data isolation verification | Store 1, Admin user, Customer user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:23:| 13 - Responsive / Mobile | `tests/Browser/Storefront/ResponsiveTest.php` | 8 | Mobile and tablet viewport rendering and interaction | Products, Admin user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:24:| 14 - Accessibility | `tests/Browser/Storefront/AccessibilityTest.php` | 11 | Heading hierarchy, ARIA labels, form labels, keyboard nav | Products, Store 1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:25:| 15 - Admin Collections | `tests/Browser/Admin/CollectionManagementTest.php` | 3 | Collection CRUD in admin | Admin user, Collections |
specs/08-PLAYWRIGHT-E2E-PLAN.md:26:| 16 - Admin Customers | `tests/Browser/Admin/CustomerManagementTest.php` | 3 | Customer listing and detail views | Admin user, Customer user, Orders |
specs/08-PLAYWRIGHT-E2E-PLAN.md:27:| 17 - Admin Pages | `tests/Browser/Admin/PageManagementTest.php` | 3 | CMS page management | Admin user, Pages |
specs/08-PLAYWRIGHT-E2E-PLAN.md:28:| 18 - Admin Analytics | `tests/Browser/Admin/AnalyticsTest.php` | 3 | Analytics dashboard rendering | Admin user, Orders |
specs/08-PLAYWRIGHT-E2E-PLAN.md:37:- **Test runner:** Pest v4 with browser testing capabilities (Playwright under the hood)
specs/08-PLAYWRIGHT-E2E-PLAN.md:48:| `visit(url)` | Open a real browser and navigate to the given URL |
specs/08-PLAYWRIGHT-E2E-PLAN.md:49:| `visit([url1, url2, ...])` | Visit multiple pages (for batch smoke testing) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:56:Additionally, standard Laravel test features are available within browser tests: factories, `Event::fake()`, `Notification::fake()`, `$this->actingAs()`, and model queries.
specs/08-PLAYWRIGHT-E2E-PLAN.md:76:3. Playwright browsers installed via `npx playwright install`
specs/08-PLAYWRIGHT-E2E-PLAN.md:147:tests/Browser/
specs/08-PLAYWRIGHT-E2E-PLAN.md:174:**File:** `tests/Browser/SmokeTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:314:**File:** `tests/Browser/Admin/AuthenticationTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:510:**File:** `tests/Browser/Admin/ProductM…179 chars truncated…iscountManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1039:**File:** `tests/Browser/Admin/SettingsTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1187:**File:** `tests/Browser/Storefront/BrowsingTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1423:**File:** `tests/Browser/Storefront/CartTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1693:**File:** `tests/Browser/Storefront/CheckoutTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2080:**File:** `tests/Browser/Storefront/CustomerAccountTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2110:3. Enter email: `new-customer-e2e@example.com`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2321:**File:** `tests/Browser/Storefront/InventoryTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2405:**File:** `tests/Browser/Storefront/TenantIsolationTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2516:**File:** `tests/Browser/Storefront/ResponsiveTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2682:**File:** `tests/Browser/Storefront/AccessibilityTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2868:**File:** `tests/Browser/Admin/CollectionManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2932:**File:** `tests/Browser/Admin/CustomerManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2992:**File:** `tests/Browser/Admin/PageManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:3054:**File:** `tests/Browser/Admin/AnalyticsTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:3122:| 1 - Smoke Tests | `tests/Browser/SmokeTest.php` | 10 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3123:| 2 - Admin Authentication | `tests/Browser/Admin/AuthenticationTest.php` | 10 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3124:| 3 - Admin Product Management | `tests/Browser/Admin/ProductManagementTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3125:| 4 - Admin Order Management | `tests/Browser/Admin/OrderManagementTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3126:| 5 - Admin Discount Management | `tests/Browser/Admin/DiscountManagementTest.php` | 6 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3127:| 6 - Admin Settings | `tests/Browser/Admin/SettingsTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3128:| 7 - Storefront Browsing | `tests/Browser/Storefront/BrowsingTest.php` | 15 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3129:| 8 - Cart Flow | `tests/Browser/Storefront/CartTest.php` | 12 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3130:| 9 - Checkout Flow | `tests/Browser/Storefront/CheckoutTest.php` | 8 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3131:| 10 - Customer Account | `tests/Browser/Storefront/CustomerAccountTest.php` | 12 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3132:| 11 - Inventory Enforcement | `tests/Browser/Storefront/InventoryTest.php` | 4 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3133:| 12 - Tenant Isolation | `tests/Browser/Storefront/TenantIsolationTest.php` | 5 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3134:| 13 - Responsive / Mobile | `tests/Browser/Storefront/ResponsiveTest.php` | 8 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3135:| 14 - Accessibility | `tests/Browser/Storefront/AccessibilityTest.php` | 11 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3136:| 15 - Admin Collections | `tests/Browser/Admin/CollectionManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3137:| 16 - Admin Customers | `tests/Browser/Admin/CustomerManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3138:| 17 - Admin Pages | `tests/Browser/Admin/PageManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3139:| 18 - Admin Analytics | `tests/Browser/Admin/AnalyticsTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3148:| Run all browser tests | `php artisan test tests/Browser/` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3149:| Run a specific suite | `php artisan test tests/Browser/SmokeTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3150:| Run a specific suite (nested) | `php artisan test tests/Browser/Storefront/CartTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3152:| Run admin auth tests | `php artisan test tests/Browser/Admin/AuthenticationTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3153:| Run checkout flow tests | `php artisan test tests/Browser/Storefront/CheckoutTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3163:3. **Pest v4 syntax:** All tests use Pest's `it()` function, NOT class-based PHPUnit. No `$this->` within closures unless accessing Laravel test methods. Use `visit()`, `fill()`, `click()`, `assertSee()` as the primary browser interaction API.
specs/08-PLAYWRIGHT-E2E-PLAN.md:3169:6. **Viewport testing (Suite 13):** The coding agent should use Pest v4 / Playwright's viewport configuration to set browser dimensions. The exact API for setting viewport in Pest v4 browser tests should be looked up via documentation search.
tests/Feature/Catalog/CatalogUiTest.php:87:        ->set('handle', 'test-product-created-by-e2e')
tests/Feature/Catalog/CatalogUiTest.php:97:    $product = Product::query()->where('handle', 'test-product-created-by-e2e')->firstOrFail();
tests/Feature/Catalog/CatalogUiTest.php:236:        ->set('handle', 'e2e-test-collection')
tests/Feature/Catalog/CatalogUiTest.php:242:    $collection = Collection::query()->where('handle', 'e2e-test-collection')->firstOrFail();


Output:
Chunk ID: e2cd8b
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2545
Output:
specs/08-PLAYWRIGHT-E2E-PLAN.md:1:# 08 - Playwright E2E Test Plan
specs/08-PLAYWRIGHT-E2E-PLAN.md:3:> Complete end-to-end browser test specification for the e-commerce platform using Pest v4 browser testing (Playwright-backed). All tests verify the entire application works through a real browser. This document defines requirements and specifications for the coding agent to implement.
specs/08-PLAYWRIGHT-E2E-PLAN.md:11:| 1 - Smoke Tests | `tests/Browser/SmokeTest.php` | 10 | Hit every major page, assert HTTP 200 and no JS errors | Store 1, Products, Collections, Pages |
specs/08-PLAYWRIGHT-E2E-PLAN.md:12:| 2 - Admin Authentication | `tests/Browser/Admin/AuthenticationTest.php` | 10 | Admin login, logout, invalid credentials, session access control | Admin user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:13:| 3 - Admin Product Management | `tests/Browser/Admin/ProductManagementTest.php` | 7 | Product CRUD: listing, creating, editing, archiving, filtering | Admin user, Products (incl. #15 draft) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:14:| 4 - Admin Order Management | `tests/Browser/Admin/OrderManagementTest.php` | 11 | Order listing, filtering, detail view, fulfillment, refund, confirm payment, fulfillment guard, mark shipped/delivered | Admin user, Orders (#1001, #1005), Customer |
specs/08-PLAYWRIGHT-E2E-PLAN.md:15:| 5 - Admin Discount Management | `tests/Browser/Admin/DiscountManagementTest.php` | 6 | Discount code listing, creation, editing | Admin user, Discounts |
specs/08-PLAYWRIGHT-E2E-PLAN.md:16:| 6 - Admin Settings | `tests/Browser/Admin/SettingsTest.php` | 7 | Store settings, shipping zones, tax config, domains | Admin user, Shipping zones, Store 1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:17:| 7 - Storefront Browsing | `tests/Browser/Storefront/BrowsingTest.php` | 15 | Home page, collections, product detail, variants, search, pages | Products, Collections, Pages, Products #15/#17/#18 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:18:| 8 - Cart Flow | `tests/Browser/Storefront/CartTest.php` | 12 | Cart lifecycle: add, update qty, remove, discounts, totals | Products, Discounts (all codes) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:19:| 9 - Checkout Flow | `tests/Browser/Storefront/CheckoutTest.php` | 13 | Full checkout: contact, address, shipping, payment method selection, payment, confirmation, magic card decline, bank transfer flow | Products, Shipping zones, Discounts |
specs/08-PLAYWRIGHT-E2E-PLAN.md:20:| 10 - Customer Account | `tests/Browser/Storefront/CustomerAccountTest.php` | 12 | Registration, login, order history, addresses, logout | Customer user, Orders (#1001/#1002/#1004) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:21:| 11 - Inventory Enforcement | `tests/Browser/Storefront/InventoryTest.php` | 4 | Inventory policy enforcement: deny vs. continue | Products #17 (deny), #18 (continue), #1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:22:| 12 - Tenant Isolation | `tests/Browser/Storefront/TenantIsolationTest.php` | 5 | Multi-store data isolation verification | Store 1, Admin user, Customer user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:23:| 13 - Responsive / Mobile | `tests/Browser/Storefront/ResponsiveTest.php` | 8 | Mobile and tablet viewport rendering and interaction | Products, Admin user |
specs/08-PLAYWRIGHT-E2E-PLAN.md:24:| 14 - Accessibility | `tests/Browser/Storefront/AccessibilityTest.php` | 11 | Heading hierarchy, ARIA labels, form labels, keyboard nav | Products, Store 1 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:25:| 15 - Admin Collections | `tests/Browser/Admin/CollectionManagementTest.php` | 3 | Collection CRUD in admin | Admin user, Collections |
specs/08-PLAYWRIGHT-E2E-PLAN.md:26:| 16 - Admin Customers | `tests/Browser/Admin/CustomerManagementTest.php` | 3 | Customer listing and detail views | Admin user, Customer user, Orders |
specs/08-PLAYWRIGHT-E2E-PLAN.md:27:| 17 - Admin Pages | `tests/Browser/Admin/PageManagementTest.php` | 3 | CMS page management | Admin user, Pages |
specs/08-PLAYWRIGHT-E2E-PLAN.md:28:| 18 - Admin Analytics | `tests/Browser/Admin/AnalyticsTest.php` | 3 | Analytics dashboard rendering | Admin user, Orders |
specs/08-PLAYWRIGHT-E2E-PLAN.md:37:- **Test runner:** Pest v4 with browser testing capabilities (Playwright under the hood)
specs/08-PLAYWRIGHT-E2E-PLAN.md:48:| `visit(url)` | Open a real browser and navigate to the given URL |
specs/08-PLAYWRIGHT-E2E-PLAN.md:49:| `visit([url1, url2, ...])` | Visit multiple pages (for batch smoke testing) |
specs/08-PLAYWRIGHT-E2E-PLAN.md:56:Additionally, standard Laravel test features are available within browser tests: factories, `Event::fake()`, `Notification::fake()`, `$this->actingAs()`, and model queries.
specs/08-PLAYWRIGHT-E2E-PLAN.md:76:3. Playwright browsers installed via `npx playwright install`
specs/08-PLAYWRIGHT-E2E-PLAN.md:147:tests/Browser/
specs/08-PLAYWRIGHT-E2E-PLAN.md:174:**File:** `tests/Browser/SmokeTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:314:**File:** `tests/Browser/Admin/AuthenticationTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:510:**File:** `tests/Browser/Admin/ProductManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:678:**File:** `tests/Browser/Admin/OrderManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:908:**File:** `tests/Browser/Admin/DiscountManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1039:**File:** `tests/Browser/Admin/SettingsTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1187:**File:** `tests/Browser/Storefront/BrowsingTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1423:**File:** `tests/Browser/Storefront/CartTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:1693:**File:** `tests/Browser/Storefront/CheckoutTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2080:**File:** `tests/Browser/Storefront/CustomerAccountTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2110:3. Enter email: `new-customer-e2e@example.com`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2321:**File:** `tests/Browser/Storefront/InventoryTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2405:**File:** `tests/Browser/Storefront/TenantIsolationTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2516:**File:** `tests/Browser/Storefront/ResponsiveTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2682:**File:** `tests/Browser/Storefront/AccessibilityTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2868:**File:** `tests/Browser/Admin/CollectionManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2932:**File:** `tests/Browser/Admin/CustomerManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:2992:**File:** `tests/Browser/Admin/PageManagementTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:3054:**File:** `tests/Browser/Admin/AnalyticsTest.php`
specs/08-PLAYWRIGHT-E2E-PLAN.md:3122:| 1 - Smoke Tests | `tests/Browser/SmokeTest.php` | 10 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3123:| 2 - Admin Authentication | `tests/Browser/Admin/AuthenticationTest.php` | 10 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3124:| 3 - Admin Product Management | `tests/Browser/Admin/ProductManagementTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3125:| 4 - Admin Order Management | `tests/Browser/Admin/OrderManagementTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3126:| 5 - Admin Discount Management | `tests/Browser/Admin/DiscountManagementTest.php` | 6 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3127:| 6 - Admin Settings | `tests/Browser/Admin/SettingsTest.php` | 7 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3128:| 7 - Storefront Browsing | `tests/Browser/Storefront/BrowsingTest.php` | 15 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3129:| 8 - Cart Flow | `tests/Browser/Storefront/CartTest.php` | 12 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3130:| 9 - Checkout Flow | `tests/Browser/Storefront/CheckoutTest.php` | 8 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3131:| 10 - Customer Account | `tests/Browser/Storefront/CustomerAccountTest.php` | 12 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3132:| 11 - Inventory Enforcement | `tests/Browser/Storefront/InventoryTest.php` | 4 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3133:| 12 - Tenant Isolation | `tests/Browser/Storefront/TenantIsolationTest.php` | 5 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3134:| 13 - Responsive / Mobile | `tests/Browser/Storefront/ResponsiveTest.php` | 8 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3135:| 14 - Accessibility | `tests/Browser/Storefront/AccessibilityTest.php` | 11 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3136:| 15 - Admin Collections | `tests/Browser/Admin/CollectionManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3137:| 16 - Admin Customers | `tests/Browser/Admin/CustomerManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3138:| 17 - Admin Pages | `tests/Browser/Admin/PageManagementTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3139:| 18 - Admin Analytics | `tests/Browser/Admin/AnalyticsTest.php` | 3 |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3148:| Run all browser tests | `php artisan test tests/Browser/` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3149:| Run a specific suite | `php artisan test tests/Browser/SmokeTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3150:| Run a specific suite (nested) | `php artisan test tests/Browser/Storefront/CartTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3152:| Run admin auth tests | `php artisan test tests/Browser/Admin/AuthenticationTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3153:| Run checkout flow tests | `php artisan test tests/Browser/Storefront/CheckoutTest.php` |
specs/08-PLAYWRIGHT-E2E-PLAN.md:3163:3. **Pest v4 syntax:** All tests use Pest's `it()` function, NOT class-based PHPUnit. No `$this->` within closures unless accessing Laravel test methods. Use `visit()`, `fill()`, `click()`, `assertSee()` as the primary browser interaction API.
specs/08-PLAYWRIGHT-E2E-PLAN.md:3169:6. **Viewport testing (Suite 13):** The coding agent should use Pest v4 / Playwright's viewport configuration to set browser dimensions. The exact API for setting viewport in Pest v4 browser tests should be looked up via documentation search.
tests/Feature/Catalog/CatalogUiTest.php:87:        ->set('handle', 'test-product-created-by-e2e')
tests/Feature/Catalog/CatalogUiTest.php:97:    $product = Product::query()->where('handle', 'test-product-created-by-e2e')->firstOrFail();
tests/Feature/Catalog/CatalogUiTest.php:236:        ->set('handle', 'e2e-test-collection')
tests/Feature/Catalog/CatalogUiTest.php:242:    $collection = Collection::query()->where('handle', 'e2e-test-collection')->firstOrFail();


find tests -maxdepth 3 -type f | sort | sed -n '1,220p'


laravel/livewire-starter-kit

The official Laravel starter kit for Livewire.

@php -r "file_exists('.env') || copy('.env.example', '.env');"

npx concurrently -c "#93c5fd,#c4b5fd,#fb7185,#fdba74" "php artisan serve" "php artisan queue:listen --tries=1 --timeout=0" "php artisan pail --timeout=0" "npm run dev" --names=server,queue,logs,vite --kill-others

@php artisan config:clear --ansi
@test:lint
@php artisan test

@php artisan vendor:publish --tag=laravel-assets --ansi --force

@php -r "file_exists('database/database.sqlite') || touch('database/database.sqlite');"


Output:
Chunk ID: 7eed75
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 804
Output:
{
    "$schema": "https://getcomposer.org/schema.json",
    "name": "laravel/livewire-starter-kit",
    "type": "project",
    "description": "The official Laravel starter kit for Livewire.",
    "keywords": [
        "laravel",
        "framework"
    ],
    "license": "MIT",
    "require": {
        "php": "^8.2",
        "laravel/fortify": "^1.30",
        "laravel/framework": "^12.0",
        "laravel/tinker": "^2.10.1",
        "livewire/flux": "^2.9.0",
        "livewire/livewire": "^4.0"
    },
    "require-dev": {
        "fakerphp/faker": "^1.23",
        "laravel/boost": "^2.4",
        "laravel/pail": "^1.2.2",
        "laravel/pint": "^1.24",
        "laravel/sail": "^1.41",
        "mockery/mockery": "^1.6",
        "nunomaduro/collision": "^8.6",
        "pestphp/pest": "^4.3",
        "pestphp/pest-plugin-laravel": "^4.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "setup": [
            "composer install",
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
            "@php artisan key:generate",
            "@php artisan migrate --force",
            "npm install",
            "npm run build"
        ],
        "dev": [
            "Composer\\Config::disableProcessTimeout",
            "npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1 --timeout=0\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
        ],
        "lint": [
            "pint --parallel"
        ],
        "test:lint": [
            "pint --parallel --test"
        ],
        "test": [
            "@php artisan config:clear --ansi",
            "@test:lint",
            "@php artisan test"
        ],
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-update-cmd": [
            "@php artisan vendor:publish --tag=laravel-assets --ansi --force"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi",
            "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
            "@php artisan migrate --graceful --ansi"
        ],
        "pre-package-uninstall": [
            "Illuminate\\Foundation\\ComposerScripts::prePackageUninstall"
        ]
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true,
        "allow-plugins": {
            "pestphp/pest-plugin": true,
            "php-http/discovery": true
        }
    },
    "minimum-stability": "stable",
    "prefer-stable": true
}


Output:
Chunk ID: 433456
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 159
Output:
{
    "$schema": "https://www.schemastore.org/package.json",
    "private": true,
    "type": "module",
    "scripts": {
        "build": "vite build",
        "dev": "vite"
    },
    "dependencies": {
        "@tailwindcss/vite": "^4.1.11",
        "autoprefixer": "^10.4.20",
        "axios": "^1.7.4",
        "concurrently": "^9.0.1",
        "laravel-vite-plugin": "^2.0",
        "tailwindcss": "^4.0.7",
        "vite": "^7.0.4"
    },
    "optionalDependencies": {
        "@rollup/rollup-linux-x64-gnu": "4.9.5",
        "@tailwindcss/oxide-linux-x64-gnu": "^4.0.1",
        "lightningcss-linux-x64-gnu": "^1.29.1"
    }
}


Output:
Chunk ID: 3ecba3
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 611
Output:
tests/Feature/Admin/AnalyticsDashboardTest.php
tests/Feature/Admin/AppsDevelopersTest.php
tests/Feature/Admin/ContentManagementTest.php
tests/Feature/Admin/CustomerManagementTest.php
tests/Feature/Admin/DashboardTest.php
tests/Feature/Admin/DiscountManagementTest.php
tests/Feature/Admin/OrderManagementTest.php
tests/Feature/Admin/ProductMediaManagementTest.php
tests/Feature/Admin/SearchSettingsTest.php
tests/Feature/Admin/SettingsManagementTest.php
tests/Feature/Analytics/AnalyticsServiceTest.php
tests/Feature/Api/AdminCatalogApiTest.php
tests/Feature/Api/AdminOrderApiTest.php
tests/Feature/Api/StorefrontAnalyticsApiTest.php
tests/Feature/Api/StorefrontCartApiTest.php
tests/Feature/Api/StorefrontCheckoutApiTest.php
tests/Feature/Api/StorefrontOrderApiTest.php
tests/Feature/Api/StorefrontSearchApiTest.php
tests/Feature/Auth/AuthenticationTest.php
tests/Feature/Auth/CustomerPasswordResetTest.php
tests/Feature/Auth/EmailVerificationTest.php
tests/Feature/Auth/PasswordConfirmationTest.php
tests/Feature/Auth/PasswordResetTest.php
tests/Feature/Auth/RegistrationTest.php
tests/Feature/Auth/TwoFactorChallengeTest.php
tests/Feature/Cart/CartServiceTest.php
tests/Feature/Catalog/CatalogFoundationTest.php
tests/Feature/Catalog/CatalogUiTest.php
tests/Feature/Catalog/InventoryServiceTest.php
tests/Feature/Catalog/MediaProcessingTest.php
tests/Feature/Catalog/ProductServiceTest.php
tests/Feature/Catalog/VariantMatrixServiceTest.php
tests/Feature/Checkout/CheckoutServiceTest.php
tests/Feature/Checkout/PricingServicesTest.php
tests/Feature/DashboardTest.php
tests/Feature/ExampleTest.php
tests/Feature/Foundation/AuthorizationTest.php
tests/Feature/Foundation/CustomerAuthTest.php
tests/Feature/Foundation/TenancyTest.php
tests/Feature/Orders/BankTransferOrderTest.php
tests/Feature/Orders/FulfillmentServiceTest.php
tests/Feature/Orders/OrderServiceTest.php
tests/Feature/Orders/RefundServiceTest.php
tests/Feature/Payments/MockPaymentProviderTest.php
tests/Feature/Search/SearchServiceTest.php
tests/Feature/Settings/PasswordUpdateTest.php
tests/Feature/Settings/ProfileUpdateTest.php
tests/Feature/Settings/TwoFactorAuthenticationTest.php
tests/Feature/Storefront/CartCheckoutUiTest.php
tests/Feature/Storefront/OrderViewsTest.php
tests/Feature/Storefront/ThemeDataTest.php
tests/Feature/Webhooks/WebhookDeliveryTest.php
tests/Feature/Webhooks/WebhookSignatureTest.php
tests/Pest.php
tests/TestCase.php
tests/Unit/ExampleTest.php


rg -n "function visit|class Browser|assertNoJavaScriptErrors|pest-plugin-browser|Browser\\


Output:
Chunk ID: 082550
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 5
Output:
zsh:1: unmatched "


rg -n 'function visit|assertNoJavaScriptErrors|pest-plugin-browser|Pest\\Browser|namespace Pest\\Browser' vendor tests composer.lock | head -n 100


rg -n 'pest-plugin-browser|playwright|browser' composer.lock composer.json vendor/pestphp -g 'composer.json'


rg -n 'pest-plugin-browser|playwright|browser' composer.lock composer.json vendor/pestphp -g 'composer.json'

rg -n 'pest-plugin-browser|playwright|browser' composer.lock composer.json vendor/pestphp -g composer.json

Question: pest-plugin-browser|playwright|browser

composer.lock:4452:                "symfony/browser-kit": "<6.4",
composer.lock:4476:                "symfony/browser-kit": "^6.4|^7.0|^8.0",
composer.lock:7564:                "pestphp/pest-plugin-browser": "^4.2.1",
vendor/pestphp/pest-plugin-browser/composer.json:2:    "name": "pestphp/pest-plugin-browser",
vendor/pestphp/pest-plugin-browser/composer.json:3:    "description": "Pest plugin to test browser interactions",
vendor/pestphp/pest-plugin-browser/composer.json:11:        "browser"
vendor/pestphp/pest/composer.json:59:        "pestphp/pest-plugin-browser": "^4.2.1",


rg -n 'function visit|assertNoJavaScriptErrors|pest-plugin-browser|Pest\\Browser|namespace Pest\\Browser' vendor tests composer.lock | head -n 100

rg -n "function visit|assertNoJavaScriptErrors|pest-plugin-browser|Pest\\\\Browser|namespace Pest\\\\Browser" vendor tests composer.lock

Question: function visit|assertNoJavaScriptErrors|pest-plugin-browser|Pest\\Browser|namespace Pest\\Browser

composer.lock:7564:                "pestphp/pest-plugin-browser": "^4.2.1",
vendor/pestphp/pest-plugin-browser/src/Cleanables/Ziggy.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Ziggy.php:7:use Pest\Browser\Contracts\Cleanable;
vendor/nunomaduro/collision/src/Adapters/Phpunit/Style.php:354:            '/vendor\/pestphp\/pest-plugin-browser/',
vendor/pestphp/pest-plugin-browser/src/Cleanables/Inertia.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Inertia.php:8:use Pest\Browser\Contracts\Cleanable;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Livewire.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Livewire.php:8:use Pest\Browser\Contracts\Cleanable;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:5:namespace Pest\Browser;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:7:use Pest\Browser\Contracts\HttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:8:use Pest\Browser\Contracts\PlaywrightServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:9:use Pest\Browser\Drivers\LaravelHttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:10:use Pest\Browser\Drivers\NullableHttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:11:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:12:use Pest\Browser\Playwright\Servers\AlreadyStartedPlaywrightServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:13:use Pest\Browser\Playwright\Servers\PlaywrightNpmServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:14:use Pest\Browser\Support\PackageJsonDirectory;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:15:use Pest\Browser\Support\Port;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/HasWaitCapabilities.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/HasWaitCapabilities.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:7:use Pest\Browser\Api\AwaitableWebpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:8:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:8:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:8:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithScreen.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithViewPort.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesElementAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesElementAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesUrlAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesUrlAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:8:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:9:use Pest\Browser\Enums\AccessibilityIssueLevel;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:10:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:11:use Pest\Browser\Support\AccessibilityFormatter;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:26:        $this->assertNoJavaScriptErrors();
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:78:    public function assertNoJavaScriptErrors(): Webpage
vendor/pestphp/pest-plugin-browse…408 chars truncated…r\Api;
vendor/pestphp/pest-plugin-browser/src/Api/ArrayablePendingAwaitablePage.php:12:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:8:use Pest\Browser\Enums\ColorScheme;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:9:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:10:use Pest\Browser\Playwright\InitScript;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:11:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:12:use Pest\Browser\Support\ComputeUrl;
vendor/pestphp/pest-plugin-browser/src/Api/TestableLivewire.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/TestableLivewire.php:9:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Livewire.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:8:use Pest\Browser\Enums\City;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:9:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:7:use Pest\Browser\Exceptions\BrowserExpectationFailedException;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:8:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:10:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:11:use Pest\Browser\ServerManager;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:7:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:8:use Pest\Browser\Playwright\Locator;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:10:use Pest\Browser\Support\GuessLocator;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:8:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Support/BrowserTestIdentifier.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:7:use Pest\Browser\Playwright\Locator;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:8:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Support/AccessibilityFormatter.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/PackageJsonDirectory.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Screenshot.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/ComputeUrl.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/ComputeUrl.php:7:use Pest\Browser\ServerManager;
vendor/pestphp/pest-plugin-browser/src/Support/Shell.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Str.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Selector.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/JavaScriptSerializer.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Port.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Port.php:7:use Pest\Browser\Exceptions\PortNotFoundException;
vendor/pestphp/pest-plugin-browser/src/Support/ImageDiffView.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:5:namespace Pest\Browser;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:7:use Pest\Browser\Cleanables\Inertia;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:8:use Pest\Browser\Cleanables\Livewire;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:9:use Pest\Browser\Cleanables\Ziggy;
vendor/pestphp/pest-plugin-browser/src/Exceptions/PlaywrightNotInstalledException.php:5:namespace Pest\Browser\Exceptions;
vendor/pestphp/pest-plugin-browser/src/Exceptions/BrowserExpectationFailedException.php:5:namespace Pest\Browser\Exceptions;


Output:
Chunk ID: 4a6493
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2602
Output:
composer.lock:7564:                "pestphp/pest-plugin-browser": "^4.2.1",
vendor/pestphp/pest-plugin-browser/src/Cleanables/Ziggy.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Ziggy.php:7:use Pest\Browser\Contracts\Cleanable;
vendor/nunomaduro/collision/src/Adapters/Phpunit/Style.php:354:            '/vendor\/pestphp\/pest-plugin-browser/',
vendor/pestphp/pest-plugin-browser/src/Cleanables/Inertia.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Inertia.php:8:use Pest\Browser\Contracts\Cleanable;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Livewire.php:5:namespace Pest\Browser\Cleanables;
vendor/pestphp/pest-plugin-browser/src/Cleanables/Livewire.php:8:use Pest\Browser\Contracts\Cleanable;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:5:namespace Pest\Browser;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:7:use Pest\Browser\Contracts\HttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:8:use Pest\Browser\Contracts\PlaywrightServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:9:use Pest\Browser\Drivers\LaravelHttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:10:use Pest\Browser\Drivers\NullableHttpServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:11:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:12:use Pest\Browser\Playwright\Servers\AlreadyStartedPlaywrightServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:13:use Pest\Browser\Playwright\Servers\PlaywrightNpmServer;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:14:use Pest\Browser\Support\PackageJsonDirectory;
vendor/pestphp/pest-plugin-browser/src/ServerManager.php:15:use Pest\Browser\Support\Port;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/HasWaitCapabilities.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/HasWaitCapabilities.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:7:use Pest\Browser\Api\AwaitableWebpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:8:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithFrames.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesScreenshotAssertions.php:8:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithElements.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithTab.php:8:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithScreen.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithViewPort.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesElementAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesElementAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesUrlAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesUrlAssertions.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:8:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:9:use Pest\Browser\Enums\AccessibilityIssueLevel;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:10:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:11:use Pest\Browser\Support\AccessibilityFormatter;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:26:        $this->assertNoJavaScriptErrors();
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/MakesConsoleAssertions.php:78:    public function assertNoJavaScriptErrors(): Webpage
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithToolbar.php:5:namespace Pest\Browser\Api\Concerns;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithToolbar.php:7:use Pest\Browser\Api\Webpage;
vendor/pestphp/pest-plugin-browser/src/Api/Concerns/InteractsWithToolbar.php:8:use Pest\Browser\Support\ComputeUrl;
vendor/pestphp/pest-plugin-browser/src/Api/ArrayablePendingAwaitablePage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/ArrayablePendingAwaitablePage.php:12:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:8:use Pest\Browser\Enums\ColorScheme;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:9:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:10:use Pest\Browser\Playwright\InitScript;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:11:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/PendingAwaitablePage.php:12:use Pest\Browser\Support\ComputeUrl;
vendor/pestphp/pest-plugin-browser/src/Api/TestableLivewire.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/TestableLivewire.php:9:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Livewire.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:8:use Pest\Browser\Enums\City;
vendor/pestphp/pest-plugin-browser/src/Api/From.php:9:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:7:use Pest\Browser\Exceptions\BrowserExpectationFailedException;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:8:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:10:use Pest\Browser\Playwright\Playwright;
vendor/pestphp/pest-plugin-browser/src/Api/AwaitableWebpage.php:11:use Pest\Browser\ServerManager;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:7:use Pest\Browser\Execution;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:8:use Pest\Browser\Playwright\Locator;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:9:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Api/Webpage.php:10:use Pest\Browser\Support\GuessLocator;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:5:namespace Pest\Browser\Api;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:7:use Pest\Browser\Enums\BrowserType;
vendor/pestphp/pest-plugin-browser/src/Api/On.php:8:use Pest\Browser\Enums\Device;
vendor/pestphp/pest-plugin-browser/src/Support/BrowserTestIdentifier.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:7:use Pest\Browser\Playwright\Locator;
vendor/pestphp/pest-plugin-browser/src/Support/GuessLocator.php:8:use Pest\Browser\Playwright\Page;
vendor/pestphp/pest-plugin-browser/src/Support/AccessibilityFormatter.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/PackageJsonDirectory.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Screenshot.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/ComputeUrl.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/ComputeUrl.php:7:use Pest\Browser\ServerManager;
vendor/pestphp/pest-plugin-browser/src/Support/Shell.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Str.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Selector.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/JavaScriptSerializer.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Port.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/Support/Port.php:7:use Pest\Browser\Exceptions\PortNotFoundException;
vendor/pestphp/pest-plugin-browser/src/Support/ImageDiffView.php:5:namespace Pest\Browser\Support;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:5:namespace Pest\Browser;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:7:use Pest\Browser\Cleanables\Inertia;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:8:use Pest\Browser\Cleanables\Livewire;
vendor/pestphp/pest-plugin-browser/src/GlobalState.php:9:use Pest\Browser\Cleanables\Ziggy;
vendor/pestphp/pest-plugin-browser/src/Exceptions/PlaywrightNotInstalledException.php:5:namespace Pest\Browser\Exceptions;
vendor/pestphp/pest-plugin-browser/src/Exceptions/BrowserExpectationFailedException.php:5:namespace Pest\Browser\Exceptions;


Output:
Chunk ID: 2843e5
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 146
Output:
composer.lock:4452:                "symfony/browser-kit": "<6.4",
composer.lock:4476:                "symfony/browser-kit": "^6.4|^7.0|^8.0",
composer.lock:7564:                "pestphp/pest-plugin-browser": "^4.2.1",
vendor/pestphp/pest-plugin-browser/composer.json:2:    "name": "pestphp/pest-plugin-browser",
vendor/pestphp/pest-plugin-browser/composer.json:3:    "description": "Pest plugin to test browser interactions",
vendor/pestphp/pest-plugin-browser/composer.json:11:        "browser"
vendor/pestphp/pest/composer.json:59:        "pestphp/pest-plugin-browser": "^4.2.1",


The next visible gap is automated browser coverage. Pest’s browser plugin is already present in `vendor`, so I’m going to add a small maintainable smoke suite first rather than trying to port all 120+ planned scenarios at once.


browser testing visit multiple pages assert no javascript errors

Pest browser testing Laravel livewire visit assertSee


# Search Results

## Database Testing
Database Testing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/database-testing.md

# Database Testing

- [Introduction](#introduction)
    - [Resetting the Database After Each Test](#resetting-the-database-after-each-test)
- [Model Factories](#model-factories)
- [Running Seeders](#running-seeders)
- [Available Assertions](#available-assertions)

---

## Dusk Available Assertions assertSee
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

#### assertSee

Assert that the given text is present on the page:

```php
$browser->assertSee($text);
```

---

## Pest V4 Is Here Now With Browser Testing
Pest V4 Is Here Now With Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/pest-v4-is-here-now-with-browser-testing.md

---
title: Pest v4 Is Here — Now with Browser Testing
description: Today, we're thrilled to announce Pest v4 — our biggest release yet, featuring powerful new browser testing with parallel support and full Laravel integration.
---

> To get started with Pest v4's new features including browser testing, please refer to the upgrade guide: [Upgrade Guide →](/docs/upgrade-guide).

- [Browser Testing](#content-pest-v4-is-here-now-with-browser-testing)
- [Smoke Testing](#content-smoke-testing)
- [Visual Regression Testing](#content-visual-regression-testing)
- [Test Sharding](#content-test-sharding)
- [Type Coverage Is Much Faster](#content-type-coverage-is-much-faster)
- [Profanity Checking](#content-profanity-checking)
- [On Top of PHPUnit 12](#content-on-top-of-phpunit-12)

# Pest v4 Is Here — Now with Browser Testing

Today, we're thrilled to announce the release of **Pest v4**, bringing the biggest testing upgrade yet: powerful **[Browser Testing](/docs/browser-testing)**. Pest's new browser testing features let you run elegant, maintainable browser tests — with first-class support for Laravel's testing API and the ability to run tests in parallel. For the first time, this is browser testing that feels as good as writing unit tests.

Here is the creator of Pest, [Nuno Maduro](https://twitter.com/enunomaduro), demoing the new browser testing features in Pest v4 at Laracon US:

[![Pest v4](/assets/pest4_play.png)](https://youtu.be/f5gAgwwwwOI?si=LtPpySZe3tf8qMjz&t=52)

Here is an example of Browser Testing using [Laravel](https://laravel.com):

```php
it('may reset the password', function () {
    // access any laravel testing helpers...
    Notification::fake();

    // access to the database — using the RefreshDatabase trait (even sqlite in memory...)
    $this->actingAs(User::factory()->create());

    $page = visit('/sign-in') // visit on a real browser...
        ->on()->mobile() // or ->desktop(), ->tablet(), etc...
        ->inDarkMode(); // or ->inLightMode()

    $page->assertSee('Sign In')
         ->click('Forgot Password?')
         ->type('email', 'nuno@laravel.com')
         ->press('Send Reset Link')
         ->assertSee('We have emailed your password reset link!')
         ->assertNoJavascriptErrors(); // or ->assertNoConsoleLogs()

    Notification::assertSent(ResetPassword::class);
});
```

With Pest v4's browser testing, you can:
- Seamlessly use **Laravel features** like `Event::fake()`, `assertAuthenticated()`, and model factories
- Use `RefreshDatabase`, even with SQLite in-memory databases, to ensure a clean state for each test
- Test on **multiple browsers** (Chrome, Firefox, Safari)
- Test on **different devices** and viewports (like iPhone 14 Pro, tablets, or custom breakpoints)
- Switch **color schemes** (light/dark mode)
- Interact with the page (click, type, scroll, select, submit, drag-and-drop, touch gestures, etc.)
- Run **parallel browser tests** for dramatically faster suites
- Take **screenshots** or pause tests for debugging
- …all with the elegance of Pest syntax
- **Playwright-based** — modern, fast, and reliable

To get started with browser testing in Pest, you need to install the Pest Browser Plugin:

```bash
composer require pestphp/pest-plugin-browser --dev

npm install playwright@latest
npx playwright install
```

After, you may use the `visit()` function anywhere. Finally, running this test is as simple as executing `./vendor/bin/pest` in your terminal. Pest will handle the rest, launching a browser, navigating to the page, and performing the actions you specified.

## Smoke Testing

Smoke testing your application in real browsers has never been easier. With Pest v4, you can literally visit all your application pages, and ensure they don't throw any JavaScript errors, and they don't log any console errors.

```php
$routes = ['/', '/about', '/contact'];

visit($routes)->assertNoSmoke();

// assertNoSmoke() is a shorthand for:
// - assertNoJavascriptErrors()
// - assertNoConsoleLogs()
```

## Visual Regression Testing

Want to ensure your pages look exactly as expected over time? Pest v4 introduces visual regression testing with the `assertScreenshotMatches()` assertion. This allows you to take screenshots of your pages and compare them against baseline images, ensuring that your UI remains consistent across changes.

```php
$pages = visit(['/', '/about', '/contact']);

$pages->assertScreenshotMatches();
```

This is just a glimpse of what Browser Testing in Pest v4 can do. Find out more about the new features below, and check out the [Browser Testing documentation](/docs/browser-testing) for a complete guide on how to get started.

## Test Sharding

Pest v4 introduces **Test Sharding**, allowing you to split your test suite into smaller, manageable chunks. This is particularly useful for large applications (or when running browser tests) where running all tests at once can be time-consuming.

This feature is particularly useful on CI platforms, where on things like GitHub actions you can no longer scale vertical, but rather horizontally. This means you can run your tests in parallel across multiple machines, significantly speeding up your test suite execution.

To get started with Test Sharding, you can use the `--shard` option when running Pest:

```bash
# GitHub Workflow One
./vendor/bin/pest --shard=1/4

# GitHub Workflow Two
./vendor/bin/pest --shard=2/4

# GitHub Workflow Three
./vendor/bin/pest --shard=3/4

# GitHub Workflow Four
./vendor/bin/pest --shard=4/4
```

You may combine this with the `--parallel` option to run your tests in parallel, and this way trully maximize your test suite execution speed:

```bash
./vendor/bin/pest --shard=1/4 --parallel
```

Finally, to easily set up sharding your CI configuration, you just have to ensure each job in your CI configuration runs a different shard of your test suite. For example, in GitHub Actions, you can use the `matrix` strategy to define multiple jobs that run different shards:

```yaml
strategy:
  matrix:
    shard: [1, 2, 3, 4]

name: Tests (Shard ${{ matrix.shard }}/4)

steps:
  - name: Run tests
    run: pest --parallel --shard ${{ matrix.shard }}/4
```

## Type Coverage Is Much Faster

Remember the days when you had to wait for your type coverage to run? Not anymore! Pest v4 introduces a new type coverage engine that is significantly faster than previous versions.

Type coverage is 2x faster on the first run and instant on subsequent runs. This means you can quickly check your type coverage without waiting for long periods, making your development workflow much more efficient.

In addition, Type Coverage now supports **Sharding**. This means you can run type coverage with the `--shard` option, just like you do with your tests.

## Profanity Checking

Pest v4 introduces a new feature that allows you to check for profanity in your test code. This is particularly useful for maintaining a clean and professional codebase, especially in collaborative environments.

You can enable profanity checking by adding the `--profanity` option when running Pest:

```bash
./vendor/bin/pest --profanity
```

To start using Pest's Profanity plugin, you need to require the plugin via Composer.

```bash
composer require pestphp/pest-plugin-profanity --dev
```

After requiring the plugin, you may utilize the `--profanity` option to generate a report of your profanity.

```bash
./vendor/bin/pest --profanity
```

If any of your files contain profanity, they will be highlighted in red and displayed using their respective line
numbers and the profane word(s) that have been found.

As an example, `pr31(f*ck)` means that the word "fuck" was found on line 31.

To learn more about the Profanity plugin and how to configure it, check out the [Profanity documentation](/docs/profanity).

### Skip Locally or On CI

Pest v4 introduces the ability to conditionally skip tests based on the environment. You can use `skipLocally()` to skip tests when running locally, or `skipOnCi` to skip tests when running on a CI server.

```php
it('does not run locally', function () {
    // This test will be skipped when running locally
})->skipLocally();

it('does not run on CI', function () {
    // This test will be skipped when running on a CI server
})->skipOnCi();
```

### Miscellaneous Improvements

- You may now use `skipLocally()` or `skipOnCi` to conditionally skip tests based on the environment.
- The `not->toHaveSuspiciousCharacters()` arch expectation has been added to help you identify potential suspicious characters in your code. This arch expectation is now enabled by default on the `php` arch preset. This expectation requires the `intl` PHP extension.
- The expectation `toBeSlug` has been added to help you validate that a string is a valid slug.

### On Top of PHPUnit 12

Pest v4 is built on top of PHPUnit 12, which means you get all the latest features and improvements from PHPUnit. As such, be sure to check out the [PHPUnit 12 release announcement](https://phpunit.de/announcements/phpunit-12.html).

### Thanks To You, Pest v4 Is Here!

There's never been a better time to dive into testing and start using Pest. If you're ready to get started with Pest v4 right away, check out our [installation guide](/docs/installation) for step-by-step instructions. And if you're currently using an earlier version of Pest, we've got you covered with detailed upgrade instructions in our [upgrade guide](/docs/upgrade-guide).

Thank you for your continued support and feedback. We can't wait to see what you build with Pest v4!

---

Thank you for reading about Pest v4's new features! Want to get started with Pest? You can find the installation guide in the next section of the documentation: [Installation →](/docs/installation)

---

## Browser Testing waitForKey
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### waitForKey

The `waitForKey` method opens the current page URL in the default web browser and waits for a key press:

```php
$page->waitForKey(); // Useful for debugging
```

## Debugging tests

Sometimes you may want to debug your browser tests. Pest provides a convenient way to do this by using the `--debug` option, which makes pest to open the browser window and pause the execution of the test when it fails. You can then inspect the page and see what went wrong.

```bash
./vendor/bin/pest --debug
```

Optionally, you can also use the `debug()` method in your test. It will limit execution to this test (like using [`only()`](filtering-tests.md#only)), pause the execution and open the browser window:

```php
$page->debug();
```

You can also take a screenshot of the current page using the `screenshot()` method. This is useful for visual debugging:

NOTE: If you don't pass the filename, it will use the test name as the filename.

```php
$page->screenshot();
$page->screenshot(fullPage: true);
$page->screenshot(filename: 'custom-name');
```

You can also take a screenshot of a specific element using the `screenshotElement()` method:

```php
$page->screenshotElement('#my-element');
```

You can also use the `tinker()` method to open a Tinker session in the context of the current page. This allows you to interact with the page using PHP code:

```php
$page->tinker();
```

After you can run your tests with the `--headed` option to open the browser window:

```bash
./vendor/bin/pest --headed
```

If you wish to run the tests in a headed mode by default, you can set it in your `Pest.php` configuration file:

```php
pest()->browser()->headed();
```

## Continuous Integration

You may refer to Pest's [Continuous Integration](https://pestphp.com/docs/continuous-integration) documentation for more information on how to run your browser tests in a CI environment.

However, if you are using GitHub Actions, you need to add the following steps to your workflow file:

```yaml
    - uses: actions/setup-node@v4
      with:
        node-version: lts/*

    - name: Install dependencies
      run: npm ci

    - name: Install Playwright Browsers
      run: npx playwright install --with-deps
```

---

Now, let's dive into architectural testing and how it can benefit your development process. By performing architectural testing, you can evaluate the overall design of your application and identify potential flaws before they become significant issues: [Arch Testing](/docs/arch-testing)

---

## Browser Testing
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

---
title: Browser Testing
description:
---

# Browser Testing

Browser testing is an essential part of modern web development, allowing you to ensure that your application works correctly across different browsers and devices. Pest provides a simple and elegant way to write browser tests. Here is an example of how to write a browser test using Pest:

```php
it('may welcome the user', function () {
    $page = visit('/');

    $page->assertSee('Welcome');
});
```

This is a basic example of a browser test that checks if the homepage contains the text "Welcome". However, Pest's browser testing capabilities go beyond this simple example. You can use various methods to interact with the page, such as clicking buttons, filling out forms, and navigating between pages.

Here is an example of a more complex browser test, on Laravel, that checks if a user can sign in:

```php
it('may sign in the user', function () {
    Event::fake();

    User::factory()->create([ // assumes RefreshDatabase trait is used on Pest.php...
        'email' => 'nuno@laravel.com',
        'password' => 'password',
    ]);

    $page = visit('/')->on()->mobile()->firefox();

    $page->click('Sign In')
         ->assertUrlIs('/login')
         ->assertSee('Sign In to Your Account')
         ->fill('email', 'nuno@laravel.com')
         ->fill('password', 'password')
         ->click('Submit')
         ->assertSee('Dashboard');

    $this->assertAuthenticated();

    Event::assertDispatched(UserLoggedIn::class);
});
```

Note that, you are leveraging the full power of Laravel's testing capabilities, such as refresh database, event faking, and authentication assertions, while also actually doing browser testing.

## Getting Started

To get started with browser testing in Pest, you need to install the Pest Browser plugin. You can do this by running the following command:

```bash
composer require pestphp/pest-plugin-browser --dev

npm install playwright@latest
npx playwright install
```

Finally, add `tests/Browser/Screenshots` to your `.gitignore` file to avoid committing screenshots taken during browser tests.

### Running Browser Tests

Running browser tests is similar to running regular Pest tests:

```bash
./vendor/bin/pest
```

We recommend running tests in parallel using the `--parallel` option to speed up the execution:

```bash
./vendor/bin/pest --parallel
```

For debugging purposes, you can run the tests in a headed mode and pause the execution at the end of the failed test run:

```bash
./vendor/bin/pest --debug
```

### Navigation

The `visit()` method is used to navigate to a specific URL in your browser test. It provides various methods to interact with the page:

```php
test('example', function () {
    $page = visit('/');

    $page->assertSee('Welcome');
});
```

### Using Other Browsers

By default, the `visit()` method uses Chrome as the browser. However, if you want to use a different browser, you can specify it using the `--browser` option when running the tests:

```bash
./vendor/bin/pest --browser firefox
./vendor/bin/pest --browser safari
```

If you wish to use a different browser by default without specifying it in the command line, you can set it in your `Pest.php` configuration file:

```php
pest()->browser()->inFirefox();
pest()->browser()->inSafari();
```

### Using Other Devices

The `visit()` method uses a desktop viewport. However, you can specify a mobile viewport using the `onMobile()` method. For example:

```php
$page = visit('/')->on()->mobile();
```

If you wish to use a specific device, you can use the `on()` method and chain it with the `macbook14`, `iPhone14Pro`, etc:

```php
$page = visit('/')->on()->iPhone14Pro();
```

### Using Dark Mode

Pest enforces a light color scheme by default. However, you can specify a dark color scheme using the `inDarkMode()` method:

```php
$page = visit('/')->inDarkMode();
```

### Visiting Multiple Pages

You can visit multiple pages simultaneously by passing an array of URLs to the `visit()` method. This is useful for testing scenarios where you need to interact with multiple pages at once:

```php
$pages = visit(['/', '/about']);

$pages->assertNoSmoke()
    ->assertNoAccessibilityIssues()
    ->assertNoConsoleLogs()
    ->assertNoJavaScriptErrors();

[$homePage, $aboutPage] = $pages;

$homePage->assertSee('Welcome to our website');
$aboutPage->assertSee('About Us');
```

### Navigation

After visiting a page, you can navigate to other pages using the `navigate()` method. This method allows you to navigate to a different URL while keeping the current browser context:

```php
$page = visit('/');

$page->navigate('/about')
     ->assertSee('About Us');
```

### Locating Elements

You can locate elements in the DOM using text or CSS selectors. Pest provides a simple syntax for locating elements:

```php
// Clicks the first link with the text "Login"
$page->click('Login');

// Clicks the first element with the class "btn-primary"
$page->click('.btn-primary');

// Clicks the element with the data-test attribute "login"
$page->click('@login');

// Clicks the element with the ID "submit-button"
$page->click('#submit-button');

// etc...
```

### Configuring Timeouts

Sometimes, elements may take time to appear on the page. By default, Pest waits for `5` seconds before timing out. You can configure the default timeout for browser tests in your `Pest.php` configuration file:

```php
pest()->browser()->timeout(10000);
```

### Configuring User Agent

By default, the User Agent will default to the Browser you're running for tests such as: `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/133.0.6943.16 Safari/537.36`

You may wish to override the User Agent of the browser for all of your tests, you can configure this in the `Pest.php` configuration file:

```php
pest()->browser()->userAgent('CustomUserAgent');
```

### Configuring Host

By default, the server will bind to `127.0.0.1` for all browser tests.

You may wish to override the host for subdomain applications. You can configure this in the `Pest.php` configuration file:

```php
pest()->browser()->withHost('some-subdomain.localhost');
```

### Geolocation

Sometimes, you need to define where the browser believes it is physically on the earth.  This method takes a latitude and longitude and will set the `geolocation` permission in the browser and then make the coordinates available via Javascript's getCurrentPosition API:

```php
$page = visit('/')
     ->geolocation(39.399872, -8.224454);
```

### Configuring Locale

You can set the locale for your test requests using the `withLocale` method. This is particularly useful for testing multilingual applications.

```php
$page = visit('/')->withLocale('fr-FR');

$page->assertSee('Bienvenue');
```
### Configuring Timezone

You can set the timezone for your test requests using the `withTimezone` method. This is useful for testing date and time displays in different time zones.

```php
$page = visit('/')->withTimezone('America/New_York');

$page->assertSee('EST');
```

### Configuring UserAgent

You can set the User-Agent header for your test requests using the `withUserAgent` method. This is useful for testing how your application responds to different types of clients, such as mobile browsers or bots.

```php
$page = visit('/')->withUserAgent('Googlebot');

$page->assertSee('Welcome, bot!');
```

### Configuring Host

You can set the host for your test server using the `withHost` method. This is useful for testing subdomains or where different hosts serve different content.

```php
$page = visit('/dashboard')->withHost('some-subdomain.localhost');

$page->assertSee('Welcome to Some Subdomain');
```

## Table of Contents

### Available Assertions

[assertTitle](#assert-title)
[assertTitleContains](#assert-title-contains)
[assertSee](#assert-see)
[assertDontSee](#assert-dont-see)
[assertSeeIn](#assert-see-in)
[assertDontSeeIn](#assert-dont-see-in)
[assertSeeAnythingIn](#assert-see-anything-in)
[assertSeeNothingIn](#assert-see-nothing-in)
[assertCount](#assert-count)
[assertScript](#assert-script)
[assertSourceHas](#assert-source-has)
[assertSourceMissing](#assert-source-missing)
[assertSeeLink](#assert-see-link)
[assertDontSeeLink](#assert-dont-see-link)
[assertChecked](#assert-checked)
[assertNotChecked](#assert-not-checked)
[assertIndeterminate](#assert-indeterminate)
[assertRadioSelected](#assert-radio-selected)
[assertRadioNotSelected](#assert-radio-not-selected)
[assertSelected](#assert-selected)
[assertNotSelected](#assert-not-selected)
[assertValue](#assert-value)
[assertValueIsNot](#assert-value-is-not)
[assertAttribute](#assert-attribute)
[assertAttributeMissing](#assert-attribute-missing)
[assertAttributeContains](#assert-attribute-contains)
[assertAttributeDoesntContain](#assert-attribute-doesnt-contain)
[assertAriaAttribute](#assert-aria-attribute)
[assertDataAttribute](#assert-data-attribute)
[assertVisible](#assert-visible)
[assertPresent](#assert-present)
[assertNotPresent](#assert-not-present)
[assertMissing](#assert-missing)
[assertEnabled](#assert-enabled)
[assertDisabled](#assert-disabled)
[assertButtonEnabled](#assert-button-enabled)
[assertButtonDisabled](#assert-button-disabled)
[assertUrlIs](#assert-url-is)
[assertSchemeIs](#assert-scheme-is)
[assertSchemeIsNot](#assert-scheme-is-not)
[assertHostIs](#assert-host-is)
[assertHostIsNot](#assert-host-is-not)
[assertPortIs](#assert-port-is)
[assertPortIsNot](#assert-port-is-not)
[assertPathBeginsWith](#assert-path-begins-with)
[assertPathEndsWith](#assert-path-ends-with)
[assertPathContains](#assert-path-contains)
[assertPathIs](#assert-path-is)
[assertPathIsNot](#assert-path-is-not)
[assertQueryStringHas](#assert-query-string-has)
[assertQueryStringMissing](#assert-query-string-missing)
[assertFragmentIs](#assert-fragment-is)
[assertFragmentBeginsWith](#assert-fragment-begins-with)
[assertFragmentIsNot](#assert-fragment-is-not)
[assertNoSmoke](#assert-no-smoke)
[assertNoConsoleLogs](#assert-no-console-logs)
[assertNoJavaScriptErrors](#assert-no-javascript-errors)
[assertNoAccessibilityIssues](#assert-no-accessibility-issues)
[assertScreenshotMatches](#assert-screenshot-matches)

### Element Interactions

[click](#click)
[text](#text)
[attribute](#attribute)
[keys](#keys)
[withKeyDown](#withKeyDown)
[type](#type)
[typeSlowly](#type-slowly)
[select](#select)
[append](#append)
[clear](#clear)
[radio](#radio)
[check](#check)
[uncheck](#uncheck)
[attach](#attach)
[press](#press)
[pressAndWaitFor](#press-and-wait-for)
[drag](#drag)
[hover](#hover)
[submit](#submit)
[value](#value)
[withinIframe](#within-iframe)
[resize](#resize)
[script](#script)
[content](#content)
[url](#url)
[wait](#wait)
[waitForKey](#wait-for-key)

### Debugging tests

[debug](#debug)
[screenshot](#screenshot)
[screenshotElement](#screenshot-element)
[tinker](#tinker)
[headed](#headed)

## Element Assertions

---

## Dusk Pages Configuring Pages The `assert` Method
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

#### The `assert` Method

The `assert` method may make any assertions necessary to verify that the browser is actually on the given page. It is not actually necessary to place anything within this method; however, you are free to make these assertions if you wish. These assertions will be run automatically when navigating to the page:

```php
/**
 * Assert that the browser is on the page.
 */
public function assert(Browser $browser): void
{
    $browser->assertPathIs($this->url());
}
```

---

## Dusk Available Assertions assertSeeAnythingIn
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

#### assertSeeAnythingIn

Assert that any text is present within the selector:

```php
$browser->assertSeeAnythingIn($selector);
```

---

## Browser Testing assertNoJavaScriptErrors
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertNoJavaScriptErrors

The `assertNoJavaScriptErrors` method asserts there are no JavaScript errors on the page:

```php
$page->assertNoJavaScriptErrors();
```

---

## Browser Testing assertSee
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertSee

The `assertSee` method asserts that the given text is present on the page:

```php
$page->assertSee('Welcome to our website');
```

---

## Dusk Available Assertions assertSeeIn
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

#### assertSeeIn

Assert that the given text is present within the selector:

```php
$browser->assertSeeIn($selector, $text);
```

---

## Browser Testing wait
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### wait

The `wait` method pauses for the given number of seconds:

```php
$page->wait(2); // Wait for 2 seconds
```

---

## Http Tests Available Assertions Response Assertions
Http Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md

### Response Assertions

Laravel's `Illuminate\Testing\TestResponse` class provides a variety of custom assertion methods that you may utilize when testing your application. These assertions may be accessed on the response that is returned by the `json`, `get`, `post`, `put`, and `delete` test methods:

[assertAccepted](#assert-accepted)
[assertBadRequest](#assert-bad-request)
[assertClientError](#assert-client-error)
[assertConflict](#assert-conflict)
[assertCookie](#assert-cookie)
[assertCookieExpired](#assert-cookie-expired)
[assertCookieNotExpired](#assert-cookie-not-expired)
[assertCookieMissing](#assert-cookie-missing)
[assertCreated](#assert-created)
[assertDontSee](#assert-dont-see)
[assertDontSeeText](#assert-dont-see-text)
[assertDownload](#assert-download)
[assertExactJson](#assert-exact-json)
[assertExactJsonStructure](#assert-exact-json-structure)
[assertFailedDependency](#assert-failed-dependency)
[assertForbidden](#assert-forbidden)
[assertFound](#assert-found)
[assertGone](#assert-gone)
[assertHeader](#assert-header)
[assertHeaderContains](#assert-header-contains)
[assertHeaderMissing](#assert-header-missing)
[assertInternalServerError](#assert-internal-server-error)
[assertJson](#assert-json)
[assertJsonCount](#assert-json-count)
[assertJsonFragment](#assert-json-fragment)
[assertJsonIsArray](#assert-json-is-array)
[assertJsonIsObject](#assert-json-is-object)
[assertJsonMissing](#assert-json-missing)
[assertJsonMissingExact](#assert-json-missing-exact)
[assertJsonMissingValidationErrors](#assert-json-missing-validation-errors)
[assertJsonPath](#assert-json-path)
[assertJsonMissingPath](#assert-json-missing-path)
[assertJsonStructure](#assert-json-structure)
[assertJsonValidationErrors](#assert-json-validation-errors)
[assertJsonValidationErrorFor](#assert-json-validation-error-for)
[assertLocation](#assert-location)
[assertMethodNotAllowed](#assert-method-not-allowed)
[assertMovedPermanently](#assert-moved-permanently)
[assertContent](#assert-content)
[assertNoContent](#assert-no-content)
[assertStreamed](#assert-streamed)
[assertStreamedContent](#assert-streamed-content)
[assertNotFound](#assert-not-found)
[assertOk](#assert-ok)
[assertPaymentRequired](#assert-payment-required)
[assertPlainCookie](#assert-plain-cookie)
[assertRedirect](#assert-redirect)
[assertRedirectBack](#assert-redirect-back)
[assertRedirectBackWithErrors](#assert-redirect-back-with-errors)
[assertRedirectBackWithoutErrors](#assert-redirect-back-without-errors)
[assertRedirectContains](#assert-redirect-contains)
[assertRedirectToRoute](#assert-redirect-to-route)
[assertRedirectToSignedRoute](#assert-redirect-to-signed-route)
[assertRequestTimeout](#assert-request-timeout)
[assertSee](#assert-see)
[assertSeeInOrder](#assert-see-in-order)
[assertSeeText](#assert-see-text)
[assertSeeTextInOrder](#assert-see-text-in-order)
[assertServerError](#assert-server-error)
[assertServiceUnavailable](#assert-service-unavailable)
[assertSessionHas](#assert-session-has)
[assertSessionHasInput](#assert-session-has-input)
[assertSessionHasAll](#assert-session-has-all)
[assertSessionHasErrors](#assert-session-has-errors)
[assertSessionHasErrorsIn](#assert-session-has-errors-in)
[assertSessionHasNoErrors](#assert-session-has-no-errors)
[assertSessionDoesntHaveErrors](#assert-session-doesnt-have-errors)
[assertSessionMissing](#assert-session-missing)
[assertStatus](#assert-status)
[assertSuccessful](#assert-successful)
[assertTooManyRequests](#assert-too-many-requests)
[assertUnauthorized](#assert-unauthorized)
[assertUnprocessable](#assert-unprocessable)
[assertUnsupportedMediaType](#assert-unsupported-media-type)
[assertValid](#assert-valid)
[assertInvalid](#assert-invalid)
[assertViewHas](#assert-view-has)
[assertViewHasAll](#assert-view-has-all)
[assertViewIs](#assert-view-is)
[assertViewMissing](#assert-view-missing)

---

## Browser Testing resize
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### resize

You may use the resize method to adjust the size of the browser window:

```php
$page->resize(1280, 720);
```

---

## Browser Testing assertScript
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertScript

The `assertScript` method asserts that the given JavaScript expression evaluates to the given value:

```php
$page->assertScript('document.title', 'Home Page');
$page->assertScript('document.querySelector(".btn").disabled', true);
```

---

## Browser Testing assertSeeIn
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertSeeIn

The `assertSeeIn` method asserts that the given text is present within the selector:

```php
$page->assertSeeIn('.header', 'Welcome');
```

---

## Browser Testing url
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### url

The `url` method gets the page's URL:

```php
$currentUrl = $page->url();
```

---

## Browser Testing script
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### script

The `script` method executes a script in the context of the page:

```php
$result = $page->script('document.title');
```

---

## Browser Testing content
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### content

The `content` method gets the page's content:

```php
$html = $page->content();
```

---

## Browser Testing assertNoSmoke
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertNoSmoke

The `assertNoSmoke` method asserts there are no console logs or JavaScript errors on the page:

```php
$page->assertNoSmoke();
```

---

## Browser Testing check
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### check

The `check` method checks the given checkbox:

```php
$page->check('terms');
$page->check('color', 'blue'); // For checkbox with specific value
```

---

## Browser Testing withinIframe
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### withinIframe

The `withinIframe` method allows you to interact with elements inside an iframe:

```php
use Pest\Browser\Api\PendingAwaitablePage;

$page->withinIframe('.iframe-container', function (PendingAwaitablePage $page) {
    $page->type('frame-input', 'Hello iframe')
        ->click('frame-button');
});
```

---

## Browser Testing assertSeeAnythingIn
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertSeeAnythingIn

The `assertSeeAnythingIn` method asserts that any text is present within the selector:

```php
$page->assertSeeAnythingIn('.content');
```

---

## Dusk Browser Basics Resizing Browser Windows
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

### Resizing Browser Windows

You may use the `resize` method to adjust the size of the browser window:

```php
$browser->resize(1920, 1080);
```

The `maximize` method may be used to maximize the browser window:

```php
$browser->maximize();
```

The `fitContent` method will resize the browser window to match the size of its content:

```php
$browser->fitContent();
```

When a test fails, Dusk will automatically resize the browser to fit the content prior to taking a screenshot. You may disable this feature by calling the `disableFitOnFailure` method within your test:

```php
$browser->disableFitOnFailure();
```

You may use the `move` method to move the browser window to a different position on your screen:

```php
$browser->move($x = 100, $y = 100);
```

---

## Browser Testing select
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### select

The `select` method selects the given value in the given field:

```php
$page->select('country', 'US');
$page->select('interests', ['music', 'sports']); // Multiple select
```

---

## Browser Testing submit
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### submit

The `submit` method submits the first form found on the page:

```php
$page->submit();
```

---

## Browser Testing value
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### value

The `value` method gets the value of the element matching the given selector:

```php
$value = $page->value('input[name=email]');
```

---

## Browser Testing drag
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### drag

The `drag` method drags an element to another element using selectors:

```php
$page->drag('#item', '#target');
```

---

## Dusk Browser Basics Creating Browsers
Dusk | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/dusk.md

### Creating Browsers

To get started, let's write a test that verifies we can log into our application. After generating a test, we can modify it to navigate to the login page, enter some credentials, and click the "Login" button. To create a browser instance, you may call the `browse` method from within your Dusk test:

```php tab=Pest
<?php

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;

pest()->use(DatabaseMigrations::class);

test('basic example', function () {
    $user = User::factory()->create([
        'email' => 'taylor@laravel.com',
    ]);

    $this->browse(function (Browser $browser) use ($user) {
        $browser->visit('/login')
            ->type('email', $user->email)
            ->type('password', 'password')
            ->press('Login')
            ->assertPathIs('/home');
    });
});
```

```php tab=PHPUnit
<?php

namespace Tests\Browser;

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;

    /**
     * A basic browser test example.
     */
    public function test_basic_example(): void
    {
        $user = User::factory()->create([
            'email' => 'taylor@laravel.com',
        ]);

        $this->browse(function (Browser $browser) use ($user) {
            $browser->visit('/login')
                ->type('email', $user->email)
                ->type('password', 'password')
                ->press('Login')
                ->assertPathIs('/home');
        });
    }
}
```

As you can see in the example above, the `browse` method accepts a closure. A browser instance will automatically be passed to this closure by Dusk and is the main object used to interact with and make assertions against your application.

---

## Browser Testing hover
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### hover

The `hover` method hovers over the given element:

```php
$page->hover('#item');
```

---

## Browser Testing assertNotPresent
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertNotPresent

The `assertNotPresent` method asserts that the element matching the given selector is not present in the DOM:

```php
$page->assertNotPresent('.error-message');
```

---

## Browser Testing keys
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### keys

The `keys` method sends the given keys to the element matching the given selector:

```php
$page->keys('input[name=password]', 'secret');
$page->keys('input[name=password]', ['{Control}', 'a']); // Keyboard shortcuts
```

---

## Browser Testing assertNoAccessibilityIssues
Browser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md

### assertNoAccessibilityIssues

The `assertNoAccessibilityIssues` method asserts there are no "serious" accessibility issues on the page:

```php
$page->assertNoAccessibilityIssues();
```

By default, the level is 1 (serious). You can change to one of the following levels:

```
0. Critical
1. Serious
2. Moderate
3. Minor
```

- The level 0 (critical) only reports issues that cause severe barriers for individuals with disabilities. The organization may be subject to legal action if these issues are not addressed.
- The level 1 (serious) includes all critical issues (level 0) and adds issues that significantly impact accessibility. The organization may be subject to legal action if these issues are not addressed.
- The level 2 (moderate) includes all serious issues (level 1) and adds issues that moderately affect accessibility. The end-user would appreciate the fix, but it is not a barrier.
- The level 3 (minor) includes all moderate issues (level 2) and adds issues that have a minor impact on accessibility. These issues are often related to best practices and do not significantly affect the user experience.

## Screenshot Assertions

_[Truncated]_