F
Filament8mo ago
Jo

Testing actions defined within extraModalFooterActions()

When using Pest for testing, is there a way to test the actions defined within extraModalFooterActions() ? I've tried the obvious things like mounting / calling the action which calls the modal first and even dot notation but nothing seems to be working. Basic example:
Action::make('action1')
->requiresConfirmation()
->extraModalFooterActions(fn (Action $action): array => [
$action->make('action2'),
]);
Action::make('action1')
->requiresConfirmation()
->extraModalFooterActions(fn (Action $action): array => [
$action->make('action2'),
]);
This test passes:
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action1')
->assertInfolistActionExists('component', 'action1');
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action1')
->assertInfolistActionExists('component', 'action1');
This fails:
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action2')
->assertInfolistActionExists('component', 'action2');
livewire(ViewPost::class, [
'record' => $this->record->getRouteKey(),
])
->mountInfolistAction('component', 'action2')
->assertInfolistActionExists('component', 'action2');
Failed asserting that a infolist action with name [action2] is registered to [component] on the [App\Filament\Resources\PostResource\Pages\ViewPost] component.
Failed asserting that null is an instance of class Filament\Infolists\Components\Actions\Action.
Failed asserting that a infolist action with name [action2] is registered to [component] on the [App\Filament\Resources\PostResource\Pages\ViewPost] component.
Failed asserting that null is an instance of class Filament\Infolists\Components\Actions\Action.
I just want to be able to do a similar test for action2 as I can do for action1
Solution:
mountInfolistAction after a mountInfolistAction is the issue.. not sure if it is a bug, but I think it isn't a big problem if you can use call()
Jump to solution
10 Replies
LeandroFerreira
LeandroFerreira8mo ago
Where is the action?
Jo
JoOP8mo ago
Well that was a cut-down example because my real code is quite long. I guess it wasn't clear though so I've written a complete new example which is just the Infolist and the Tests to be more clear: Infolist:
public static function infolist(Infolist $infolist): Infolist
{
return $infolist
->schema([
Actions::make([
Action::make('action1')
->modalHeading('Action 1')
->requiresConfirmation()
->action(function () {
dd('action1');
})
->extraModalFooterActions([
Action::make('action2')
->modalHeading('Action 2')
->requiresConfirmation()
->action(function () {
dd('action2');
})
]),
])
]);
}
public static function infolist(Infolist $infolist): Infolist
{
return $infolist
->schema([
Actions::make([
Action::make('action1')
->modalHeading('Action 1')
->requiresConfirmation()
->action(function () {
dd('action1');
})
->extraModalFooterActions([
Action::make('action2')
->modalHeading('Action 2')
->requiresConfirmation()
->action(function () {
dd('action2');
})
]),
])
]);
}
Test:
use App\Filament\Resources\JobResource\Pages\ViewJob;
use App\Models\Job;

use function \Pest\Livewire\livewire;

beforeEach(function () {
$this->job = Job::factory()->create();
});

it('displays the 1st modal', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->mountInfolistAction('.action1Action', 'action1', infolistName: 'infolist')
->assertSee('Action 1');
});

it('displays the 2nd modal', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->mountInfolistAction('.action1Action', 'action2', infolistName: 'infolist')
->assertSee('Action 2');
});
use App\Filament\Resources\JobResource\Pages\ViewJob;
use App\Models\Job;

use function \Pest\Livewire\livewire;

beforeEach(function () {
$this->job = Job::factory()->create();
});

it('displays the 1st modal', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->mountInfolistAction('.action1Action', 'action1', infolistName: 'infolist')
->assertSee('Action 1');
});

it('displays the 2nd modal', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->mountInfolistAction('.action1Action', 'action2', infolistName: 'infolist')
->assertSee('Action 2');
});
The 1st test passes, the 2nd test fails.
LeandroFerreira
LeandroFerreira8mo ago
.action2Action instead of .action1Action ?
Jo
JoOP8mo ago
Well that's what I thought at first, yes, but Filament actually renders the HTML as .action1Action for the 2nd one too.
Jo
JoOP8mo ago
This is how the HTML is rendered by Filament based on the infolist code I gave above. Also of note is the fact that component and name are the opposite way around here than required by mountInfolistAction()
No description
Jo
JoOP8mo ago
(also, I did try .action2Action and it made no difference, the test fails in the same way) Also, something very weird which I don't understand is that this does pass:
it('displays the 2nd modal again', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->call('mountInfolistAction', 'action1', '.action1Action', 'infolist')
->call('mountInfolistAction', 'action2', '.action1Action', 'infolist')
->assertSee('Action 2');
});
it('displays the 2nd modal again', function () {
livewire(ViewJob::class, [
'record' => $this->job->getRouteKey(),
])
->call('mountInfolistAction', 'action1', '.action1Action', 'infolist')
->call('mountInfolistAction', 'action2', '.action1Action', 'infolist')
->assertSee('Action 2');
});
Note that I'm using .action1Action for both of them and that I've switched the name and component arguments around in call() compared to the order they're in when using mountInfolistAction() as it seems to require them in the opposite order. So two weird things here: 1) It works with call() but not mountInfolistAction() and 2) It necessary to swap the order of the arguments. Do you think it could be a bug?
LeandroFerreira
LeandroFerreira8mo ago
try this in the 2nd modal
->mountInfolistAction('.action1Action', 'action1')
->call('mountInfolistAction', 'action2', '.action1Action')
->assertSee('Action 2')
->mountInfolistAction('.action1Action', 'action1')
->call('mountInfolistAction', 'action2', '.action1Action')
->assertSee('Action 2')
Jo
JoOP8mo ago
Yes, that passes too.
Solution
LeandroFerreira
LeandroFerreira8mo ago
mountInfolistAction after a mountInfolistAction is the issue.. not sure if it is a bug, but I think it isn't a big problem if you can use call()
Jo
JoOP8mo ago
Yeah, it's fine now that I know to do it 🙂 Thank you for your help!
Want results from more Discord servers?
Add your server