diff --git a/docs/10-testing/02-testing-resources.md b/docs/10-testing/02-testing-resources.md index 001d7ff1d9..0271bd0e92 100644 --- a/docs/10-testing/02-testing-resources.md +++ b/docs/10-testing/02-testing-resources.md @@ -1,10 +1,10 @@ --- -title: Testing +title: Testing resources --- ## Introduction -All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit. +All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit, mostly by switching out the `livewire()` function from Pest with the `Livewire::test()` method. Since all pages in the app are Livewire components, we're just using Livewire testing helpers everywhere. If you've never tested Livewire components before, please read [this guide](https://livewire.laravel.com/docs/testing) from the Livewire docs. diff --git a/docs/10-testing/03-testing-tables.md b/docs/10-testing/03-testing-tables.md index 615b35b504..9d2913310b 100644 --- a/docs/10-testing/03-testing-tables.md +++ b/docs/10-testing/03-testing-tables.md @@ -4,7 +4,7 @@ title: Testing tables ## Introduction -All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit. +All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit, mostly by switching out the `livewire()` function from Pest with the `Livewire::test()` method. Since the Table Builder works on Livewire components, you can use the [Livewire testing helpers](https://livewire.laravel.com/docs/testing). However, we have many custom testing helpers that you can use for tables: @@ -175,7 +175,7 @@ it('has an author column', function () { }); ``` -You may pass a function as an additional argument in order to assert that a column passes a given "truth test". This is useful for asserting that a column has a specific configuration. You can also pass in a record as the third parameter, which is useful if your check is dependant on which table row is being rendered: +You may pass a function as an additional argument to assert that a column passes a given "truth test". This is useful for asserting that a column has a specific configuration. You can also pass in a record as the third parameter, which is useful if your check is dependant on which table row is being rendered: ```php use function Pest\Livewire\livewire; @@ -375,7 +375,7 @@ it('has an author filter', function () { }); ``` -You may pass a function as an additional argument in order to assert that a filter passes a given "truth test". This is useful for asserting that a filter has a specific configuration: +You may pass a function as an additional argument to assert that a filter passes a given "truth test". This is useful for asserting that a filter has a specific configuration: ```php use function Pest\Livewire\livewire; @@ -389,299 +389,6 @@ it('has an author filter', function () { }); ``` -## Actions - -### Calling actions - -You can call an action by passing its name or class to `callTableAction()`: - -```php -use function Pest\Livewire\livewire; - -it('can delete posts', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableAction(DeleteAction::class, $post); - - $this->assertModelMissing($post); -}); -``` - -This example assumes that you have a `DeleteAction` on your table. If you have a custom `Action::make('reorder')`, you may use `callTableAction('reorder')`. - -For column actions, you may do the same, using `callTableColumnAction()`: - -```php -use function Pest\Livewire\livewire; - -it('can copy posts', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableColumnAction('copy', $post); - - $this->assertDatabaseCount((new Post)->getTable(), 2); -}); -``` - -For bulk actions, you may do the same, passing in multiple records to execute the bulk action against with `callTableBulkAction()`: - -```php -use function Pest\Livewire\livewire; - -it('can bulk delete posts', function () { - $posts = Post::factory()->count(10)->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableBulkAction(DeleteBulkAction::class, $posts); - - foreach ($posts as $post) { - $this->assertModelMissing($post); - } -}); -``` - -To pass an array of data into an action, use the `data` parameter: - -```php -use function Pest\Livewire\livewire; - -it('can edit posts', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableAction(EditAction::class, $post, data: [ - 'title' => $title = fake()->words(asText: true), - ]) - ->assertHasNoTableActionErrors(); - - expect($post->refresh()) - ->title->toBe($title); -}); -``` - -### Execution - -To check if an action or bulk action has been halted, you can use `assertTableActionHalted()` / `assertTableBulkActionHalted()`: - -```php -use function Pest\Livewire\livewire; - -it('will halt delete if post is flagged', function () { - $posts= Post::factory()->count(2)->flagged()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableAction('delete', $posts->first()) - ->callTableBulkAction('delete', $posts) - ->assertTableActionHalted('delete') - ->assertTableBulkActionHalted('delete'); - - $this->assertModelExists($post); -}); -``` - -### Errors - -`assertHasNoTableActionErrors()` is used to assert that no validation errors occurred when submitting the action form. - -To check if a validation error has occurred with the data, use `assertHasTableActionErrors()`, similar to `assertHasErrors()` in Livewire: - -```php -use function Pest\Livewire\livewire; - -it('can validate edited post data', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->callTableAction(EditAction::class, $post, data: [ - 'title' => null, - ]) - ->assertHasTableActionErrors(['title' => ['required']]); -}); -``` - -For bulk actions these methods are called `assertHasTableBulkActionErrors()` and `assertHasNoTableBulkActionErrors()`. - -### Pre-filled data - -To check if an action or bulk action is pre-filled with data, you can use the `assertTableActionDataSet()` or `assertTableBulkActionDataSet()` method: - -```php -use function Pest\Livewire\livewire; - -it('can load existing post data for editing', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->mountTableAction(EditAction::class, $post) - ->assertTableActionDataSet([ - 'title' => $post->title, - ]) - ->setTableActionData([ - 'title' => $title = fake()->words(asText: true), - ]) - ->callMountedTableAction() - ->assertHasNoTableActionErrors(); - - expect($post->refresh()) - ->title->toBe($title); -}); -``` - -You may also find it useful to pass a function to the `assertTableActionDataSet()` and `assertTableBulkActionDataSet()` methods, which allow you to access the form `$state` and perform additional assertions: - -```php -use Illuminate\Support\Str; -use function Pest\Livewire\livewire; - -it('can automatically generate a slug from the title without any spaces', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->mountTableAction(EditAction::class, $post) - ->assertTableActionDataSet(function (array $state) use ($post): array { - expect($state['slug']) - ->not->toContain(' '); - - return [ - 'slug' => Str::slug($post->title), - ]; - }); -}); -``` - -### Action state - -To ensure that an action or bulk action exists or doesn't in a table, you can use the `assertTableActionExists()` / `assertTableActionDoesNotExist()` or `assertTableBulkActionExists()` / `assertTableBulkActionDoesNotExist()` method: - -```php -use function Pest\Livewire\livewire; - -it('can publish but not unpublish posts', function () { - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionExists('publish') - ->assertTableActionDoesNotExist('unpublish') - ->assertTableBulkActionExists('publish') - ->assertTableBulkActionDoesNotExist('unpublish'); -}); -``` - -To ensure different sets of actions exist in the correct order, you can use the various "InOrder" assertions - -```php -use function Pest\Livewire\livewire; - -it('has all actions in expected order', function () { - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionsExistInOrder(['edit', 'delete']) - ->assertTableBulkActionsExistInOrder(['restore', 'forceDelete']) - ->assertTableHeaderActionsExistInOrder(['create', 'attach']) - ->assertTableEmptyStateActionsExistInOrder(['create', 'toggle-trashed-filter']) -}); -``` - -To ensure that an action or bulk action is enabled or disabled for a user, you can use the `assertTableActionEnabled()` / `assertTableActionDisabled()` or `assertTableBulkActionEnabled()` / `assertTableBulkActionDisabled()` methods: - -```php -use function Pest\Livewire\livewire; - -it('can not publish, but can delete posts', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionDisabled('publish', $post) - ->assertTableActionEnabled('delete', $post) - ->assertTableBulkActionDisabled('publish') - ->assertTableBulkActionEnabled('delete'); -}); -``` - - -To ensure that an action or bulk action is visible or hidden for a user, you can use the `assertTableActionVisible()` / `assertTableActionHidden()` or `assertTableBulkActionVisible()` / `assertTableBulkActionHidden()` methods: - -```php -use function Pest\Livewire\livewire; - -it('can not publish, but can delete posts', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionHidden('publish', $post) - ->assertTableActionVisible('delete', $post) - ->assertTableBulkActionHidden('publish') - ->assertTableBulkActionVisible('delete'); -}); -``` - -### Button Style - -To ensure an action or bulk action has the correct label, you can use `assertTableActionHasLabel()` / `assertTableBulkActionHasLabel()` and `assertTableActionDoesNotHaveLabel()` / `assertTableBulkActionDoesNotHaveLabel()`: - -```php -use function Pest\Livewire\livewire; - -it('delete actions have correct labels', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionHasLabel('delete', 'Archive Post') - ->assertTableActionDoesNotHaveLabel('delete', 'Delete'); - ->assertTableBulkActionHasLabel('delete', 'Archive Post') - ->assertTableBulkActionDoesNotHaveLabel('delete', 'Delete'); -}); -``` - -To ensure an action or bulk action's button is showing the correct icon, you can use `assertTableActionHasIcon()` / `assertTableBulkActionHasIcon()` or `assertTableActionDoesNotHaveIcon()` / `assertTableBulkActionDoesNotHaveIcon()`: - -```php -use function Pest\Livewire\livewire; - -it('delete actions have correct icons', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionHasIcon('delete', 'heroicon-m-archive-box') - ->assertTableActionDoesNotHaveIcon('delete', 'heroicon-m-trash'); - ->assertTableBulkActionHasIcon('delete', 'heroicon-m-archive-box') - ->assertTableBulkActionDoesNotHaveIcon('delete', 'heroicon-m-trash'); -}); -``` - -To ensure that an action or bulk action's button is displaying the right color, you can use `assertTableActionHasColor()` / `assertTableBulkActionHasColor()` or `assertTableActionDoesNotHaveColor()` / `assertTableBulkActionDoesNotHaveColor()`: - -```php -use function Pest\Livewire\livewire; - -it('delete actions have correct colors', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionHasColor('delete', 'warning') - ->assertTableActionDoesNotHaveColor('delete', 'danger'); - ->assertTableBulkActionHasColor('delete', 'warning') - ->assertTableBulkActionDoesNotHaveColor('delete', 'danger'); -}); -``` - -### URL - -To ensure an action or bulk action has the correct URL traits, you can use `assertTableActionHasUrl()`, `assertTableActionDoesNotHaveUrl()`, `assertTableActionShouldOpenUrlInNewTab()`, and `assertTableActionShouldNotOpenUrlInNewTab()`: - -```php -use function Pest\Livewire\livewire; - -it('links to the correct Filament sites', function () { - $post = Post::factory()->create(); - - livewire(PostResource\Pages\ListPosts::class) - ->assertTableActionHasUrl('filament', 'https://filamentphp.com/') - ->assertTableActionDoesNotHaveUrl('filament', 'https://github.com/filamentphp/filament') - ->assertTableActionShouldOpenUrlInNewTab('filament') - ->assertTableActionShouldNotOpenUrlInNewTab('github'); -}); -``` - ## Summaries To test that a summary calculation is working, you may use the `assertTableColumnSummarySet()` method: diff --git a/docs/10-testing/04-testing-schemas.md b/docs/10-testing/04-testing-forms.md similarity index 53% rename from docs/10-testing/04-testing-schemas.md rename to docs/10-testing/04-testing-forms.md index 46c3a835a6..69ce7028e9 100644 --- a/docs/10-testing/04-testing-schemas.md +++ b/docs/10-testing/04-testing-forms.md @@ -1,10 +1,10 @@ --- -title: Testing schemas +title: Testing forms --- ## Introduction -All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit. +All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit, mostly by switching out the `livewire()` function from Pest with the `Livewire::test()` method. Since the Form Builder works on Livewire components, you can use the [Livewire testing helpers](https://livewire.laravel.com/docs/testing). However, we have custom testing helpers that you can use with forms: @@ -132,7 +132,7 @@ it('has a title field', function () { }); ``` -You may pass a function as an additional argument in order to assert that a field passes a given "truth test". This is useful for asserting that a field has a specific configuration: +You may pass a function as an additional argument to assert that a field passes a given "truth test". This is useful for asserting that a field has a specific configuration: ```php use function Pest\Livewire\livewire; @@ -335,264 +335,3 @@ it('moves to next wizard step only for fooForm', function () { ->assertHasFormErrors(['title'], formName: 'fooForm'); }); ``` - -## Actions - -You can call an action by passing its form component name, and then the name of the action to `callFormComponentAction()`: - -```php -use function Pest\Livewire\livewire; - -it('can send invoices', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->callFormComponentAction('customer_id', 'send'); - - expect($invoice->refresh()) - ->isSent()->toBeTrue(); -}); -``` - -To pass an array of data into an action, use the `data` parameter: - -```php -use function Pest\Livewire\livewire; - -it('can send invoices', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->callFormComponentAction('customer_id', 'send', data: [ - 'email' => $email = fake()->email(), - ]) - ->assertHasNoFormComponentActionErrors(); - - expect($invoice->refresh()) - ->isSent()->toBeTrue() - ->recipient_email->toBe($email); -}); -``` - -If you ever need to only set an action's data without immediately calling it, you can use `setFormComponentActionData()`: - -```php -use function Pest\Livewire\livewire; - -it('can send invoices', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->mountAction('customer_id', 'send') - ->setFormComponentActionData([ - 'email' => $email = fake()->email(), - ]) -}); -``` - -### Execution - -To check if an action has been halted, you can use `assertFormComponentActionHalted()`: - -```php -use function Pest\Livewire\livewire; - -it('stops sending if invoice has no email address', function () { - $invoice = Invoice::factory(['email' => null])->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->callFormComponentAction('customer_id', 'send') - ->assertFormComponentActionHalted('customer_id', 'send'); -}); -``` - -### Errors - -`assertHasNoFormComponentActionErrors()` is used to assert that no validation errors occurred when submitting the action form. - -To check if a validation error has occurred with the data, use `assertHasFormComponentActionErrors()`, similar to `assertHasErrors()` in Livewire: - -```php -use function Pest\Livewire\livewire; - -it('can validate invoice recipient email', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->callFormComponentAction('customer_id', 'send', data: [ - 'email' => Str::random(), - ]) - ->assertHasFormComponentActionErrors(['email' => ['email']]); -}); -``` - -To check if an action is pre-filled with data, you can use the `assertFormComponentActionDataSet()` method: - -```php -use function Pest\Livewire\livewire; - -it('can send invoices to the primary contact by default', function () { - $invoice = Invoice::factory()->create(); - $recipientEmail = $invoice->company->primaryContact->email; - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->mountAction('customer_id', 'send') - ->assertFormComponentActionDataSet([ - 'email' => $recipientEmail, - ]) - ->callMountedAction() - ->assertHasNoFormComponentActionErrors(); - - expect($invoice->refresh()) - ->isSent()->toBeTrue() - ->recipient_email->toBe($recipientEmail); -}); -``` - -### Action state - -To ensure that an action exists or doesn't in a form, you can use the `assertFormComponentActionExists()` or `assertFormComponentActionDoesNotExist()` method: - -```php -use function Pest\Livewire\livewire; - -it('can send but not unsend invoices', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionExists('customer_id', 'send') - ->assertFormComponentActionDoesNotExist('customer_id', 'unsend'); -}); -``` - -To ensure an action is hidden or visible for a user, you can use the `assertFormComponentActionHidden()` or `assertFormComponentActionVisible()` methods: - -```php -use function Pest\Livewire\livewire; - -it('can only print customers', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionHidden('customer_id', 'send') - ->assertFormComponentActionVisible('customer_id', 'print'); -}); -``` - -To ensure an action is enabled or disabled for a user, you can use the `assertFormComponentActionEnabled()` or `assertFormComponentActionDisabled()` methods: - -```php -use function Pest\Livewire\livewire; - -it('can only print a customer for a sent invoice', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionDisabled('customer_id', 'send') - ->assertFormComponentActionEnabled('customer_id', 'print'); -}); -``` - -To check if an action is hidden to a user, you can use the `assertFormComponentActionHidden()` method: - -```php -use function Pest\Livewire\livewire; - -it('can not send invoices', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionHidden('customer_id', 'send'); -}); -``` - -### Button appearance - -To ensure an action has the correct label, you can use `assertFormComponentActionHasLabel()` and `assertFormComponentActionDoesNotHaveLabel()`: - -```php -use function Pest\Livewire\livewire; - -it('send action has correct label', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionHasLabel('customer_id', 'send', 'Email Invoice') - ->assertFormComponentActionDoesNotHaveLabel('customer_id', 'send', 'Send'); -}); -``` - -To ensure an action's button is showing the correct icon, you can use `assertFormComponentActionHasIcon()` or `assertFormComponentActionDoesNotHaveIcon()`: - -```php -use function Pest\Livewire\livewire; - -it('when enabled the send button has correct icon', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionEnabled('customer_id', 'send') - ->assertFormComponentActionHasIcon('customer_id', 'send', 'envelope-open') - ->assertFormComponentActionDoesNotHaveIcon('customer_id', 'send', 'envelope'); -}); -``` - -To ensure that an action's button is displaying the right color, you can use `assertFormComponentActionHasColor()` or `assertFormComponentActionDoesNotHaveColor()`: - -```php -use function Pest\Livewire\livewire; - -it('actions display proper colors', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionHasColor('customer_id', 'delete', 'danger') - ->assertFormComponentActionDoesNotHaveColor('customer_id', 'print', 'danger'); -}); -``` - -### URL - -To ensure an action has the correct URL, you can use `assertFormComponentActionHasUrl()`, `assertFormComponentActionDoesNotHaveUrl()`, `assertFormComponentActionShouldOpenUrlInNewTab()`, and `assertFormComponentActionShouldNotOpenUrlInNewTab()`: - -```php -use function Pest\Livewire\livewire; - -it('links to the correct Filament sites', function () { - $invoice = Invoice::factory()->create(); - - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->assertFormComponentActionHasUrl('customer_id', 'filament', 'https://filamentphp.com/') - ->assertFormComponentActionDoesNotHaveUrl('customer_id', 'filament', 'https://github.com/filamentphp/filament') - ->assertFormComponentActionShouldOpenUrlInNewTab('customer_id', 'filament') - ->assertFormComponentActionShouldNotOpenUrlInNewTab('customer_id', 'github'); -}); -``` diff --git a/docs/10-testing/05-testing-actions.md b/docs/10-testing/05-testing-actions.md index 797c930e04..655ec115e0 100644 --- a/docs/10-testing/05-testing-actions.md +++ b/docs/10-testing/05-testing-actions.md @@ -4,7 +4,7 @@ title: Testing actions ## Introduction -All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit. +All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit, mostly by switching out the `livewire()` function from Pest with the `Livewire::test()` method. Since all actions are mounted to a Livewire component, we're just using Livewire testing helpers everywhere. If you've never tested Livewire components before, please read [this guide](https://livewire.laravel.com/docs/testing) from the Livewire docs. @@ -170,6 +170,26 @@ it('can send but not unsend invoices', function () { }); ``` +You may pass a function as an additional argument to assert that an action passes a given "truth test". This is useful for asserting that an action has a specific configuration: + +```php +use Filament\Actions\Action; +use function Pest\Livewire\livewire; + +it('has the correct description', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->assertActionExists('send', function (Action $action): bool { + return $action->getModalDescription() === 'This will send an email to the customer\'s primary address, with the invoice attached as a PDF'; + }); +}); +``` + +### Hidden actions + To ensure an action is hidden or visible for a user, you can use the `assertActionHidden()` or `assertActionVisible()` methods: ```php @@ -186,6 +206,8 @@ it('can only print invoices', function () { }); ``` +### Disabled actions + To ensure an action is enabled or disabled for a user, you can use the `assertActionEnabled()` or `assertActionDisabled()` methods: ```php @@ -302,3 +324,150 @@ it('links to the correct Filament sites', function () { ->assertActionShouldNotOpenUrlInNewTab('github'); }); ``` + +## Testing table actions + +To test table actions, you can use a `TestAction` object with the `table()` method. This object receives the name of the action you want to test, and replaces the name of the action in any testing method you want to use. For example: + +```php +use Filament\Actions\Testing\TestAction;use function Pest\Livewire\livewire; + +$invoice = Invoice::factory()->create(); + +livewire(ListInvoices::class) + ->callAction(TestAction::make('send')->table($invoice)); + +livewire(ListInvoices::class) + ->assertActionVisible(TestAction::make('send')->table($invoice)) + +livewire(ListInvoices::class) + ->assertActionExists(TestAction::make('send')->table($invoice)) +``` + +### Testing table header actions + +To test a header action, you can use the `table()` method without passing in a specific record to test with: + +```php +use Filament\Actions\Testing\TestAction;use function Pest\Livewire\livewire; + +livewire(ListInvoices::class) + ->callAction(TestAction::make('create')->table()); + +livewire(ListInvoices::class) + ->assertActionVisible(TestAction::make('create')->table()) + +livewire(ListInvoices::class) + ->assertActionExists(TestAction::make('create')->table()) +``` + +### Testing table bulk actions + +To test a bulk action, first call `selectTableRecords()` and pass in any records you want to select. Then, use the `TestAction`'s `bulk()` method to specify the action you want to test. For example: + +```php +use Filament\Actions\Testing\TestAction;use function Pest\Livewire\livewire; + +$invoices = Invoice::factory()->count(3)->create(); + +livewire(ListInvoices::class) + ->selectTableRecords($invoices->pluck('id')->toArray()) + ->callAction(TestAction::make('send')->table()->bulk()); + +livewire(ListInvoices::class) + ->assertActionVisible(TestAction::make('send')->table()->bulk()) + +livewire(ListInvoices::class) + ->assertActionExists(TestAction::make('send')->table()->bulk()) +``` + +## Testing resource form component actions + +If an action belongs to a component in a resource's form, for example, if it is in the `belowContent()` method of a form field, you can use the `TestAction` object with the `schemaComponent()` method. This object receives the name of the action you want to test and replaces the name of the action in any testing method you want to use. The `schemaComponent()` method should receive a `TestSchemaComponent::inResourceForm()` object, which accepts the name of the form component you want to test. For example: + +```php +use Filament\Actions\Testing\TestAction; +use Filament\Schemas\Testing\TestSchemaComponent; +use function Pest\Livewire\livewire; + +$invoice = Invoice::factory()->create(); + +livewire(EditInvoice::class) + ->callAction(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceForm('customer_id'))); + +livewire(EditInvoice::class) + ->assertActionVisible(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceForm('customer_id'))) + +livewire(EditInvoice::class) + ->assertActionExists(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceForm('customer_id'))) +``` + +## Testing resource infolist component actions + +If an action belongs to a component in a resource's infolist, for example, if it is in the `belowContent()` method of an infolist entry, you can use the `TestAction` object with the `schemaComponent()` method. This object receives the name of the action you want to test and replaces the name of the action in any testing method you want to use. The `schemaComponent()` method should receive a `TestSchemaComponent::inResourceInfolist()` object, which accepts the name of the infolist component you want to test. For example: + +```php +use Filament\Actions\Testing\TestAction; +use Filament\Schemas\Testing\TestSchemaComponent; +use function Pest\Livewire\livewire; + +$invoice = Invoice::factory()->create(); + +livewire(ViewInvoice::class) + ->callAction(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceInfolist('customer.name'))); + +livewire(ViewInvoice::class) + ->assertActionVisible(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceInfolist('customer.name'))) + +livewire(ViewInvoice::class) + ->assertActionExists(TestAction::make('send')->schemaComponent(TestSchemaComponent::inResourceInfolist('customer.name'))) +``` + +## Testing actions inside another action's schema / form + +If an action belongs to a component in another action's `schema()` (or `form()`), for example, if it is in the `belowContent()` method of a form field in an action modal, you can use the `TestAction` object with the `schemaComponent()` method. This object receives the name of the action you want to test and replaces the name of the action in any testing method you want to use. The `schemaComponent()` method should receive a `TestSchemaComponent::inActionSchema()` object, which accepts the name of the action component you want to test. You should pass an array of `TestAction` objects in order, for example: + +```php +use Filament\Actions\Testing\TestAction; +use Filament\Schemas\Testing\TestSchemaComponent; +use function Pest\Livewire\livewire; + +$invoice = Invoice::factory()->create(); + +livewire(ManageInvoices::class) + ->callAction([ + TestAction::make('view')->table($invoice), + TestAction::make('send')->schemaComponent(TestSchemaComponent::inActionSchema('customer.name')), + ]); + +livewire(ManageInvoices::class) + ->assertActionVisible([ + TestAction::make('view')->table($invoice), + TestAction::make('send')->schemaComponent(TestSchemaComponent::inActionSchema('customer.name')), + ]); + +livewire(ManageInvoices::class) + ->assertActionExists([ + TestAction::make('view')->table($invoice), + TestAction::make('send')->schemaComponent(TestSchemaComponent::inActionSchema('customer.name')), + ]); +``` + +## Testing action arguments + +To test action arguments, you can use a `TestAction` object with the `arguments()` method. This object receives the name of the action you want to test and replaces the name of the action in any testing method you want to use. For example: + +```php +use Filament\Actions\Testing\TestAction;use function Pest\Livewire\livewire; + +$invoice = Invoice::factory()->create(); + +livewire(ManageInvoices::class) + ->callAction(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])); + +livewire(ManageInvoices::class) + ->assertActionVisible(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])) + +livewire(ManageInvoices::class) + ->assertActionExists(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])) +``` diff --git a/docs/10-testing/06-testing-notifications.md b/docs/10-testing/06-testing-notifications.md index a0eb66d8cc..a9959697a2 100644 --- a/docs/10-testing/06-testing-notifications.md +++ b/docs/10-testing/06-testing-notifications.md @@ -4,7 +4,7 @@ title: Testing notifications ## Introduction -All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit. +All examples in this guide will be written using [Pest](https://pestphp.com). To use Pest's Livewire plugin for testing, you can follow the installation instructions in the Pest documentation on plugins: [Livewire plugin for Pest](https://pestphp.com/docs/plugins#livewire). However, you can easily adapt this to PHPUnit, mostly by switching out the `livewire()` function from Pest with the `Livewire::test()` method. ## Testing session notifications diff --git a/packages/actions/.stubs.php b/packages/actions/.stubs.php index 7284d728de..8e1e165978 100644 --- a/packages/actions/.stubs.php +++ b/packages/actions/.stubs.php @@ -4,7 +4,7 @@ namespace Livewire\Features\SupportTesting { use BackedEnum; use Closure; - use Filament\Actions\Testing\Fixtures\TestAction; + use Filament\Actions\Testing\TestAction; class Testable { public function mountAction(string | TestAction | array $actions, array $arguments = []): static {} diff --git a/packages/actions/src/Testing/Fixtures/TestAction.php b/packages/actions/src/Testing/TestAction.php similarity index 83% rename from packages/actions/src/Testing/Fixtures/TestAction.php rename to packages/actions/src/Testing/TestAction.php index 543b8dcfe7..d1792c6155 100644 --- a/packages/actions/src/Testing/Fixtures/TestAction.php +++ b/packages/actions/src/Testing/TestAction.php @@ -1,9 +1,11 @@ table; + if ($this->table instanceof Model) { + $array['context']['recordKey'] = $this->table->getKey(); + } elseif (is_array($this->table)) { + $array['context']['recordKey'] = $this->table[ArrayRecord::getKeyName()] ?? null; + } else { + $array['context']['recordKey'] = $this->table; + } return $array; } diff --git a/packages/actions/src/Testing/TestsActions.php b/packages/actions/src/Testing/TestsActions.php index bab38b2c4f..58751e6750 100644 --- a/packages/actions/src/Testing/TestsActions.php +++ b/packages/actions/src/Testing/TestsActions.php @@ -9,7 +9,6 @@ use Filament\Actions\Action; use Filament\Actions\ActionGroup; use Filament\Actions\Contracts\HasActions; use Filament\Actions\Exceptions\ActionNotResolvableException; -use Filament\Actions\Testing\Fixtures\TestAction; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Testing\Assert; diff --git a/packages/forms/src/Testing/TestsForms.php b/packages/forms/src/Testing/TestsForms.php index 756e56c5c8..2a9946697e 100644 --- a/packages/forms/src/Testing/TestsForms.php +++ b/packages/forms/src/Testing/TestsForms.php @@ -25,14 +25,14 @@ class TestsForms { public function fillForm(): Closure { - return function (array | Closure $state = [], string $formName = 'form'): static { + return function (array | Closure $state = [], string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); $livewire = $this->instance(); /** @var Schema $form */ - $form = $livewire->{$formName}; + $form = $livewire->{$schemaName}; $formStatePath = $form->getStatePath(); @@ -67,14 +67,14 @@ class TestsForms public function assertFormSet(): Closure { - return function (array | Closure $state, string $formName = 'form'): static { + return function (array | Closure $state, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); $livewire = $this->instance(); /** @var Schema $form */ - $form = $livewire->{$formName}; + $form = $livewire->{$schemaName}; $formStatePath = $form->getStatePath(); @@ -94,14 +94,14 @@ class TestsForms public function assertHasFormErrors(): Closure { - return function (array $keys = [], string $formName = 'form'): static { + return function (array $keys = [], string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); $livewire = $this->instance(); /** @var Schema $form */ - $form = $livewire->{$formName}; + $form = $livewire->{$schemaName}; $formStatePath = $form->getStatePath(); @@ -123,14 +123,14 @@ class TestsForms public function assertHasNoFormErrors(): Closure { - return function (array $keys = [], string $formName = 'form'): static { + return function (array $keys = [], string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); $livewire = $this->instance(); /** @var Schema $form */ - $form = $livewire->{$formName}; + $form = $livewire->{$schemaName}; $formStatePath = $form->getStatePath(); @@ -170,17 +170,17 @@ class TestsForms public function assertFormComponentExists(): Closure { - return function (string $componentKey, string | Closure $formName = 'form', ?Closure $checkComponentUsing = null): static { - if ($formName instanceof Closure) { - $checkComponentUsing = $formName; - $formName = 'form'; + return function (string $componentKey, string | Closure $schemaName = 'form', ?Closure $checkComponentUsing = null): static { + if ($schemaName instanceof Closure) { + $checkComponentUsing = $schemaName; + $schemaName = 'form'; } /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Component | Action | null $component */ $component = $form->getFlatComponents(withHidden: true)[$componentKey] ?? null; @@ -190,13 +190,13 @@ class TestsForms Assert::assertInstanceOf( Component::class, $component, - "Failed asserting that a component with the key [{$componentKey}] exists on the form with the name [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a component with the key [{$componentKey}] exists on the form with the name [{$schemaName}] on the [{$livewireClass}] component." ); if ($checkComponentUsing) { Assert::assertTrue( $checkComponentUsing($component), - "Failed asserting that a component with the key [{$componentKey}] and provided configuration exists on the form with the name [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a component with the key [{$componentKey}] and provided configuration exists on the form with the name [{$schemaName}] on the [{$livewireClass}] component." ); } @@ -206,9 +206,9 @@ class TestsForms public function assertFormComponentDoesNotExist(): Closure { - return function (string $componentKey, string $formName = 'form'): static { + return function (string $componentKey, string $schemaName = 'form'): static { /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; $components = $form->getFlatComponents(withHidden: true); @@ -217,7 +217,7 @@ class TestsForms Assert::assertArrayNotHasKey( $componentKey, $components, - "Failed asserting that a component with the key [{$componentKey}] does not exist on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a component with the key [{$componentKey}] does not exist on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return $this; @@ -226,17 +226,17 @@ class TestsForms public function assertFormFieldExists(): Closure { - return function (string $fieldName, string | Closure $formName = 'form', ?Closure $checkFieldUsing = null): static { - if ($formName instanceof Closure) { - $checkFieldUsing = $formName; - $formName = 'form'; + return function (string $fieldName, string | Closure $schemaName = 'form', ?Closure $checkFieldUsing = null): static { + if ($schemaName instanceof Closure) { + $checkFieldUsing = $schemaName; + $schemaName = 'form'; } /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var ?Field $field */ $field = $form->getFlatFields(withHidden: true)[$fieldName] ?? null; @@ -246,13 +246,13 @@ class TestsForms Assert::assertInstanceOf( Field::class, $field, - "Failed asserting that a field with the name [{$fieldName}] exists on the form with the name [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] exists on the form with the name [{$schemaName}] on the [{$livewireClass}] component." ); if ($checkFieldUsing) { Assert::assertTrue( $checkFieldUsing($field), - "Failed asserting that a field with the name [{$fieldName}] and provided configuration exists on the form with the name [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] and provided configuration exists on the form with the name [{$schemaName}] on the [{$livewireClass}] component." ); } @@ -262,9 +262,9 @@ class TestsForms public function assertFormFieldDoesNotExist(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; $fields = $form->getFlatFields(withHidden: false); @@ -273,7 +273,7 @@ class TestsForms Assert::assertArrayNotHasKey( $fieldName, $fields, - "Failed asserting that a field with the name [{$fieldName}] does not exist on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] does not exist on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return $this; @@ -282,12 +282,12 @@ class TestsForms public function assertFormFieldDisabled(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName); + $this->assertFormFieldExists($fieldName, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Field $field */ $field = $form->getFlatFields(withHidden: true)[$fieldName]; @@ -295,10 +295,10 @@ class TestsForms $livewireClass = $this->instance()::class; /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName, function (Field $field) use ($fieldName, $formName, $livewireClass): bool { + $this->assertFormFieldExists($fieldName, $schemaName, function (Field $field) use ($fieldName, $schemaName, $livewireClass): bool { Assert::assertTrue( $field->isDisabled(), - "Failed asserting that a field with the name [{$fieldName}] is disabled on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] is disabled on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return true; @@ -318,12 +318,12 @@ class TestsForms public function assertFormFieldEnabled(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName); + $this->assertFormFieldExists($fieldName, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Field $field */ $field = $form->getFlatFields(withHidden: true)[$fieldName]; @@ -331,10 +331,10 @@ class TestsForms $livewireClass = $this->instance()::class; /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName, function (Field $field) use ($fieldName, $formName, $livewireClass): bool { + $this->assertFormFieldExists($fieldName, $schemaName, function (Field $field) use ($fieldName, $schemaName, $livewireClass): bool { Assert::assertFalse( $field->isDisabled(), - "Failed asserting that a field with the name [{$fieldName}] is enabled on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] is enabled on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return true; @@ -354,12 +354,12 @@ class TestsForms public function assertFormFieldReadOnly(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName); + $this->assertFormFieldExists($fieldName, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var TextInput $field */ $field = $form->getFlatFields(withHidden: true)[$fieldName]; @@ -368,7 +368,7 @@ class TestsForms Assert::assertTrue( $field->isReadOnly(), - "Failed asserting that a field with the name [{$fieldName}] is read-only on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] is read-only on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return $this; @@ -385,12 +385,12 @@ class TestsForms public function assertFormFieldHidden(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName); + $this->assertFormFieldExists($fieldName, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; $fields = $form->getFlatFields(withHidden: false); @@ -399,7 +399,7 @@ class TestsForms Assert::assertArrayNotHasKey( $fieldName, $fields, - "Failed asserting that a field with the name [{$fieldName}] is hidden on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] is hidden on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return $this; @@ -416,12 +416,12 @@ class TestsForms public function assertFormFieldVisible(): Closure { - return function (string $fieldName, string $formName = 'form'): static { + return function (string $fieldName, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormFieldExists($fieldName, $formName); + $this->assertFormFieldExists($fieldName, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; $fields = $form->getFlatFields(withHidden: false); @@ -430,7 +430,7 @@ class TestsForms Assert::assertArrayHasKey( $fieldName, $fields, - "Failed asserting that a field with the name [{$fieldName}] is visible on the form named [{$formName}] on the [{$livewireClass}] component." + "Failed asserting that a field with the name [{$fieldName}] is visible on the form named [{$schemaName}] on the [{$livewireClass}] component." ); return $this; @@ -447,12 +447,12 @@ class TestsForms public function assertWizardStepExists(): Closure { - return function (int $step, string $formName = 'form'): static { + return function (int $step, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Wizard $wizard */ $wizard = $form->getComponent(fn (Component | Action | ActionGroup $component): bool => $component instanceof Wizard); @@ -468,12 +468,12 @@ class TestsForms public function assertWizardCurrentStep(): Closure { - return function (int $step, string $formName = 'form'): static { + return function (int $step, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Wizard $wizard */ $wizard = $form->getComponent(fn (Component | Action | ActionGroup $component): bool => $component instanceof Wizard); @@ -489,12 +489,12 @@ class TestsForms public function goToWizardStep(): Closure { - return function (int $step, string $formName = 'form'): static { + return function (int $step, string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertWizardStepExists($step, $formName); + $this->assertWizardStepExists($step, $schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Wizard $wizard */ $wizard = $form->getComponent(fn (Component | Action | ActionGroup $component): bool => $component instanceof Wizard); @@ -509,12 +509,12 @@ class TestsForms public function goToNextWizardStep(): Closure { - return function (string $formName = 'form'): static { + return function (string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Wizard $wizard */ $wizard = $form->getComponent(fn (Component | Action | ActionGroup $component): bool => $component instanceof Wizard); @@ -527,12 +527,12 @@ class TestsForms public function goToPreviousWizardStep(): Closure { - return function (string $formName = 'form'): static { + return function (string $schemaName = 'form'): static { /** @phpstan-ignore-next-line */ - $this->assertFormExists($formName); + $this->assertFormExists($schemaName); /** @var Schema $form */ - $form = $this->instance()->{$formName}; + $form = $this->instance()->{$schemaName}; /** @var Wizard $wizard */ $wizard = $form->getComponent(fn (Component | Action | ActionGroup $component): bool => $component instanceof Wizard); diff --git a/packages/infolists/src/Testing/TestsInfolistActions.php b/packages/infolists/src/Testing/TestsInfolistActions.php index 63f8ea50b1..df1d7ab3e3 100644 --- a/packages/infolists/src/Testing/TestsInfolistActions.php +++ b/packages/infolists/src/Testing/TestsInfolistActions.php @@ -17,10 +17,10 @@ class TestsInfolistActions { public function mountInfolistAction(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->mountAction($actions); @@ -57,10 +57,10 @@ class TestsInfolistActions public function callInfolistAction(): Closure { - return function (string $component, string | array $actions, array $data = [], array $arguments = [], string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, array $data = [], array $arguments = [], string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName, $arguments); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName, $arguments); $this->callAction($actions, $data); @@ -79,10 +79,10 @@ class TestsInfolistActions public function assertInfolistActionExists(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionExists($actions); @@ -92,10 +92,10 @@ class TestsInfolistActions public function assertInfolistActionDoesNotExist(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDoesNotExist($actions); @@ -105,10 +105,10 @@ class TestsInfolistActions public function assertInfolistActionVisible(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionVisible($actions); @@ -118,10 +118,10 @@ class TestsInfolistActions public function assertInfolistActionHidden(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionHidden($actions); @@ -131,10 +131,10 @@ class TestsInfolistActions public function assertInfolistActionEnabled(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionEnabled($actions); @@ -144,10 +144,10 @@ class TestsInfolistActions public function assertInfolistActionDisabled(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDisabled($actions); @@ -157,10 +157,10 @@ class TestsInfolistActions public function assertInfolistActionHasIcon(): Closure { - return function (string $component, string | array $actions, string | BackedEnum $icon, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string | BackedEnum $icon, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionHasIcon($actions, $icon); @@ -170,10 +170,10 @@ class TestsInfolistActions public function assertInfolistActionDoesNotHaveIcon(): Closure { - return function (string $component, string | array $actions, string | BackedEnum $icon, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string | BackedEnum $icon, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDoesNotHaveIcon($actions, $icon); @@ -183,10 +183,10 @@ class TestsInfolistActions public function assertInfolistActionHasLabel(): Closure { - return function (string $component, string | array $actions, string $label, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $label, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionHasLabel($actions, $label); @@ -196,10 +196,10 @@ class TestsInfolistActions public function assertInfolistActionDoesNotHaveLabel(): Closure { - return function (string $component, string | array $actions, string $label, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $label, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDoesNotHaveLabel($actions, $label); @@ -209,10 +209,10 @@ class TestsInfolistActions public function assertInfolistActionHasColor(): Closure { - return function (string $component, string | array $actions, string | array $color, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string | array $color, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionHasColor($actions, $color); @@ -222,10 +222,10 @@ class TestsInfolistActions public function assertInfolistActionDoesNotHaveColor(): Closure { - return function (string $component, string | array $actions, string | array $color, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string | array $color, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDoesNotHaveColor($actions, $color); @@ -235,10 +235,10 @@ class TestsInfolistActions public function assertInfolistActionHasUrl(): Closure { - return function (string $component, string | array $actions, string $url, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $url, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionHasUrl($actions, $url); @@ -248,10 +248,10 @@ class TestsInfolistActions public function assertInfolistActionDoesNotHaveUrl(): Closure { - return function (string $component, string | array $actions, string $url, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $url, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionDoesNotHaveUrl($actions, $url); @@ -261,10 +261,10 @@ class TestsInfolistActions public function assertInfolistActionShouldOpenUrlInNewTab(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionShouldOpenUrlInNewTab($actions); @@ -274,10 +274,10 @@ class TestsInfolistActions public function assertInfolistActionShouldNotOpenUrlInNewTab(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionShouldNotOpenUrlInNewTab($actions); @@ -287,10 +287,10 @@ class TestsInfolistActions public function assertInfolistActionMounted(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionMounted($actions); @@ -300,10 +300,10 @@ class TestsInfolistActions public function assertInfolistActionNotMounted(): Closure { - return function (string $component, string | array $actions, string $infolistName = 'infolist'): static { + return function (string $component, string | array $actions, string $schemaName = 'infolist'): static { /** @var array> $actions */ /** @phpstan-ignore-next-line */ - $actions = $this->parseNestedInfolistActions($component, $actions, $infolistName); + $actions = $this->parseNestedInfolistActions($component, $actions, $schemaName); $this->assertActionNotMounted($actions); diff --git a/packages/panels/src/Livewire/Concerns/HasUserMenu.php b/packages/panels/src/Livewire/Concerns/HasUserMenu.php index dc44538d9b..68c9af9fe7 100644 --- a/packages/panels/src/Livewire/Concerns/HasUserMenu.php +++ b/packages/panels/src/Livewire/Concerns/HasUserMenu.php @@ -17,7 +17,7 @@ trait HasUserMenu if (! Filament::auth()->check()) { return; } - + $this->userMenuItems = Filament::getUserMenuItems(); foreach ($this->userMenuItems as $action) { diff --git a/packages/schemas/src/Testing/TestSchemaComponent.php b/packages/schemas/src/Testing/TestSchemaComponent.php new file mode 100644 index 0000000000..25e53469a7 --- /dev/null +++ b/packages/schemas/src/Testing/TestSchemaComponent.php @@ -0,0 +1,37 @@ + $name]); + } + + public static function inResourceForm(string $name): static + { + return app(static::class, ['name' => "form.{$name}"]); + } + + public static function inResourceInfolist(string $name): static + { + return app(static::class, ['name' => "infolist.{$name}"]); + } + + public static function inActionSchema(string $name, int $actionNestingIndex = 0): static + { + return app(static::class, ['name' => "mountedActionSchema{$actionNestingIndex}.{$name}"]); + } + + public function __toString() + { + return $this->name; + } +} diff --git a/tests/src/Actions/ActionTest.php b/tests/src/Actions/ActionTest.php index ec65a2a6b0..a27de404f9 100644 --- a/tests/src/Actions/ActionTest.php +++ b/tests/src/Actions/ActionTest.php @@ -1,7 +1,7 @@ assertHasNoFormErrors(formName: 'fooForm') - ->assertHasNoFormErrors(formName: 'barForm') + ->assertHasNoFormErrors(schemaName: 'fooForm') + ->assertHasNoFormErrors(schemaName: 'barForm') ->assertWizardStepExists(2, 'fooForm') - ->goToWizardStep(2, formName: 'fooForm') + ->goToWizardStep(2, schemaName: 'fooForm') ->assertHasFormErrors(['title'], 'fooForm') ->assertHasNoFormErrors(['title'], 'barForm'); }); diff --git a/tests/src/Infolists/ActionTest.php b/tests/src/Infolists/ActionTest.php index 678e964712..8c9e7070d0 100644 --- a/tests/src/Infolists/ActionTest.php +++ b/tests/src/Infolists/ActionTest.php @@ -1,7 +1,7 @@