ADD pest and livewire to laravel boost

This commit is contained in:
E98Developer 2026-03-30 13:56:13 +02:00
parent d7af667f80
commit 6fedf6a84f
6 changed files with 253 additions and 23 deletions

View File

@ -0,0 +1,115 @@
---
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, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, loading states, migrating from Livewire 2 to 3, 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 3 patterns and documentation.
## Basic Usage
### Creating Components
Use the `php artisan make:livewire [Posts\CreatePost]` Artisan command to create new components.
### Fundamental Concepts
- State should live on the server, with the UI reflecting it.
- All Livewire requests hit the Laravel backend; they're like regular HTTP requests. Always validate form data and run authorization checks in Livewire actions.
## Livewire 3 Specifics
### Key Changes From Livewire 2
These things changed in Livewire 3, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.
- Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default.
- Components now use the `App\Livewire` namespace (not `App\Http\Livewire`).
- Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`).
- Use the `components.layouts.app` view as the typical layout path (not `layouts.app`).
### New Directives
- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use.
### Alpine Integration
- Alpine is now included with Livewire; don't manually include Alpine.js.
- Plugins included with Alpine: persist, intersect, collapse, and focus.
## Best Practices
### Component Structure
- Livewire components require a single root element.
- Use `wire:loading` and `wire:dirty` for delightful loading states.
### Using Keys in Loops
<!-- Wire Key in Loops -->
```blade
@foreach ($items as $item)
<div wire:key="item-{{ $item->id }}">
{{ $item->name }}
</div>
@endforeach
```
### Lifecycle Hooks
Prefer lifecycle hooks like `mount()`, `updatedFoo()` for initialization and reactive side effects:
<!-- Lifecycle Hook Examples -->
```php
public function mount(User $user) { $this->user = $user; }
public function updatedSearch() { $this->resetPage(); }
```
## JavaScript Hooks
You can listen for `livewire:init` to hook into Livewire initialization:
<!-- Livewire Init Hook Example -->
```js
document.addEventListener('livewire:init', function () {
Livewire.hook('request', ({ fail }) => {
if (fail && fail.status === 419) {
alert('Your session expired');
}
});
Livewire.hook('message.failed', (message, component) => {
console.error(message);
});
});
```
## Testing
<!-- Example Livewire Component Test -->
```php
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1)
->assertSee(1)
->assertStatus(200);
```
<!-- Testing Livewire Component Exists on Page -->
```php
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
```
## Common Pitfalls
- Forgetting `wire:key` in loops causes unexpected behavior when items change
- Using `wire:model` expecting real-time updates (use `wire:model.live` instead in v3)
- Not validating/authorizing in Livewire actions (treat them like HTTP requests)
- Including Alpine.js separately when it's already bundled with Livewire 3

View File

@ -0,0 +1,108 @@
---
name: pest-testing
description: "Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit) or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for editing factories, seeders, migrations, controllers, models, or non-test PHP code."
license: MIT
metadata:
author: laravel
---
# Pest Testing 3
## Documentation
Use `search-docs` for detailed Pest 3 patterns and documentation.
## Basic Usage
### Creating Tests
All tests must be written using Pest. Use `php artisan make:test --pest {name}`.
### Test Organization
- Tests live in the `tests/Feature` and `tests/Unit` directories.
- Do NOT remove tests without approval - these are core application code.
- Test happy paths, failure paths, and edge cases.
### Basic Test Structure
<!-- Basic Pest Test Example -->
```php
it('is true', function () {
expect(true)->toBeTrue();
});
```
### Running Tests
- Run minimal tests with filter before finalizing: `php artisan test --compact --filter=testName`.
- Run all tests: `php artisan test --compact`.
- Run file: `php artisan test --compact tests/Feature/ExampleTest.php`.
## Assertions
Use specific assertions (`assertSuccessful()`, `assertNotFound()`) instead of `assertStatus()`:
<!-- Pest Response Assertion -->
```php
it('returns all', function () {
$this->postJson('/api/docs', [])->assertSuccessful();
});
```
| Use | Instead of |
|-----|------------|
| `assertSuccessful()` | `assertStatus(200)` |
| `assertNotFound()` | `assertStatus(404)` |
| `assertForbidden()` | `assertStatus(403)` |
## Mocking
Import mock function before use: `use function Pest\Laravel\mock;`
## Datasets
Use datasets for repetitive tests (validation rules, etc.):
<!-- Pest Dataset Example -->
```php
it('has emails', function (string $email) {
expect($email)->not->toBeEmpty();
})->with([
'james' => 'james@laravel.com',
'taylor' => 'taylor@laravel.com',
]);
```
## Pest 3 Features
### Architecture Testing
Pest 3 includes architecture testing to enforce code conventions:
<!-- Architecture Test Example -->
```php
arch('controllers')
->expect('App\Http\Controllers')
->toExtendNothing()
->toHaveSuffix('Controller');
arch('models')
->expect('App\Models')
->toExtend('Illuminate\Database\Eloquent\Model');
arch('no debugging')
->expect(['dd', 'dump', 'ray'])
->not->toBeUsed();
```
### Type Coverage
Pest 3 provides improved type coverage analysis. Run with `--type-coverage` flag.
## Common Pitfalls
- Not importing `use function Pest\Laravel\mock;` before using mock
- Using `assertStatus(200)` instead of `assertSuccessful()`
- Forgetting datasets for repetitive validation tests
- Deleting tests without approval

View File

@ -19,6 +19,7 @@ ## Foundational Context
- laravel/mcp (MCP) - v0 - laravel/mcp (MCP) - v0
- laravel/pail (PAIL) - v1 - laravel/pail (PAIL) - v1
- laravel/sail (SAIL) - v1 - laravel/sail (SAIL) - v1
- pestphp/pest (PEST) - v3
- phpunit/phpunit (PHPUNIT) - v11 - phpunit/phpunit (PHPUNIT) - v11
- tailwindcss (TAILWINDCSS) - v4 - tailwindcss (TAILWINDCSS) - v4
@ -27,6 +28,8 @@ ## Skills Activation
This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck. This project has domain-specific skills available. You MUST activate the relevant skill whenever you work in that domain—don't wait until you're stuck.
- `laravel-best-practices` — 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. - `laravel-best-practices` — 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.
- `livewire-development` — Use for any task or question involving Livewire. Activate if user mentions Livewire, wire: directives, or Livewire-specific concepts like wire:model, wire:click, invoke this skill. Covers building new components, debugging reactivity issues, real-time form validation, loading states, migrating from Livewire 2 to 3, 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.
- `pest-testing` — Use this skill for Pest PHP testing in Laravel projects only. Trigger whenever any test is being written, edited, fixed, or refactored — including fixing tests that broke after a code change, adding assertions, converting PHPUnit to Pest, adding datasets, and TDD workflows. Always activate when the user asks how to write something in Pest, mentions test files or directories (tests/Feature, tests/Unit) or architecture tests. Covers: it()/expect() syntax, datasets, mocking, browser testing, arch(), Livewire component tests, RefreshDatabase, and all Pest 4 features. Do not use for editing factories, seeders, migrations, controllers, models, or non-test PHP code.
- `tailwindcss-development` — Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS. - `tailwindcss-development` — Always invoke when the user's message includes 'tailwind' in any form. Also invoke for: building responsive grid layouts (multi-column card grids, product grids), flex/grid page structures (dashboards with sidebars, fixed topbars, mobile-toggle navs), styling UI components (cards, tables, navbars, pricing sections, forms, inputs, badges), adding dark mode variants, fixing spacing or typography, and Tailwind v3/v4 work. The core use case: writing or fixing Tailwind utility classes in HTML templates (Blade, JSX, Vue). Skip for backend PHP logic, database queries, API routes, JavaScript with no HTML/CSS component, CSS file audits, build tool configuration, and vanilla CSS.
## Conventions ## Conventions
@ -162,22 +165,20 @@ ### Models
- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models. - Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models.
=== phpunit/core rules === === livewire/core rules ===
# PHPUnit # Livewire
- This application uses PHPUnit for testing. All tests must be written as PHPUnit classes. Use `php artisan make:test --phpunit {name}` to create a new test. - Livewire allow to build dynamic, reactive interfaces in PHP without writing JavaScript.
- If you see a test using "Pest", convert it to PHPUnit. - You can use Alpine.js for client-side interactions instead of JavaScript frameworks.
- Every time a test has been updated, run that singular test. - Keep state server-side so the UI reflects it. Validate and authorize in actions as you would in HTTP requests.
- When the tests relating to your feature are passing, ask the user if they would like to also run the entire test suite to make sure everything is still passing.
- Tests should cover all happy paths, failure paths, and edge cases.
- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files; these are core to the application.
## Running Tests === pest/core rules ===
- Run the minimal number of tests, using an appropriate filter, before finalizing. ## Pest
- To run all tests: `php artisan test --compact`.
- To run all tests in a file: `php artisan test --compact tests/Feature/ExampleTest.php`. - This project uses Pest for testing. Create tests: `php artisan make:test --pest {name}`.
- To filter on a particular test name: `php artisan test --compact --filter=testName` (recommended after making a change to a related file). - Run tests: `php artisan test --compact` or filter: `php artisan test --compact --filter=testName`.
- Do NOT delete tests without approval.
</laravel-boost-guidelines> </laravel-boost-guidelines>

View File

@ -5,6 +5,8 @@
"guidelines": true, "guidelines": true,
"skills": [ "skills": [
"laravel-best-practices", "laravel-best-practices",
"livewire-development",
"pest-testing",
"tailwindcss-development" "tailwindcss-development"
] ]
} }

View File

@ -20,6 +20,7 @@
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"league/flysystem-aws-s3-v3": "^3.0", "league/flysystem-aws-s3-v3": "^3.0",
"livewire/livewire": "^3.7",
"maatwebsite/excel": "^3.1", "maatwebsite/excel": "^3.1",
"rap2hpoutre/fast-excel": "^5.6", "rap2hpoutre/fast-excel": "^5.6",
"santigarcor/laratrust": "^8.4", "santigarcor/laratrust": "^8.4",
@ -35,8 +36,8 @@
"laravel/sail": "^1.41", "laravel/sail": "^1.41",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6", "nunomaduro/collision": "^8.6",
"pestphp/pest": "*", "pestphp/pest": "^3.8",
"pestphp/pest-plugin-laravel": "*", "pestphp/pest-plugin-laravel": "^3.2",
"phpunit/phpunit": "^11.5.3", "phpunit/phpunit": "^11.5.3",
"spatie/laravel-ignition": "^2.9" "spatie/laravel-ignition": "^2.9"
}, },
@ -101,7 +102,10 @@
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,
"preferred-install": "dist", "preferred-install": "dist",
"sort-packages": true "sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
}, },
"minimum-stability": "stable", "minimum-stability": "stable",
"prefer-stable": true "prefer-stable": true

14
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "a697e341b64053fa6d0011f8fec1ee8b", "content-hash": "e0f1d8d7662b5a589c4fb33e4fb321a6",
"packages": [ "packages": [
{ {
"name": "ahmedhakeem/extra", "name": "ahmedhakeem/extra",
@ -6114,16 +6114,16 @@
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
"version": "v3.7.11", "version": "v3.7.12",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/livewire/livewire.git", "url": "https://github.com/livewire/livewire.git",
"reference": "addd6e8e9234df75f29e6a327ee2a745a7d67bb6" "reference": "7fcb612d1274980d80703efb5658e58d6d37ada9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/addd6e8e9234df75f29e6a327ee2a745a7d67bb6", "url": "https://api.github.com/repos/livewire/livewire/zipball/7fcb612d1274980d80703efb5658e58d6d37ada9",
"reference": "addd6e8e9234df75f29e6a327ee2a745a7d67bb6", "reference": "7fcb612d1274980d80703efb5658e58d6d37ada9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6178,7 +6178,7 @@
"description": "A front-end framework for Laravel.", "description": "A front-end framework for Laravel.",
"support": { "support": {
"issues": "https://github.com/livewire/livewire/issues", "issues": "https://github.com/livewire/livewire/issues",
"source": "https://github.com/livewire/livewire/tree/v3.7.11" "source": "https://github.com/livewire/livewire/tree/v3.7.12"
}, },
"funding": [ "funding": [
{ {
@ -6186,7 +6186,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2026-02-26T00:58:19+00:00" "time": "2026-03-25T23:04:42+00:00"
}, },
{ {
"name": "maatwebsite/excel", "name": "maatwebsite/excel",