command: sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/laravel-best-practices/SKILL.md

aggregated_output:
---
name: laravel-best-practices
description: "Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization and security patterns, validation, error handling, queue and job configuration, route definitions, and architectural decisions. Also use for Laravel code reviews and refactoring existing Laravel code to follow best practices. Covers any task involving Laravel backend PHP code patterns."
license: MIT
metadata:
  author: laravel
---

# Laravel Best Practices

Best practices for Laravel, prioritized by impact. Each rule teaches what to do and why. For exact API syntax, verify with `search-docs`.

## Consistency First

Before applying any rule, check what the application already does. Laravel offers multiple valid approaches — the best choice is the one the codebase already uses, even if another pattern would be theoretically better. Inconsistency is worse than a suboptimal pattern.

Check sibling files, related controllers, models, or tests for established patterns. If one exists, follow it — don't introduce a second way. These rules are defaults for when no pattern exists yet, not overrides.

## Quick Reference

### 1. Database Performance → `rules/db-performance.md`

- Eager load with `with()` to prevent N+1 queries
- Enable `Model::preventLazyLoading()` in development
- Select only needed columns, avoid `SELECT *`
- `chunk()` / `chunkById()` for large datasets
- Index columns used in `WHERE`, `ORDER BY`, `JOIN`
- `withCount()` instead of loading relations to count
- `cursor()` for memory-efficient read-only iteration
- Never query in Blade templates

### 2. Advanced Query Patterns → `rules/advanced-queries.md`

- `addSelect()` subqueries over eager-loading entire has-many for a single value
- Dynamic relationships via subquery FK + `belongsTo`
- Conditional aggregates (`CASE WHEN` in `selectRaw`) over multiple count queries
- `setRelation()` to prevent circular N+1 queries
- `whereIn` + `pluck()` over `whereHas` for better index usage
- Two simple queries can beat one complex query
- Compound indexes matching `orderBy` column order
- Correlated subqueries in `orderBy` for has-many sorting (avoid joins)

### 3. Security → `rules/security.md`

- Define `$fillable` or `$guarded` on every model, authorize every action via policies or gates
- No raw SQL with user input — use Eloquent or query builder
- `{{ }}` for output escaping, `@csrf` on all POST/PUT/DELETE forms, `throttle` on auth and API routes
- Validate MIME type, extension, and size for file uploads
- Never commit `.env`, use `config()` for secrets, `encrypted` cast for sensitive DB fields

### 4. Caching → `rules/caching.md`

- `Cache::remember()` over manual get/put
- `Cache::flexible()` for stale-while-revalidate on high-traffic data
- `Cache::memo()` to avoid redundant cache hits within a request
- Cache tags to invalidate related groups
- `Cache::add()` for atomic conditional writes
- `once()` to memoize per-request or per-object lifetime
- `Cache::lock()` / `lockForUpdate()` for race conditions
- Failover cache stores in production

### 5. Eloquent Patterns → `rules/eloquent.md`

- Correct relationship types with return type hints
- Local scopes for reusable query constraints
- Global scopes sparingly — document their existence
- Attribute casts in the `casts()` method
- Cast date columns, use Carbon instances in templates
- `whereBelongsTo($model)` for cleaner queries
- Never hardcode table names — use `(new Model)->getTable()` or Eloquent queries

### 6. Validation & Forms → `rules/validation.md`

- Form Request classes, not inline validation
- Array notation `['required', 'email']` for new code; follow existing convention
- `$request->validated()` only — never `$request->all()`
- `Rule::when()` for conditional validation
- `after()` instead of `withValidator()`

### 7. Configuration → `rules/config.md`

- `env()` only inside config files
- `App::environment()` or `app()->isProduction()`
- Config, lang files, and constants over hardcoded text

### 8. Testing Patterns → `rules/testing.md`

- `LazilyRefreshDatabase` over `RefreshDatabase` for speed
- `assertModelExists()` over raw `assertDatabaseHas()`
- Factory states and sequences over manual overrides
- Use fakes (`Event::fake()`, `Exceptions::fake()`, etc.) — but always after factory setup, not before
- `recycle()` to share relationship instances across factories

### 9. Queue & Job Patterns → `rules/queue-jobs.md`

- `retry_after` must exceed job `timeout`; use exponential backoff `[1, 5, 10]`
- `ShouldBeUnique` to prevent duplicates; `ShouldBeUniqueUntilProcessing` for early lock release
- Always implement `failed()`; with `retryUntil()`, set `$tries = 0`
- `RateLimited` middleware for external API calls; `Bus::batch()` for related jobs
- Horizon for complex multi-queue scenarios

### 10. Routing & Controllers → `rules/routing.md`

- Implicit route model binding
- Scoped bindings for nested resources
- `Route::resource()` or `apiResource()`
- Methods under 10 lines — extract to actions/services
- Type-hint Form Requests for auto-validation

### 11. HTTP Client → `rules/http-client.md`

- Explicit `timeout` and `connectTimeout` on every request
- `retry()` with exponential backoff for external APIs
- Check response status or use `throw()`
- `Http::pool()` for concurrent independent requests
- `Http::fake()` and `preventStrayRequests()` in tests

### 12. Events, Notifications & Mail → `rules/events-notifications.md`, `rules/mail.md`

- Event discovery over manual registration; `event:cache` in production
- `ShouldDispatchAfterCommit` / `afterCommit()` inside transactions
- Queue notifications and mailables with `ShouldQueue`
- On-demand notifications for non-user recipients
- `HasLocalePreference` on notifiable models
- `assertQueued()` not `assertSent()` for queued mailables
- Markdown mailables for transactional emails

### 13. Error Handling → `rules/error-handling.md`

- `report()`/`render()` on exception classes or in `bootstrap/app.php` — follow existing pattern
- `ShouldntReport` for exceptions that should never log
- Throttle high-volume exceptions to protect log sinks
- `dontReportDuplicates()` for multi-catch scenarios
- Force JSON rendering for API routes
- Structured context via `context()` on exception classes

### 14. Task Scheduling → `rules/scheduling.md`

- `withoutOverlapping()` on variable-duration tasks
- `onOneServer()` on multi-server deployments
- `runInBackground()` for concurrent long tasks
- `environments()` to restrict to appropriate environments
- `takeUntilTimeout()` for time-bounded processing
- Schedule groups for shared configuration

### 15. Architecture → `rules/architecture.md`

- Single-purpose Action classes; dependency injection over `app()` helper
- Prefer official Laravel packages and follow conventions, don't override defaults
- Default to `ORDER BY id DESC` or `created_at DESC`; `mb_*` for UTF-8 safety
- `defer()` for post-response work; `Context` for request-scoped data; `Concurrency::run()` for parallel execution

### 16. Migrations → `rules/migrations.md`

- Generate migrations with `php artisan make:migration`
- `constrained()` for foreign keys
- Never modify migrations that have run in production
- Add indexes in the migration, not as an afterthought
- Mirror column defaults in model `$attributes`
- Reversible `down()` by default; forward-fix migrations for intentionally irreversible changes
- One concern per migration — never mix DDL and DML

### 17. Collections → `rules/collections.md`

- Higher-order messages for simple collection operations
- `cursor()` vs. `lazy()` — choose based on relationship needs
- `lazyById()` when updating records while iterating
- `toQuery()` for bulk operations on collections

### 18. Blade & Views → `rules/blade-views.md`

- `$attributes->merge()` in component templates
- Blade components over `@include`; `@pushOnce` for per-component scripts
- View Composers for shared view data
- `@aware` for deeply nested component props

### 19. Conventions & Style → `rules/style.md`

- Follow Laravel naming conventions for all entities
- Prefer Laravel helpers (`Str`, `Arr`, `Number`, `Uri`, `Str::of()`, `$request->string()`) over raw PHP functions


output:
Chunk ID: e4d6c8
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2128
Output:
---
name: laravel-best-practices
description: "Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization and security patterns, validation, error handling, queue and job configuration, route definitions, and architectural decisions. Also use for Laravel code reviews and refactoring existing Laravel code to follow best practices. Covers any task involving Laravel backend PHP code patterns."
license: MIT
metadata:
  author: laravel
---

# Laravel Best Practices

Best practices for Laravel, prioritized by impact. Each rule teaches what to do and why. For exact API syntax, verify with `search-docs`.

## Consistency First

Before applying any rule, check what the application already does. Laravel offers multiple valid approaches — the best choice is the one the codebase already uses, even if another pattern would be theoretically better. Inconsistency is worse than a suboptimal pattern.

Check sibling files, related controllers, models, or tests for established patterns. If one exists, follow it — don't introduce a second way. These rules are defaults for when no pattern exists yet, not overrides.

## Quick Reference

### 1. Database Performance → `rules/db-performance.md`

- Eager load with `with()` to prevent N+1 queries
- Enable `Model::preventLazyLoading()` in development
- Select only needed columns, avoid `SELECT *`
- `chunk()` / `chunkById()` for large datasets
- Index columns used in `WHERE`, `ORDER BY`, `JOIN`
- `withCount()` instead of loading relations to count
- `cursor()` for memory-efficient read-only iteration
- Never query in Blade templates

### 2. Advanced Query Patterns → `rules/advanced-queries.md`

- `addSelect()` subqueries over eager-loading entire has-many for a single value
- Dynamic relationships via subquery FK + `belongsTo`
- Conditional aggregates (`CASE WHEN` in `selectRaw`) over multiple count queries
- `setRelation()` to prevent circular N+1 queries
- `whereIn` + `pluck()` over `whereHas` for better index usage
- Two simple queries can beat one complex query
- Compound indexes matching `orderBy` column order
- Correlated subqueries in `orderBy` for has-many sorting (avoid joins)

### 3. Security → `rules/security.md`

- Define `$fillable` or `$guarded` on every model, authorize every action via policies or gates
- No raw SQL with user input — use Eloquent or query builder
- `{{ }}` for output escaping, `@csrf` on all POST/PUT/DELETE forms, `throttle` on auth and API routes
- Validate MIME type, extension, and size for file uploads
- Never commit `.env`, use `config()` for secrets, `encrypted` cast for sensitive DB fields

### 4. Caching → `rules/caching.md`

- `Cache::remember()` over manual get/put
- `Cache::flexible()` for stale-while-revalidate on high-traffic data
- `Cache::memo()` to avoid redundant cache hits within a request
- Cache tags to invalidate related groups
- `Cache::add()` for atomic conditional writes
- `once()` to memoize per-request or per-object lifetime
- `Cache::lock()` / `lockForUpdate()` for race conditions
- Failover cache stores in production

### 5. Eloquent Patterns → `rules/eloquent.md`

- Correct relationship types with return type hints
- Local scopes for reusable query constraints
- Global scopes sparingly — document their existence
- Attribute casts in the `casts()` method
- Cast date columns, use Carbon instances in templates
- `whereBelongsTo($model)` for cleaner queries
- Never hardcode table names — use `(new Model)->getTable()` or Eloquent queries

### 6. Validation & Forms → `rules/validation.md`

- Form Request classes, not inline validation
- Array notation `['required', 'email']` for new code; follow existing convention
- `$request->validated()` only — never `$request->all()`
- `Rule::when()` for conditional validation
- `after()` instead of `withValidator()`

### 7. Configuration → `rules/config.md`

- `env()` only inside config files
- `App::environment()` or `app()->isProduction()`
- Config, lang files, and constants over hardcoded text

### 8. Testing Patterns → `rules/testing.md`

- `LazilyRefreshDatabase` over `RefreshDatabase` for speed
- `assertModelExists()` over raw `assertDatabaseHas()`
- Factory states and sequences over manual overrides
- Use fakes (`Event::fake()`, `Exceptions::fake()`, etc.) — but always after factory setup, not before
- `recycle()` to share relationship instances across factories

### 9. Queue & Job Patterns → `rules/queue-jobs.md`

- `retry_after` must exceed job `timeout`; use exponential backoff `[1, 5, 10]`
- `ShouldBeUnique` to prevent duplicates; `ShouldBeUniqueUntilProcessing` for early lock release
- Always implement `failed()`; with `retryUntil()`, set `$tries = 0`
- `RateLimited` middleware for external API calls; `Bus::batch()` for related jobs
- Horizon for complex multi-queue scenarios

### 10. Routing & Controllers → `rules/routing.md`

- Implicit route model binding
- Scoped bindings for nested resources
- `Route::resource()` or `apiResource()`
- Methods under 10 lines — extract to actions/services
- Type-hint Form Requests for auto-validation

### 11. HTTP Client → `rules/http-client.md`

- Explicit `timeout` and `connectTimeout` on every request
- `retry()` with exponential backoff for external APIs
- Check response status or use `throw()`
- `Http::pool()` for concurrent independent requests
- `Http::fake()` and `preventStrayRequests()` in tests

### 12. Events, Notifications & Mail → `rules/events-notifications.md`, `rules/mail.md`

- Event discovery over manual registration; `event:cache` in production
- `ShouldDispatchAfterCommit` / `afterCommit()` inside transactions
- Queue notifications and mailables with `ShouldQueue`
- On-demand notifications for non-user recipients
- `HasLocalePreference` on notifiable models
- `assertQueued()` not `assertSent()` for queued mailables
- Markdown mailables for transactional emails

### 13. Error Handling → `rules/error-handling.md`

- `report()`/`render()` on exception classes or in `bootstrap/app.php` — follow existing pattern
- `ShouldntReport` for exceptions that should never log
- Throttle high-volume exceptions to protect log sinks
- `dontReportDuplicates()` for multi-catch scenarios
- Force JSON rendering for API routes
- Structured context via `context()` on exception classes

### 14. Task Scheduling → `rules/scheduling.md`

- `withoutOverlapping()` on variable-duration tasks
- `onOneServer()` on multi-server deployments
- `runInBackground()` for concurrent long tasks
- `environments()` to restrict to appropriate environments
- `takeUntilTimeout()` for time-bounded processing
- Schedule groups for shared configuration

### 15. Architecture → `rules/architecture.md`

- Single-purpose Action classes; dependency injection over `app()` helper
- Prefer official Laravel packages and follow conventions, don't override defaults
- Default to `ORDER BY id DESC` or `created_at DESC`; `mb_*` for UTF-8 safety
- `defer()` for post-response work; `Context` for request-scoped data; `Concurrency::run()` for parallel execution

### 16. Migrations → `rules/migrations.md`

- Generate migrations with `php artisan make:migration`
- `constrained()` for foreign keys
- Never modify migrations that have run in production
- Add indexes in the migration, not as an afterthought
- Mirror column defaults in model `$attributes`
- Reversible `down()` by default; forward-fix migrations for intentionally irreversible changes
- One concern per migration — never mix DDL and DML

### 17. Collections → `rules/collections.md`

- Higher-order messages for simple collection operations
- `cursor()` vs. `lazy()` — choose based on relationship needs
- `lazyById()` when updating records while iterating
- `toQuery()` for bulk operations on collections

### 18. Blade & Views → `rules/blade-views.md`

- `$attributes->merge()` in component templates
- Blade components over `@include`; `@pushOnce` for per-component scripts
- View Composers for shared view data
- `@aware` for deeply nested component props

### 19. Conventions & Style → `rules/style.md`

- Follow Laravel naming conventions for all entities
- Prefer Laravel helpers (`Str`, `Arr`, `Number`, `Uri`, `Str::of()`, `$request->string()`) over raw PHP functions


command: sed -n '1,180p' /Users/fabianwesner/Herd/shop/.agents/skills/livewire-development/SKILL.md

SKILL.md

type: read

aggregated_output:
---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)

status: completed


output:
Chunk ID: 270dbc
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1888
Output:
---
name: livewire-development
description: "Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, wire:sort, or islands, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, drag-and-drop, loading states, migrating from Livewire 3 to 4, converting component formats (SFC/MFC/class-based), and performance optimization. Do not use for non-Livewire reactive UI (React, Vue, Alpine-only, Inertia.js) or standard Laravel forms without Livewire."
license: MIT
metadata:
  author: laravel
---

# Livewire Development

## Documentation

Use `search-docs` for detailed Livewire 4 patterns and documentation.

## Basic Usage

### Creating Components

```bash

# Single-file component (SFC - default in v4)

# Creates: resources/views/components/⚡create-post.blade.php

php artisan make:livewire create-post

# Page component (SFC - Full Page in v4)

# Creates: resources/views/pages/⚡create-post.blade.php

php artisan make:livewire pages::create-post

# Multi-file component (MFC)

# Creates: resources/views/components/⚡create-post/create-post.php

#          resources/views/components/⚡create-post/create-post.blade.php

php artisan make:livewire create-post --mfc

# Class-based component (v3 style)

# Creates: app/Livewire/CreatePost.php AND resources/views/livewire/create-post.blade.php

php artisan make:livewire create-post --class

# With namespace

php artisan make:livewire Posts/CreatePost
```

### Converting Between Formats

Use `php artisan livewire:convert create-post` to convert between single-file, multi-file, and class-based formats.

### Choosing a Component Format

> **Always follow the project's existing conventions first.** Before creating any component, inspect the project's existing Livewire components to determine the established format (SFC, MFC, or class-based) and directory structure. Check `app/Livewire/`, `resources/views/components/`, and `resources/views/livewire/` for existing components. If the project already uses a consistent format, **use that same format** — even if it differs from the Livewire v4 defaults below. Only fall back to the v4 defaults (SFC in `resources/views/components/`) when no existing convention is established.

Also check `config/livewire.php` for `make_command.type`, `make_command.emoji`, `component_locations`, and `component_namespaces` overrides, which change the default format and where files are stored.

### Component Format Reference

| Format | Flag | Class Path | View Path |
|--------|------|------------|-----------|
| Single-file (SFC) | default | — | `resources/views/components/⚡create-post.blade.php` (PHP + Blade in one file) |
| Full Page SFC | `pages::name` | — | `resources/views/pages/⚡create-post.blade.php` |
| Multi-file (MFC) | `--mfc` | `resources/views/components/⚡create-post/create-post.php` | `resources/views/components/⚡create-post/create-post.blade.php` |
| Class-based | `--class` | `app/Livewire/CreatePost.php` | `resources/views/livewire/create-post.blade.php` |
| View-based | default (Blade-only) | — | `resources/views/components/⚡create-post.blade.php` (Blade-only with functional state) |

> **Important:** The ⚡ prefix shown above is the **default** behavior in Livewire v4 — it is **configurable**. Check `config/livewire.php` for the `make_command.emoji` setting. When `true` (default), always include the ⚡ prefix in filenames you create. When `false`, omit the ⚡ prefix from all paths above.

Namespaced components map to subdirectories: `make:livewire Posts/CreatePost` creates `resources/views/components/posts/⚡create-post.blade.php` (single-file by default). Use `make:livewire Posts/CreatePost --mfc` for multi-file output at `resources/views/components/posts/⚡create-post/create-post.php` and `resources/views/components/posts/⚡create-post/create-post.blade.php`.

### Single-File Component Example

<!-- Single-File Component Example -->
```php
<?php
use Livewire\Component;

new class extends Component {
    public int $count = 0;

    public function increment(): void
    {
        $this->count++;
    }
};
?>

<div>
    <button wire:click="increment">Count: @{{ $count }}</button>
</div>
```

## Livewire 4 Specifics

### Key Changes From Livewire 3

These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.

- Use `Route::livewire()` for full-page components (e.g., `Route::livewire('/posts/create', CreatePost::class)`); config keys renamed: `layout` → `component_layout`, `lazy_placeholder` → `component_placeholder`.
- `wire:model` now ignores child events by default (use `wire:model.deep` for old behavior); `wire:scroll` renamed to `wire:navigate:scroll`.
- Component tags must be properly closed; `wire:transition` now uses View Transitions API (modifiers removed).
- JavaScript: `$wire.$js('name', fn)` → `$wire.$js.name = fn`; `commit`/`request` hooks → `interceptMessage()`/`interceptRequest()`.

### New Features

- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (`@island`) for isolated updates; async actions (`wire:click.async`, `#[Async]`) for parallel execution.
- Deferred/bundled loading: `defer`, `lazy.bundle` for optimized component loading.

| Feature | Usage | Purpose |
|---------|-------|---------|
| Islands | `@island(name: 'stats')` | Isolated update regions |
| Async | `wire:click.async` or `#[Async]` | Non-blocking actions |
| Deferred | `defer` attribute | Load after page render |
| Bundled | `lazy.bundle` | Load multiple together |

### New Directives

- `wire:sort`, `wire:intersect`, `wire:ref`, `.renderless`, `.preserve-scroll` are available for use.
- `data-loading` attribute automatically added to elements triggering network requests.

| Directive | Purpose |
|-----------|---------|
| `wire:sort` | Drag-and-drop sorting |
| `wire:intersect` | Viewport intersection detection |
| `wire:ref` | Element references for JS |
| `.renderless` | Component without rendering |
| `.preserve-scroll` | Preserve scroll position |

## Best Practices

- Always use `wire:key` in loops
- Use `wire:loading` for loading states
- Use `wire:model.live` for instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)

## Configuration

- `smart_wire_keys` defaults to `true`; new configs: `component_locations`, `component_namespaces`, `make_command`, `csp_safe`.

## Alpine & JavaScript

- `wire:transition` uses browser View Transitions API; `$errors` and `$intercept` magic properties available.
- Non-blocking `wire:poll` and parallel `wire:model.live` updates improve performance.

For interceptors and hooks, see [reference/javascript-hooks.md](reference/javascript-hooks.md).

## Testing

<!-- Testing Example -->
```php
Livewire::test(Counter::class)
    ->assertSet('count', 0)
    ->call('increment')
    ->assertSet('count', 1);
```

## Verification

1. Browser console: Check for JS errors
2. Network tab: Verify Livewire requests return 200
3. Ensure `wire:key` on all `@foreach` loops

## Common Pitfalls

- Missing `wire:key` in loops → unexpected re-rendering
- Expecting `wire:model` real-time → use `wire:model.live`
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)


server: laravel-boost

tool: search-docs

packages: pestphp/pest livewire/livewire livewire/flux laravel/framework

queries: browser testing authenticated session form modal select click

queries: Livewire modal form submit action validation testing

queries: Flux modal form button callout badge testing

queries: Laravel factories relationships browser tests actingAs session

type: text

text:
# Search Results

## Validation Form Request Validation
Validation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md

## Form Request Validation

---

## Components Badge > With close button
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

---

## Seeding Writing Seeders Using Model Factories
Seeding | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/seeding.md

### Using Model Factories

Of course, manually specifying the attributes for each model seed is cumbersome. Instead, you can use [model factories](/docs/{{version}}/eloquent-factories) to conveniently generate large amounts of database records. First, review the [model factory documentation](/docs/{{version}}/eloquent-factories) to learn how to define your factories.

For example, let's create 50 users that each has one related post:

```php
use App\Models\User;

/**
 * Run the database seeders.
 */
public function run(): void
{
    User::factory()
        ->count(50)
        ->hasPosts(1)
        ->create();
}
```

---

## Wire Transition Browser support
Wire Transition | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/wire-transition

## Browser support

View Transitions are supported in Chrome 111+, Edge 111+, and Safari 18+. In browsers that don't support View Transitions, elements will appear and disappear without animation—the functionality still works, just without the visual transition.

> [!warning] Firefox has limited support
> Firefox 144+ supports basic view transitions, but does not support transition types.

[View browser support on caniuse.com →](https://caniuse.com/view-transitions)

---

## Components Badge > As button
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

As button

Make the entire badge clickable by wrapping it in a button element.

<flux:badge as="button" rounded icon="plus" size="lg">Amount</flux:badge>

---

## Components Modal > $flux.modal()
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

$flux.modal()

Alpine.js magic method for controlling modals.

<ui-table-scroll-area>

Parameter

Description

    default|name

Name of the modal to control.

</ui-table-scroll-area>

<ui-table-scroll-area>

Method

Description

    show()

Shows the modal.

    close()

Closes the modal.

</ui-table-scroll-area>

---

## Logging Monolog Channel Customization Creating Custom Channels via Factories
Logging | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/logging.md

### Creating Custom Channels via Factories

If you would like to define an entirely custom channel in which you have full control over Monolog's instantiation and configuration, you may specify a `custom` driver type in your `config/logging.php` configuration file. Your configuration should include a `via` option that contains the name of the factory class which will be invoked to create the Monolog instance:

```php
'channels' => [
    'example-custom-channel' => [
        'driver' => 'custom',
        'via' => App\Logging\CreateCustomLogger::class,
    ],
],
```

Once you have configured the `custom` driver channel, you're ready to define the class that will create your Monolog instance. This class only needs a single `__invoke` method which should return the Monolog logger instance. The method will receive the channels configuration array as its only argument:

```php
<?php

namespace App\Logging;

use Monolog\Logger;

class CreateCustomLogger
{
    /**
     * Create a custom Monolog instance.
     */
    public function __invoke(array $config): Logger
    {
        return new Logger(/* ... */);
    }
}
```

---

## Testing Browser testing
Testing | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing

## Browser testing

Pest v4 includes first-party browser testing support powered by Playwright. This allows you to test your Livewire components in a real browser, interacting with them just like a user would.

### Installing browser testing

First, install the Pest browser plugin:

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

Next, install Playwright via npm:

```shell
npm install playwright@latest
npx playwright install
```

For complete browser testing documentation, see the [Pest browser testing guide](https://pestphp.com/docs/browser-testing).

### Writing browser tests

Instead of using `Livewire::test()`, you can use `Livewire::visit()` to test your component in a real browser:

```php
it('can create a new post', function () {
    Livewire::visit('post.create')
        ->type('[wire\:model="title"]', 'My first post')
        ->type('[wire\:model="content"]', 'This is the content')
        ->press('Save')
        ->assertSee('Post created successfully');
});
```

Browser tests are slower than unit tests but provide end-to-end confidence that your components work as expected in a real browser environment.

For a complete list of available browser testing assertions, see the [Pest browser testing assertions](https://pestphp.com/docs/browser-testing#content-available-assertions).

> [!info] When to use browser tests
> Use browser tests for critical user flows and complex interactions. For most component testing, the standard `Livewire::test()` approach is faster and sufficient.

---

## Eloquent Factories Factory Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

## Factory Relationships

---

## 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
```

---

## Components Modal > Flux::modals()
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

Flux::modals()

PHP method for controlling all modals on the page.

<ui-table-scroll-area>

Method

Description

    close()

Closes all modals on the page.

</ui-table-scroll-area>

---

## Eloquent Factories Factory Relationships Defining Relationships Within Factories
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

### Defining Relationships Within Factories

To define a relationship within your model factory, you will typically assign a new factory instance to the foreign key of the relationship. This is normally done for the "inverse" relationships such as `belongsTo` and `morphTo` relationships. For example, if you would like to create a new user when creating a post, you may do the following:

```php
use App\Models\User;

/**
 * Define the model's default state.
 *
 * @return array<string, mixed>
 */
public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}
```

If the relationship's columns depend on the factory that defines it you may assign a closure to an attribute. The closure will receive the factory's evaluated attribute array:

```php
/**
 * Define the model's default state.
 *
 * @return array<string, mixed>
 */
public function definition(): array
{
    return [
        'user_id' => User::factory(),
        'user_type' => function (array $attributes) {
            return User::find($attributes['user_id'])->type;
        },
        'title' => fake()->title(),
        'content' => fake()->paragraph(),
    ];
}
```

---

## Eloquent Factories Factory Relationships Recycling an Existing Model for Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

### Recycling an Existing Model for Relationships

If you have models that share a common relationship with another model, you may use the `recycle` method to ensure a single instance of the related model is recycled for all of the relationships created by the factory.

For example, imagine you have `Airline`, `Flight`, and `Ticket` models, where the ticket belongs to an airline and a flight, and the flight also belongs to an airline. When creating tickets, you will probably want the same airline for both the ticket and the flight, so you may pass an airline instance to the `recycle` method:

```php
Ticket::factory()
    ->recycle(Airline::factory()->create())
    ->create();
```

You may find the `recycle` method particularly useful if you have models belonging to a common user or team.

The `recycle` method also accepts a collection of existing models. When a collection is provided to the `recycle` method, a random model from the collection will be chosen when the factory needs a model of that type:

```php
Ticket::factory()
    ->recycle($airlines)
    ->create();
```

---

## Styles Browser support
Styles | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/styles

## Browser support

Scoped styles use [CSS nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting), which is supported in all modern browsers (Chrome 120+, Firefox 117+, Safari 17.2+). For older browser support, consider using a CSS preprocessor or the `@assets` directive with pre-compiled stylesheets.

---

## Components Modal > Confirmation
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

Confirmation

Prompt a user for confirmation before performing a dangerous action.

<flux:modal.trigger name="delete-profile">    <flux:button variant="danger">Delete</flux:button></flux:modal.trigger><flux:modal name="delete-profile" class="min-w-[22rem]">

            <flux:heading size="lg">Delete project?</flux:heading>            <flux:text class="mt-2">                You're about to delete this project.
                This action cannot be reversed.            </flux:text>

            <flux:spacer />            <flux:modal.close>                <flux:button variant="ghost">Cancel</flux:button>            </flux:modal.close>            <flux:button type="submit" variant="danger">Delete project</flux:button>

</flux:modal>

---

## Components Modal > Flux::modal()
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

Flux::modal()

PHP method for controlling modals from Livewire components.

<ui-table-scroll-area>

Parameter

Description

    default|name

Name of the modal to control.

</ui-table-scroll-area>

<ui-table-scroll-area>

Method

Description

    close()

Closes the modal.

</ui-table-scroll-area>

---

## Installation Components not updating or errors in browser console
Installation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/installation

## Components not updating or errors in browser console

**Check the following:**
- Ensure `@livewireStyles` is in the `<head>` of your layout
- Ensure `@livewireScripts` is before `</body>` in your layout
- Check your browser's developer console for JavaScript errors
- Verify you're running a supported PHP version (8.1+) and Laravel version (10+)
- Clear your application cache: `php artisan cache:clear`

If issues persist, check the [troubleshooting documentation](/docs/4.x/troubleshooting) for more detailed debugging steps.

---

## Components Modal > flux:modal.close
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

flux:modal.close

<ui-table-scroll-area>

Slot

Description

    default

The close trigger element (e.g., button).

</ui-table-scroll-area>

---

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

## Model Factories

When testing, you may need to insert a few records into your database before executing your test. Instead of manually specifying the value of each column when you create this test data, Laravel allows you to define a set of default attributes for each of your [Eloquent models](/docs/{{version}}/eloquent) using [model factories](/docs/{{version}}/eloquent-factories).

To learn more about creating and utilizing model factories to create models, please consult the complete [model factory documentation](/docs/{{version}}/eloquent-factories). Once you have defined a model factory, you may utilize the factory within your test to create models:

```php tab=Pest
use App\Models\User;

test('models can be instantiated', function () {
    $user = User::factory()->create();

    // ...
});
```

```php tab=PHPUnit
use App\Models\User;

public function test_models_can_be_instantiated(): void
{
    $user = User::factory()->create();

    // ...
}
```

---

## Components Modal > Flyout positioning
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

            Flyout positioning

By default, flyouts will open from the right. You can change this behavior by passing "left", or "bottom" into the position prop.

<flux:modal flyout position="left">    </flux:modal>

Floating flyout

Use the "floating" variant to give your flyout modal a floating appearance.

<flux:modal.trigger name="edit-profile">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name="edit-profile" flyout variant="floating" class="md:w-lg">
        <flux:heading size="lg">Update profile</flux:heading>        <flux:subheading>Make changes to your personal details.</flux:subheading>        <flux:input label="Name" placeholder="Your name" />        <flux:input label="Date of birth" type="date" />
    <x-slot name="footer" class="flex items-center justify-end gap-2">        <flux:modal.close>            <flux:button variant="filled">Cancel</flux:button>        </flux:modal.close>        <flux:button type="submit" variant="primary">Save changes</flux:button>    </x-slot></flux:modal>

---

## Eloquent Factories Factory Relationships Polymorphic Relationships Polymorphic Many to Many Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

#### Polymorphic Many to Many Relationships

Polymorphic "many to many" (`morphToMany` / `morphedByMany`) relationships may be created just like non-polymorphic "many to many" relationships:

```php
use App\Models\Tag;
use App\Models\Video;

$video = Video::factory()
    ->hasAttached(
        Tag::factory()->count(3),
        ['public' => true]
    )
    ->create();
```

Of course, the magic `has` method may also be used to create polymorphic "many to many" relationships:

```php
$video = Video::factory()
    ->hasTags(3, ['public' => true])
    ->create();
```

---

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

### assertSelected

The `assertSelected` method asserts that the given dropdown has the given value selected:

```php
$page->assertSelected('country', 'US');
```

---

## Attribute Url Browser history
Attribute Url | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-url

## Browser history

By default, Livewire uses `history.replaceState()` to modify the URL without adding browser history entries. To add history entries (making the back button restore previous query values), use `history`:

```php
#[Url(history: true)] // [tl! highlight]
public $search = '';
```

Now clicking the browser's back button will restore previous search values instead of navigating to the previous page.

---

## Components Modal > Flyout
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

Flyout

Use the flyout prop for a more anchored and long-form dialog.

<flux:modal.trigger name="edit-profile">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name="edit-profile" flyout>

            <flux:heading size="lg">Update profile</flux:heading>            <flux:text class="mt-2">Make changes to your personal details.</flux:text>
        <flux:input label="Name" placeholder="Your name" />        <flux:input label="Date of birth" type="date" />
            <flux:spacer />            <flux:button type="submit" variant="primary">Save changes</flux:button>

</flux:modal>

---

## Eloquent Factories Factory Relationships Many to Many Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

### Many to Many Relationships

Like [has many relationships](#has-many-relationships), "many to many" relationships may be created using the `has` method:

```php
use App\Models\Role;
use App\Models\User;

$user = User::factory()
    ->has(Role::factory()->count(3))
    ->create();
```

---

## Components Modal > flux:modal.trigger
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

flux:modal.trigger

<ui-table-scroll-area>

Prop

Description

    name

Name of the modal to trigger. Must match the modal's name.

    shortcut

Keyboard shortcut to open the modal (e.g., cmd.k).

</ui-table-scroll-area>

<ui-table-scroll-area>

Slot

Description

    default

The trigger element (e.g., button).

</ui-table-scroll-area>

---

## Components Modal > Modal
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

    Modal

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name="edit-profile">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name="edit-profile" class="md:w-96">

            <flux:heading size="lg">Update profile</flux:heading>            <flux:text class="mt-2">Make changes to your personal details.</flux:text>
        <flux:input label="Name" placeholder="Your name" />        <flux:input label="Date of birth" type="date" />
            <flux:spacer />            <flux:button type="submit" variant="primary">Save changes</flux:button>

</flux:modal>

---

## Eloquent Factories Creating Models Using Factories
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

## Creating Models Using Factories

---

## Eloquent Factories Factory Relationships Polymorphic Relationships Morph To Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

#### Morph To Relationships

Magic methods may not be used to create `morphTo` relationships. Instead, the `for` method must be used directly and the name of the relationship must be explicitly provided. For example, imagine that the `Comment` model has a `commentable` method that defines a `morphTo` relationship. In this situation, we may create three comments that belong to a single post by using the `for` method directly:

```php
$comments = Comment::factory()->count(3)->for(
    Post::factory(), 'commentable'
)->create();
```

---

## Components Modal > flux:modal
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

flux:modal

<ui-table-scroll-area>

Prop

Description

    name

Unique identifier for the modal. Required when using triggers.

    flyout

If true, the modal will open as a flyout.

    variant

Visual style of the modal. Options: default, floating, bare (legacy: flyout).

    position

For flyout modals, the direction they open from. Options: right (default), left, bottom.

    scroll

Scrolling behavior for long content. Options: body. When set to body, the entire viewport scrolls instead of clipping overflow.

    dismissible

If false, prevents closing the modal by clicking outside. Default: true.

    closable

If false, hides the close button. Default: true.

    wire:model

Optional Livewire property to bind the modal's open state to.

</ui-table-scroll-area>

<ui-table-scroll-area>

Event

Description

    close

Triggered when the modal is closed by any means.

    cancel

Triggered when the modal is closed by clicking outside or pressing escape.

</ui-table-scroll-area>

<ui-table-scroll-area>

Slot

Description

    default

The modal content.

</ui-table-scroll-area>

<ui-table-scroll-area>

Class

Description

    w-*

Common use: md:w-96 for width.

</ui-table-scroll-area>

---

## Eloquent Factories Factory Relationships Polymorphic Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

### Polymorphic Relationships

[Polymorphic relationships](/docs/{{version}}/eloquent-relationships#polymorphic-relationships) may also be created using factories. Polymorphic "morph many" relationships are created in the same way as typical "has many" relationships. For example, if an `App\Models\Post` model has a `morphMany` relationship with an `App\Models\Comment` model:

```php
use App\Models\Post;

$post = Post::factory()->hasComments(3)->create();
```

---

## Attribute On Listening to browser events
Attribute On | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-on

## Listening to browser events

You can also listen for browser events dispatched from JavaScript:

```php
#[On('user-logged-in')]
public function handleUserLogin()
{
    // Handle login...
}
```

```javascript
// From JavaScript
window.dispatchEvent(new CustomEvent('user-logged-in'));
```

---

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

### click

The `click` method clicks the link with the given text:

```php
$page->click('Login');
```

You may also pass options:

```php
$page->click('#button', options: ['clickCount' => 2]);
```

---

## Components Modal > Unique modal names
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

Unique modal names

If you are placing modals inside a loop, ensure that you are dynamically generating unique modal names. Otherwise, one modal trigger, will trigger all modals of that name on the page causing unexpected behavior.

@foreach ($users as $user)    <flux:modal :name="'edit-profile-'.$user->id">        ...    </flux:modal>@endforeach

---

## Eloquent Factories Factory Relationships Belongs To Relationships
Eloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md

### Belongs To Relationships

Now that we have explored how to build "has many" relationships using factories, let's explore the inverse of the relationship. The `for` method may be used to define the parent model that factory created models belong to. For example, we can create three `App\Models\Post` model instances that belong to a single user:

```php
use App\Models\Post;
use App\Models\User;

$posts = Post::factory()
    ->count(3)
    ->for(User::factory()->state([
        'name' => 'Jessica Archer',
    ]))
    ->create();
```

If you already have a parent model instance that should be associated with the models you are creating, you may pass the model instance to the `for` method:

```php
$user = User::factory()->create();

$posts = Post::factory()
    ->count(3)
    ->for($user)
    ->create();
```

_[Truncated]_


output:
Wall time: 4.1679 seconds
Output:
[{"type":"text","text":"# Search Results\n\n## Validation Form Request Validation\nValidation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md\n\n\n## Form Request Validation\n\n---\n\n## Components Badge > With close button\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

\n\n---\n\n## Seeding Writing Seeders Using Model Factories\nSeeding | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/seeding.md\n\n\n### Using Model Factories\n\nOf course, manually specifying the attributes for each model seed is cumbersome. Instead, you can use [model factories](/docs/{{version}}/eloquent-factories) to conveniently generate large amounts of database records. First, review the [model factory documentation](/docs/{{version}}/eloquent-factories) to learn how to define your factories.\n\nFor example, let's create 50 users that each has one related post:\n\n```php\nuse App\\Models\\User;\n\n/**\n * Run the database seeders.\n */\npublic function run(): void\n{\n    User::factory()\n        ->count(50)\n        ->hasPosts(1)\n        ->create();\n}\n```\n\n---\n\n## Wire Transition Browser support\nWire Transition | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/wire-transition\n\n## Browser support\n\nView Transitions are supported in Chrome 111+, Edge 111+, and Safari 18+. In browsers that don't support View Transitions, elements will appear and disappear without animation—the functionality still works, just without the visual transition.\n\n> [!warning] Firefox has limited support\n> Firefox 144+ supports basic view transitions, but does not support transition types.\n\n[View browser support on caniuse.com →](https://caniuse.com/view-transitions)\n\n---\n\n## Components Badge > As button\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
As button

Make the entire badge clickable by wrapping it in a button element.

<flux:badge as=\"button\" rounded icon=\"plus\" size=\"lg\">Amount</flux:badge>

\n\n---\n\n## Components Modal > $flux.modal()\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
$flux.modal()

Alpine.js magic method for controlling modals.

<ui-table-scroll-area>

Parameter

Description

\n    default|name\n

Name of the modal to control.

</ui-table-scroll-area>

<ui-table-scroll-area>

Method

Description

\n    show()\n

Shows the modal.

\n    close()\n

Closes the modal.

</ui-table-scroll-area>

\n\n---\n\n## Logging Monolog Channel Customization Creating Custom Channels via Factories\nLogging | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/logging.md\n\n\n### Creating Custom Channels via Factories\n\nIf you would like to define an entirely custom channel in which you have full control over Monolog's instantiation and configuration, you may specify a `custom` driver type in your `config/logging.php` configuration file. Your configuration should include a `via` option that contains the name of the factory class which will be invoked to create the Monolog instance:\n\n```php\n'channels' => [\n    'example-custom-channel' => [\n        'driver' => 'custom',\n        'via' => App\\Logging\\CreateCustomLogger::class,\n    ],\n],\n```\n\nOnce you have configured the `custom` driver channel, you're ready to define the class that will create your Monolog instance. This class only needs a single `__invoke` method which should return the Monolog logger instance. The method will receive the channels configuration array as its only argument:\n\n```php\n<?php\n\nnamespace App\\Logging;\n\nuse Monolog\\Logger;\n\nclass CreateCustomLogger\n{\n    /**\n     * Create a custom Monolog instance.\n     */\n    public function __invoke(array $config): Logger\n    {\n        return new Logger(/* ... */);\n    }\n}\n```\n\n---\n\n## Testing Browser testing\nTesting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/testing\n\n## Browser testing\n\nPest v4 includes first-party browser testing support powered by Playwright. This allows you to test your Livewire components in a real browser, interacting with them just like a user would.\n\n### Installing browser testing\n\nFirst, install the Pest browser plugin:\n\n```shell\ncomposer require pestphp/pest-plugin-browser --dev\n```\n\nNext, install Playwright via npm:\n\n```shell\nnpm install playwright@latest\nnpx playwright install\n```\n\nFor complete browser testing documentation, see the [Pest browser testing guide](https://pestphp.com/docs/browser-testing).\n\n### Writing browser tests\n\nInstead of using `Livewire::test()`, you can use `Livewire::visit()` to test your component in a real browser:\n\n```php\nit('can create a new post', function () {\n    Livewire::visit('post.create')\n        ->type('[wire\\:model=\"title\"]', 'My first post')\n        ->type('[wire\\:model=\"content\"]', 'This is the content')\n        ->press('Save')\n        ->assertSee('Post created successfully');\n});\n```\n\nBrowser tests are slower than unit tests but provide end-to-end confidence that your components work as expected in a real browser environment.\n\nFor a complete list of available browser testing assertions, see the [Pest browser testing assertions](https://pestphp.com/docs/browser-testing#content-available-assertions).\n\n> [!info] When to use browser tests\n> Use browser tests for critical user flows and complex interactions. For most component testing, the standard `Livewire::test()` approach is faster and sufficient.\n\n---\n\n## Eloquent Factories Factory Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n## Factory Relationships\n\n---\n\n## Browser Testing select\nBrowser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md\n\n\n### select\n\nThe `select` method selects the given value in the given field:\n\n```php\n$page->select('country', 'US');\n$page->select('interests', ['music', 'sports']); // Multiple select\n```\n\n---\n\n## Components Modal > Flux::modals()\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
Flux::modals()

PHP method for controlling all modals on the page.

<ui-table-scroll-area>

Method

Description

\n    close()\n

Closes all modals on the page.

</ui-table-scroll-area>

\n\n---\n\n## Eloquent Factories Factory Relationships Defining Relationships Within Factories\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n### Defining Relationships Within Factories\n\nTo define a relationship within your model factory, you will typically assign a new factory instance to the foreign key of the relationship. This is normally done for the \"inverse\" relationships such as `belongsTo` and `morphTo` relationships. For example, if you would like to create a new user when creating a post, you may do the following:\n\n```php\nuse App\\Models\\User;\n\n/**\n * Define the model's default state.\n *\n * @return array<string, mixed>\n */\npublic function definition(): array\n{\n    return [\n        'user_id' => User::factory(),\n        'title' => fake()->title(),\n        'content' => fake()->paragraph(),\n    ];\n}\n```\n\nIf the relationship's columns depend on the factory that defines it you may assign a closure to an attribute. The closure will receive the factory's evaluated attribute array:\n\n```php\n/**\n * Define the model's default state.\n *\n * @return array<string, mixed>\n */\npublic function definition(): array\n{\n    return [\n        'user_id' => User::factory(),\n        'user_type' => function (array $attributes) {\n            return User::find($attributes['user_id'])->type;\n        },\n        'title' => fake()->title(),\n        'content' => fake()->paragraph(),\n    ];\n}\n```\n\n---\n\n## Eloquent Factories Factory Relationships Recycling an Existing Model for Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n### Recycling an Existing Model for Relationships\n\nIf you have models that share a common relationship with another model, you may use the `recycle` method to ensure a single instance of the related model is recycled for all of the relationships created by the factory.\n\nFor example, imagine you have `Airline`, `Flight`, and `Ticket` models, where the ticket belongs to an airline and a flight, and the flight also belongs to an airline. When creating tickets, you will probably want the same airline for both the ticket and the flight, so you may pass an airline instance to the `recycle` method:\n\n```php\nTicket::factory()\n    ->recycle(Airline::factory()->create())\n    ->create();\n```\n\nYou may find the `recycle` method particularly useful if you have models belonging to a common user or team.\n\nThe `recycle` method also accepts a collection of existing models. When a collection is provided to the `recycle` method, a random model from the collection will be chosen when the factory needs a model of that type:\n\n```php\nTicket::factory()\n    ->recycle($airlines)\n    ->create();\n```\n\n---\n\n## Styles Browser support\nStyles | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/styles\n\n## Browser support\n\nScoped styles use [CSS nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting), which is supported in all modern browsers (Chrome 120+, Firefox 117+, Safari 17.2+). For older browser support, consider using a CSS preprocessor or the `@assets` directive with pre-compiled stylesheets.\n\n---\n\n## Components Modal > Confirmation\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
Confirmation

Prompt a user for confirmation before performing a dangerous action.

<flux:modal.trigger name=\"delete-profile\">    <flux:button variant=\"danger\">Delete</flux:button></flux:modal.trigger><flux:modal name=\"delete-profile\" class=\"min-w-[22rem]\">

            <flux:heading size=\"lg\">Delete project?</flux:heading>            <flux:text class=\"mt-2\">                You're about to delete this project.
                This action cannot be reversed.            </flux:text>

            <flux:spacer />            <flux:modal.close>                <flux:button variant=\"ghost\">Cancel</flux:button>            </flux:modal.close>            <flux:button type=\"submit\" variant=\"danger\">Delete project</flux:button>

</flux:modal>

\n\n---\n\n## Components Modal > Flux::modal()\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
Flux::modal()

PHP method for controlling modals from Livewire components.

<ui-table-scroll-area>

Parameter

Description

\n    default|name\n

Name of the modal to control.

</ui-table-scroll-area>

<ui-table-scroll-area>

Method

Description

\n    close()\n

Closes the modal.

</ui-table-scroll-area>

\n\n---\n\n## Installation Components not updating or errors in browser console\nInstallation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/installation\n\n## Components not updating or errors in browser console\n\n**Check the following:**\n- Ensure `@livewireStyles` is in the `<head>` of your layout\n- Ensure `@livewireScripts` is before `</body>` in your layout\n- Check your browser's developer console for JavaScript errors\n- Verify you're running a supported PHP version (8.1+) and Laravel version (10+)\n- Clear your application cache: `php artisan cache:clear`\n\nIf issues persist, check the [troubleshooting documentation](/docs/4.x/troubleshooting) for more detailed debugging steps.\n\n---\n\n## Components Modal > flux:modal.close\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
flux:modal.close

<ui-table-scroll-area>

Slot

Description

\n    default\n

The close trigger element (e.g., button).

</ui-table-scroll-area>

\n\n---\n\n## Database Testing Model Factories\nDatabase Testing | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/database-testing.md\n\n\n## Model Factories\n\nWhen testing, you may need to insert a few records into your database before executing your test. Instead of manually specifying the value of each column when you create this test data, Laravel allows you to define a set of default attributes for each of your [Eloquent models](/docs/{{version}}/eloquent) using [model factories](/docs/{{version}}/eloquent-factories).\n\nTo learn more about creating and utilizing model factories to create models, please consult the complete [model factory documentation](/docs/{{version}}/eloquent-factories). Once you have defined a model factory, you may utilize the factory within your test to create models:\n\n```php tab=Pest\nuse App\\Models\\User;\n\ntest('models can be instantiated', function () {\n    $user = User::factory()->create();\n\n    // ...\n});\n```\n\n```php tab=PHPUnit\nuse App\\Models\\User;\n\npublic function test_models_can_be_instantiated(): void\n{\n    $user = User::factory()->create();\n\n    // ...\n}\n```\n\n---\n\n## Components Modal > Flyout positioning\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
\n            Flyout positioning\n

By default, flyouts will open from the right. You can change this behavior by passing \"left\", or \"bottom\" into the position prop.

<flux:modal flyout position=\"left\">    </flux:modal>

Floating flyout

Use the \"floating\" variant to give your flyout modal a floating appearance.

<flux:modal.trigger name=\"edit-profile\">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name=\"edit-profile\" flyout variant=\"floating\" class=\"md:w-lg\">
        <flux:heading size=\"lg\">Update profile</flux:heading>        <flux:subheading>Make changes to your personal details.</flux:subheading>        <flux:input label=\"Name\" placeholder=\"Your name\" />        <flux:input label=\"Date of birth\" type=\"date\" />
    <x-slot name=\"footer\" class=\"flex items-center justify-end gap-2\">        <flux:modal.close>            <flux:button variant=\"filled\">Cancel</flux:button>        </flux:modal.close>        <flux:button type=\"submit\" variant=\"primary\">Save changes</flux:button>    </x-slot></flux:modal>

\n\n---\n\n## Eloquent Factories Factory Relationships Polymorphic Relationships Polymorphic Many to Many Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n#### Polymorphic Many to Many Relationships\n\nPolymorphic \"many to many\" (`morphToMany` / `morphedByMany`) relationships may be created just like non-polymorphic \"many to many\" relationships:\n\n```php\nuse App\\Models\\Tag;\nuse App\\Models\\Video;\n\n$video = Video::factory()\n    ->hasAttached(\n        Tag::factory()->count(3),\n        ['public' => true]\n    )\n    ->create();\n```\n\nOf course, the magic `has` method may also be used to create polymorphic \"many to many\" relationships:\n\n```php\n$video = Video::factory()\n    ->hasTags(3, ['public' => true])\n    ->create();\n```\n\n---\n\n## Browser Testing assertSelected\nBrowser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md\n\n\n### assertSelected\n\nThe `assertSelected` method asserts that the given dropdown has the given value selected:\n\n```php\n$page->assertSelected('country', 'US');\n```\n\n---\n\n## Attribute Url Browser history\nAttribute Url | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-url\n\n## Browser history\n\nBy default, Livewire uses `history.replaceState()` to modify the URL without adding browser history entries. To add history entries (making the back button restore previous query values), use `history`:\n\n```php\n#[Url(history: true)] // [tl! highlight]\npublic $search = '';\n```\n\nNow clicking the browser's back button will restore previous search values instead of navigating to the previous page.\n\n---\n\n## Components Modal > Flyout\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
Flyout

Use the flyout prop for a more anchored and long-form dialog.

<flux:modal.trigger name=\"edit-profile\">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name=\"edit-profile\" flyout>

            <flux:heading size=\"lg\">Update profile</flux:heading>            <flux:text class=\"mt-2\">Make changes to your personal details.</flux:text>
        <flux:input label=\"Name\" placeholder=\"Your name\" />        <flux:input label=\"Date of birth\" type=\"date\" />
            <flux:spacer />            <flux:button type=\"submit\" variant=\"primary\">Save changes</flux:button>

</flux:modal>

\n\n---\n\n## Eloquent Factories Factory Relationships Many to Many Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n### Many to Many Relationships\n\nLike [has many relationships](#has-many-relationships), \"many to many\" relationships may be created using the `has` method:\n\n```php\nuse App\\Models\\Role;\nuse App\\Models\\User;\n\n$user = User::factory()\n    ->has(Role::factory()->count(3))\n    ->create();\n```\n\n---\n\n## Components Modal > flux:modal.trigger\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
flux:modal.trigger

<ui-table-scroll-area>

Prop

Description

\n    name\n

Name of the modal to trigger. Must match the modal's name.

\n    shortcut\n

Keyboard shortcut to open the modal (e.g., cmd.k).

</ui-table-scroll-area>

<ui-table-scroll-area>

Slot

Description

\n    default\n

The trigger element (e.g., button).

</ui-table-scroll-area>

\n\n---\n\n## Components Modal > Modal\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n

\n    Modal\n

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name=\"edit-profile\">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name=\"edit-profile\" class=\"md:w-96\">

            <flux:heading size=\"lg\">Update profile</flux:heading>            <flux:text class=\"mt-2\">Make changes to your personal details.</flux:text>
        <flux:input label=\"Name\" placeholder=\"Your name\" />        <flux:input label=\"Date of birth\" type=\"date\" />
            <flux:spacer />            <flux:button type=\"submit\" variant=\"primary\">Save changes</flux:button>

</flux:modal>

\n\n---\n\n## Eloquent Factories Creating Models Using Factories\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n## Creating Models Using Factories\n\n---\n\n## Eloquent Factories Factory Relationships Polymorphic Relationships Morph To Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n#### Morph To Relationships\n\nMagic methods may not be used to create `morphTo` relationships. Instead, the `for` method must be used directly and the name of the relationship must be explicitly provided. For example, imagine that the `Comment` model has a `commentable` method that defines a `morphTo` relationship. In this situation, we may create three comments that belong to a single post by using the `for` method directly:\n\n```php\n$comments = Comment::factory()->count(3)->for(\n    Post::factory(), 'commentable'\n)->create();\n```\n\n---\n\n## Components Modal > flux:modal\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
flux:modal

<ui-table-scroll-area>

Prop

Description

\n    name\n

Unique identifier for the modal. Required when using triggers.

\n    flyout\n

If true, the modal will open as a flyout.

\n    variant\n

Visual style of the modal. Options: default, floating, bare (legacy: flyout).

\n    position\n

For flyout modals, the direction they open from. Options: right (default), left, bottom.

\n    scroll\n

Scrolling behavior for long content. Options: body. When set to body, the entire viewport scrolls instead of clipping overflow.

\n    dismissible\n

If false, prevents closing the modal by clicking outside. Default: true.

\n    closable\n

If false, hides the close button. Default: true.

\n    wire:model\n

Optional Livewire property to bind the modal's open state to.

</ui-table-scroll-area>

<ui-table-scroll-area>

Event

Description

\n    close\n

Triggered when the modal is closed by any means.

\n    cancel\n

Triggered when the modal is closed by clicking outside or pressing escape.

</ui-table-scroll-area>

<ui-table-scroll-area>

Slot

Description

\n    default\n

The modal content.

</ui-table-scroll-area>

<ui-table-scroll-area>

Class

Description

\n    w-*\n

Common use: md:w-96 for width.

</ui-table-scroll-area>

\n\n---\n\n## Eloquent Factories Factory Relationships Polymorphic Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n### Polymorphic Relationships\n\n[Polymorphic relationships](/docs/{{version}}/eloquent-relationships#polymorphic-relationships) may also be created using factories. Polymorphic \"morph many\" relationships are created in the same way as typical \"has many\" relationships. For example, if an `App\\Models\\Post` model has a `morphMany` relationship with an `App\\Models\\Comment` model:\n\n```php\nuse App\\Models\\Post;\n\n$post = Post::factory()->hasComments(3)->create();\n```\n\n---\n\n## Attribute On Listening to browser events\nAttribute On | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-on\n\n## Listening to browser events\n\nYou can also listen for browser events dispatched from JavaScript:\n\n```php\n#[On('user-logged-in')]\npublic function handleUserLogin()\n{\n    // Handle login...\n}\n```\n\n```javascript\n// From JavaScript\nwindow.dispatchEvent(new CustomEvent('user-logged-in'));\n```\n\n---\n\n## Browser Testing click\nBrowser Testing | pestphp/pest@4.x | Source: https://github.com/pestphp/docs/blob/4.x/browser-testing.md\n\n\n### click\n\nThe `click` method clicks the link with the given text:\n\n```php\n$page->click('Login');\n```\n\nYou may also pass options:\n\n```php\n$page->click('#button', options: ['clickCount' => 2]);\n```\n\n---\n\n## Components Modal > Unique modal names\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n
Unique modal names

If you are placing modals inside a loop, ensure that you are dynamically generating unique modal names. Otherwise, one modal trigger, will trigger all modals of that name on the page causing unexpected behavior.

@foreach ($users as $user)    <flux:modal :name=\"'edit-profile-'.$user->id\">        ...    </flux:modal>@endforeach

\n\n---\n\n## Eloquent Factories Factory Relationships Belongs To Relationships\nEloquent Factories | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/eloquent-factories.md\n\n\n### Belongs To Relationships\n\nNow that we have explored how to build \"has many\" relationships using factories, let's explore the inverse of the relationship. The `for` method may be used to define the parent model that factory created models belong to. For example, we can create three `App\\Models\\Post` model instances that belong to a single user:\n\n```php\nuse App\\Models\\Post;\nuse App\\Models\\User;\n\n$posts = Post::factory()\n    ->count(3)\n    ->for(User::factory()->state([\n        'name' => 'Jessica Archer',\n    ]))\n    ->create();\n```\n\nIf you already have a parent model instance that should be associated with the models you are creating, you may pass the model instance to the `for` method:\n\n```php\n$user = User::factory()->create();\n\n$posts = Post::factory()\n    ->count(3)\n    ->for($user)\n    ->create();\n```\n\n_[Truncated]_"}]


cmd: rg -n "toast|x-on:toast|data-test=.*toast|Product saved|Discount saved|Fulfillment created" resources app tests


command: rg -n "toast|x-on:toast|data-test=.*toast|Product saved|Discount saved|Fulfillment created" resources app tests

type: search

cmd: rg -n 'toast|x-on:toast|data-test=.*toast|Product saved|Discount saved|Fulfillment created' resources app tests

query: toast|x-on:toast|data-test=.*toast|Product saved|Discount saved|Fulfillment created

path: resources

aggregated_output:
tests/Feature/Catalog/CatalogUiTest.php:95:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:106:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:135:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:144:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:189:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:208:        ->assertSee('Product saved');
tests/Feature/Admin/ProductMediaManagementTest.php:88:        ->assertSee('Product saved');
tests/Browser/Admin/ProductManagementTest.php:89:        ->assertSee('Product saved')
app/Enums/WebhookEventType.php:35:            self::FulfillmentCreated => 'Fulfillment created',
app/Livewire/Admin/Developers/Index.php:70:        $this->dispatch('toast', type: 'success', message: __('API token generated'));
app/Livewire/Admin/Developers/Index.php:80:        $this->dispatch('toast', type: 'success', message: __('API token revoked'));
app/Livewire/Admin/Developers/Index.php:127:        $this->dispatch('toast', type: 'success', message: __('Webhook saved'));
app/Livewire/Admin/Developers/Index.php:135:        $this->dispatch('toast', type: 'success', message: __('Webhook deleted'));
app/Livewire/Storefront/Products/Show.php:85:        $this->dispatch('toast', type: 'success', message: __('Added to cart'));
app/Livewire/Admin/Customers/Show.php:102:        $this->dispatch('toast', type: 'success', message: __('Address saved'));
app/Livewire/Admin/Customers/Show.php:115:        $this->dispatch('toast', type: 'success', message: __('Address deleted'));
app/Livewire/Admin/Customers/Show.php:130:        $this->dispatch('toast', type: 'success', message: __('Default address updated'));
app/Livewire/Admin/Discounts/Form.php:136:        session()->flash('status', 'Discount saved');
app/Livewire/Admin/Discounts/Form.php:137:        $this->dispatch('toast', type: 'success', message: __('Discount saved'));
app/Livewire/Admin/Collections/Form.php:110:        $this->dispatch('toast', type: 'success', message: __('Collection saved'));
app/Livewire/Admin/Settings/Notifications.php:83:        $this->dispatch('toast', type: 'success', message: __('Notification settings saved'));
app/Livewire/Admin/Apps/Show.php:48:        $this->dispatch('toast', type: 'success', message: __('App uninstalled'));
app/Livewire/Admin/Collections/Index.php:33:        $this->dispatch('toast', type: 'success', message: __('Collection deleted'));
app/Livewire/Admin/Products/Form.php:235:        session()->flash('status', 'Product saved');
app/Livewire/Admin/Products/Form.php:236:        $this->dispatch('toast', type: 'success', message: __('Product saved'));
app/Livewire/Admin/Products/Form.php:254:        $this->dispatch('toast', type: 'success', message: __('Media uploaded'));
app/Livewire/Admin/Products/Form.php:352:        session()->flash('status', 'Product saved');
app/Livewire/Admin/Settings/Checkout.php:87:        $this->dispatch('toast', type: 'success', message: __('Checkout settings saved'));
app/Livewire/Admin/Apps/Index.php:38:        $this->dispatch('toast', type: 'success', message: __('App uninstalled'));
app/Livewire/Admin/Settings/Index.php:99:        $this->dispatch('toast', type: 'success', message: __('Settings saved'));
app/Livewire/Admin/Settings/Index.php:133:        $this->dispatch('toast', type: 'success', message: __('Domain added'));
app/Livewire/Admin/Products/Index.php:143:        $this->dispatch('toast', type: 'success', message: __('Products updated'));
app/Livewire/Admin/Settings/Shipping.php:115:        $this->dispatch('toast', type: 'success', message: __('Shipping zone saved'));
app/Livewire/Admin/Settings/Shipping.php:192:        $this->dispatch('toast', type: 'success', message: __('Shipping rate saved'));
app/Livewire/Admin/Settings/Taxes.php:100:        $this->dispatch('toast', type: 'success', message: __('Tax settings saved'));
app/Livewire/Admin/Orders/Show.php:68:            $this->dispatch('toast', type: 'success', message: __('Payment confirmed'));
app/Livewire/Admin/Orders/Show.php:96:            $this->dispatch('toast', type: 'success', message: __('Refund processed'));
app/Livewire/Admin/Orders/Show.php:136:            $this->dispatch('toast', type: 'success', message: __('Fulfillment created'));
app/Livewire/Admin/Orders/Show.php:148:            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as shipped'));
app/Livewire/Admin/Orders/Show.php:160:            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as delivered'));
app/Livewire/Admin/Search/Settings.php:82:        $this->dispatch('toast', type: 'success', message: __('Search settings saved'));
app/Livewire/Admin/Search/Settings.php:104:        $this->dispatch('toast', type: 'success', message: __('Search index rebuilt'));
app/Livewire/Admin/Pages/Form.php:104:        $this->dispatch('toast', type: 'success', message: __('Page saved'));
app/Livewire/Admin/Themes/Editor.php:89:        $this->dispatch('toast', type: 'success', message: __('Theme file saved'));
app/Livewire/Admin/Themes/Editor.php:107:        $this->dispatch('toast', type: 'success', message: __('Theme saved'));
app/Livewire/Admin/Themes/Index.php:59:        $this->dispatch('toast', type: 'success', message: __('Theme published'));
app/Livewire/Admin/Navigation/Index.php:232:        $this->dispatch('toast', type: 'success', message: __('Navigation saved'));


output:
Chunk ID: f96476
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1378
Output:
tests/Feature/Catalog/CatalogUiTest.php:95:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:106:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:135:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:144:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:189:        ->assertSee('Product saved');
tests/Feature/Catalog/CatalogUiTest.php:208:        ->assertSee('Product saved');
tests/Feature/Admin/ProductMediaManagementTest.php:88:        ->assertSee('Product saved');
tests/Browser/Admin/ProductManagementTest.php:89:        ->assertSee('Product saved')
app/Enums/WebhookEventType.php:35:            self::FulfillmentCreated => 'Fulfillment created',
app/Livewire/Admin/Developers/Index.php:70:        $this->dispatch('toast', type: 'success', message: __('API token generated'));
app/Livewire/Admin/Developers/Index.php:80:        $this->dispatch('toast', type: 'success', message: __('API token revoked'));
app/Livewire/Admin/Developers/Index.php:127:        $this->dispatch('toast', type: 'success', message: __('Webhook saved'));
app/Livewire/Admin/Developers/Index.php:135:        $this->dispatch('toast', type: 'success', message: __('Webhook deleted'));
app/Livewire/Storefront/Products/Show.php:85:        $this->dispatch('toast', type: 'success', message: __('Added to cart'));
app/Livewire/Admin/Customers/Show.php:102:        $this->dispatch('toast', type: 'success', message: __('Address saved'));
app/Livewire/Admin/Customers/Show.php:115:        $this->dispatch('toast', type: 'success', message: __('Address deleted'));
app/Livewire/Admin/Customers/Show.php:130:        $this->dispatch('toast', type: 'success', message: __('Default address updated'));
app/Livewire/Admin/Discounts/Form.php:136:        session()->flash('status', 'Discount saved');
app/Livewire/Admin/Discounts/Form.php:137:        $this->dispatch('toast', type: 'success', message: __('Discount saved'));
app/Livewire/Admin/Collections/Form.php:110:        $this->dispatch('toast', type: 'success', message: __('Collection saved'));
app/Livewire/Admin/Settings/Notifications.php:83:        $this->dispatch('toast', type: 'success', message: __('Notification settings saved'));
app/Livewire/Admin/Apps/Show.php:48:        $this->dispatch('toast', type: 'success', message: __('App uninstalled'));
app/Livewire/Admin/Collections/Index.php:33:        $this->dispatch('toast', type: 'success', message: __('Collection deleted'));
app/Livewire/Admin/Products/Form.php:235:        session()->flash('status', 'Product saved');
app/Livewire/Admin/Products/Form.php:236:        $this->dispatch('toast', type: 'success', message: __('Product saved'));
app/Livewire/Admin/Products/Form.php:254:        $this->dispatch('toast', type: 'success', message: __('Media uploaded'));
app/Livewire/Admin/Products/Form.php:352:        session()->flash('status', 'Product saved');
app/Livewire/Admin/Settings/Checkout.php:87:        $this->dispatch('toast', type: 'success', message: __('Checkout settings saved'));
app/Livewire/Admin/Apps/Index.php:38:        $this->dispatch('toast', type: 'success', message: __('App uninstalled'));
app/Livewire/Admin/Settings/Index.php:99:        $this->dispatch('toast', type: 'success', message: __('Settings saved'));
app/Livewire/Admin/Settings/Index.php:133:        $this->dispatch('toast', type: 'success', message: __('Domain added'));
app/Livewire/Admin/Products/Index.php:143:        $this->dispatch('toast', type: 'success', message: __('Products updated'));
app/Livewire/Admin/Settings/Shipping.php:115:        $this->dispatch('toast', type: 'success', message: __('Shipping zone saved'));
app/Livewire/Admin/Settings/Shipping.php:192:        $this->dispatch('toast', type: 'success', message: __('Shipping rate saved'));
app/Livewire/Admin/Settings/Taxes.php:100:        $this->dispatch('toast', type: 'success', message: __('Tax settings saved'));
app/Livewire/Admin/Orders/Show.php:68:            $this->dispatch('toast', type: 'success', message: __('Payment confirmed'));
app/Livewire/Admin/Orders/Show.php:96:            $this->dispatch('toast', type: 'success', message: __('Refund processed'));
app/Livewire/Admin/Orders/Show.php:136:            $this->dispatch('toast', type: 'success', message: __('Fulfillment created'));
app/Livewire/Admin/Orders/Show.php:148:            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as shipped'));
app/Livewire/Admin/Orders/Show.php:160:            $this->dispatch('toast', type: 'success', message: __('Fulfillment marked as delivered'));
app/Livewire/Admin/Search/Settings.php:82:        $this->dispatch('toast', type: 'success', message: __('Search settings saved'));
app/Livewire/Admin/Search/Settings.php:104:        $this->dispatch('toast', type: 'success', message: __('Search index rebuilt'));
app/Livewire/Admin/Pages/Form.php:104:        $this->dispatch('toast', type: 'success', message: __('Page saved'));
app/Livewire/Admin/Themes/Editor.php:89:        $this->dispatch('toast', type: 'success', message: __('Theme file saved'));
app/Livewire/Admin/Themes/Editor.php:107:        $this->dispatch('toast', type: 'success', message: __('Theme saved'));
app/Livewire/Admin/Themes/Index.php:59:        $this->dispatch('toast', type: 'success', message: __('Theme published'));
app/Livewire/Admin/Navigation/Index.php:232:        $this->dispatch('toast', type: 'success', message: __('Navigation saved'));


cmd: rg -n "assertNotPresent|assertPresent|assertVisible|assertButtonDisabled|assertButtonEnabled|assertDontSee" tests/Browser tests/Feature


command: rg -n "assertNotPresent|assertPresent|assertVisible|assertButtonDisabled|assertButtonEnabled|assertDontSee" tests/Browser tests/Feature

type: search

cmd: rg -n 'assertNotPresent|assertPresent|assertVisible|assertButtonDisabled|assertButtonEnabled|assertDontSee' tests/Browser tests/Feature

query: assertNotPresent|assertPresent|assertVisible|assertButtonDisabled|assertButtonEnabled|assertDontSee

path: Browser

aggregated_output:
tests/Browser/Admin/ProductManagementTest.php:182:        ->assertDontSee('Product To Archive')
tests/Browser/Admin/ProductManagementTest.php:192:        ->assertDontSee('Classic Cotton T-Shirt')
tests/Browser/Admin/ProductManagementTest.php:198:        ->assertDontSee('Unreleased Winter Jacket')
tests/Browser/Admin/ProductManagementTest.php:203:        ->assertDontSee('Unreleased Winter Jacket')
tests/Browser/Admin/ProductManagementTest.php:212:        ->assertDontSee('Premium Slim Fit Jeans')
tests/Browser/Admin/ProductManagementTest.php:221:        ->assertDontSee('Classic Cotton T-Shirt')
tests/Browser/Admin/ProductManagementTest.php:226:        ->assertDontSee('Unreleased Winter Jacket')
tests/Browser/Storefront/TenantIsolationTest.php:106:        ->assertDontSee('Pro Laptop 15')
tests/Browser/Storefront/TenantIsolationTest.php:107:        ->assertDontSee('Wireless Headphones')
tests/Browser/Storefront/TenantIsolationTest.php:115:        ->assertDontSee('Pro Laptop 15')
tests/Browser/Storefront/TenantIsolationTest.php:116:        ->assertDontSee('Wireless Headphones')
tests/Browser/Storefront/TenantIsolationTest.php:128:        ->assertDontSee('Pro Laptop 15')
tests/Browser/Storefront/TenantIsolationTest.php:129:        ->assertDontSee('Wireless Headphones')
tests/Browser/Storefront/TenantIsolationTest.php:134:        ->assertDontSee('#2001')
tests/Browser/Storefront/TenantIsolationTest.php:141:        ->assertDontSee('Pro Laptop 15')
tests/Browser/Storefront/TenantIsolationTest.php:145:        ->assertDontSee('Pro Laptop 15')
tests/Browser/Storefront/TenantIsolationTest.php:160:        ->assertDontSee('#2001')
tests/Browser/Storefront/BrowsingTest.php:76:        ->assertPresent('.line-through')
tests/Browser/Storefront/BrowsingTest.php:94:        ->assertDontSee('Unreleased Winter Jacket')
tests/Browser/Storefront/BrowsingTest.php:100:        ->assertDontSee('Unreleased Winter Jacket')
tests/Browser/Storefront/BrowsingTest.php:109:        ->assertButtonDisabled('button:has-text("Sold out")')
tests/Browser/Storefront/BrowsingTest.php:110:        ->assertDontSee('Add to cart')
tests/Browser/Storefront/BrowsingTest.php:119:        ->assertButtonEnabled('button:has-text("Add to cart")')
tests/Browser/Storefront/AccessibilityTest.php:81:        ->assertVisible('button:has-text("Add to cart")')
tests/Browser/Storefront/AccessibilityTest.php:82:        ->assertButtonEnabled('button:has-text("Add to cart")')
tests/Browser/Storefront/CheckoutTest.php:209:        ->assertButtonDisabled('main button:has-text("Checkout")')
tests/Browser/Storefront/InventoryTest.php:64:        ->assertButtonDisabled('button:has-text("Sold out")')
tests/Browser/Storefront/InventoryTest.php:65:        ->assertDontSee('Add to cart')
tests/Browser/Storefront/InventoryTest.php:85:        ->assertButtonEnabled('button:has-text("Add to cart")')
tests/Browser/Storefront/InventoryTest.php:86:        ->assertDontSee('Sold out')
tests/Browser/Storefront/InventoryTest.php:87:        ->assertDontSee('Available on backorder')
tests/Browser/Storefront/ResponsiveTest.php:89:        ->assertVisible('@mobile-menu-button')
tests/Browser/Storefront/ResponsiveTest.php:95:        ->assertVisible('nav[aria-label="Mobile navigation"]')
tests/Browser/Storefront/ResponsiveTest.php:105:        ->assertButtonEnabled('button:has-text("Add to cart")')
tests/Browser/Storefront/ResponsiveTest.php:137:        ->assertVisible('main button:has-text("Checkout")');
tests/Feature/Storefront/OrderViewsTest.php:180:        ->assertDontSee('#8888');
tests/Feature/Admin/CustomerManagementTest.php:77:        ->assertDontSee('Other Customer');
tests/Feature/Admin/CustomerManagementTest.php:105:        ->assertDontSee('Bravo Example')
tests/Feature/Admin/CustomerManagementTest.php:108:        ->assertDontSee('Jane Example');
tests/Feature/Admin/DashboardTest.php:86:        ->assertDontSee('Other Store Product');
tests/Feature/Admin/OrderManagementTest.php:115:        ->assertDontSee('#9001');
tests/Feature/Admin/OrderManagementTest.php:145:        ->assertDontSee('#7002')
tests/Feature/Admin/OrderManagementTest.php:149:        ->assertDontSee('#7001');
tests/Feature/Catalog/CatalogUiTest.php:35:        ->assertDontSee('Unreleased Winter Jacket');
tests/Feature/Catalog/CatalogUiTest.php:48:        ->assertDontSee('Unreleased Winter Jacket');
tests/Feature/Catalog/CatalogUiTest.php:152:        ->assertDontSee('Classic Cotton T-Shirt')
tests/Feature/Admin/ContentManagementTest.php:71:        ->assertDontSee('Other Store Page');
tests/Feature/Admin/ContentManagementTest.php:123:        ->assertDontSee('About');
tests/Feature/Admin/DiscountManagementTest.php:83:        ->assertDontSee('OTHER20');
tests/Feature/Admin/DiscountManagementTest.php:136:        ->assertDontSee('SOON10')
tests/Feature/Admin/DiscountManagementTest.php:140:        ->assertDontSee('ACTIVE10')
tests/Feature/Admin/DiscountManagementTest.php:141:        ->assertDontSee('DISABLEDSOON')
tests/Feature/Admin/DiscountManagementTest.php:144:        ->assertDontSee('DISABLEDENDED')
tests/Feature/Admin/DiscountManagementTest.php:147:        ->assertDontSee('ACTIVE10')
tests/Feature/Admin/DiscountManagementTest.php:148:        ->assertDontSee('SOON10');