How to test Infolist Action?

I have a infolist with a ActionsGroup, I want to test if those buttons are working, but I can't figure out how to trigger those actions in the tests. (they work normally in the app) Infolist Action:
Action::make('cancelBooking')
->color('danger')
->requiresConfirmation()
->disabled(function (Booking $record) {
return $record->cancelled_at || $record->entered_at || $record->exited_at;
})
->action(function (Booking $record) {
$record->cancelled_at = now();
$record->save();

Notification::make()
->title('Booking cancelled')
->success()
->send();
}),
Action::make('cancelBooking')
->color('danger')
->requiresConfirmation()
->disabled(function (Booking $record) {
return $record->cancelled_at || $record->entered_at || $record->exited_at;
})
->action(function (Booking $record) {
$record->cancelled_at = now();
$record->save();

Notification::make()
->title('Booking cancelled')
->success()
->send();
}),
Test:
livewire(ViewBooking::class, ['record' => $booking->getRouteKey()])
->callInfolistAction('action', 'cancelBooking');

expect($booking->status)->toBe(BookingStatus::CANCELLED);
livewire(ViewBooking::class, ['record' => $booking->getRouteKey()])
->callInfolistAction('action', 'cancelBooking');

expect($booking->status)->toBe(BookingStatus::CANCELLED);
With that test I get:
Call to a member function getKey() on null
Call to a member function getKey() on null
The button does exists in the test because I "assertSee" it and it passes, but I cannot call it's action
Solution:
@Bruno Silva use this
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
...
Jump to solution
16 Replies
Dennis Koch
Dennis Koch8mo ago
I guess it should be something like this: ->callInfolistAction('cancelBooking', ['booking' => $booking]);
Bruno Silva
Bruno SilvaOP8mo ago
still didn't work, I've tried $booking->getKey(), some different ways to writing, callMountedInfolistAction...
->callMountedInfolistAction([
'action' => 'cancelBooking',
'record' => $booking->getKey(),
]);

// or

->callMountedInfolistAction(['cancelBooking']);
->callMountedInfolistAction([
'action' => 'cancelBooking',
'record' => $booking->getKey(),
]);

// or

->callMountedInfolistAction(['cancelBooking']);
these don't cause errors, but they don't trigger the button either
awcodes
awcodes8mo ago
I think you need to mountInfoListAction() before you call it.
Mark Chaney
Mark Chaney8mo ago
@Bruno Silva figure this out? I am in the same boat. Can't get past teh getKey error
Bruno Silva
Bruno SilvaOP8mo ago
Actually not, @Leandro Ferreira was also helping me through a github discussion but I still couldn't make it work. Leandro, even removing disabled condition and just trying to make the assertionActionEnabled or assertInfolistActionEnabled, it didn't work, I got this error:
Failed asserting that an action with name [test] exists on the [App\Filament\Resources\BookingResource\Pages\ViewBooking] page.
Failed asserting that null is an instance of class Filament\Actions\Action.
Failed asserting that an action with name [test] exists on the [App\Filament\Resources\BookingResource\Pages\ViewBooking] page.
Failed asserting that null is an instance of class Filament\Actions\Action.
I changed the Action name to "test" only to see if it was any problem with a two-word name.
LeandroFerreira
LeandroFerreira8mo ago
Are you able to create a mini repo on Github to reproduce this issue? or @Mark Chaney? You can also share your repo. I can take a look
Bruno Silva
Bruno SilvaOP8mo ago
I can make it, I'll send it later tonight
LeandroFerreira
LeandroFerreira8mo ago
let me know please
Mark Chaney
Mark Chaney8mo ago
super dirty, but if i make a custom Entry field, then use -registerActions() and then call them in the blade of that custom entry, I can then target them with a test using
->callInfolistAction('customcomponentname', 'actionname')
->callInfolistAction('customcomponentname', 'actionname')
. So custom entry component would be
ReviewStep::make('customcomponentname')->registerActions([.....])
ReviewStep::make('customcomponentname')->registerActions([.....])
I absolutely despise it though as its super dirty my blade for the custom entry compoennt is
<div>
@foreach($getActions() as $action)
@if ($action->isVisible())
{{ $action }}
@endif
@endforeach
</div>
<div>
@foreach($getActions() as $action)
@if ($action->isVisible())
{{ $action }}
@endif
@endforeach
</div>
so think the problem is not really having a $component to target in the normal infolist
Bruno Silva
Bruno SilvaOP8mo ago
yeah I thought that too, I've tried passing the ViewPage class name, I didn't know what component is expecting, didn't think about livewire component though
Bruno Silva
Bruno SilvaOP8mo ago
anyway here's the repo with the same problem: https://github.com/brunomdsilva/filament-test.git
GitHub
GitHub - brunomdsilva/filament-test
Contribute to brunomdsilva/filament-test development by creating an account on GitHub.
Solution
LeandroFerreira
LeandroFerreira8mo ago
@Bruno Silva use this
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
Mark Chaney
Mark Chaney8mo ago
@Leandro Ferreira shouldn’t it work with the helper though? I’m assuming this is a workaround?
Bruno Silva
Bruno SilvaOP8mo ago
Yeah, I don't understand exactly why, but the helpers work like this:
->mountInfolistAction('.updateUserNameAction', 'updateUserName')
->callMountedInfolistAction();
->mountInfolistAction('.updateUserNameAction', 'updateUserName')
->callMountedInfolistAction();
I think the .XXX is because of how the element is in the DOM:
<button style="xxx" type="button" wire:loading.attr="disabled" wire:click="mountInfolistAction('updateUserName', '.updateUserNameAction', 'infolist')"></button>
<button style="xxx" type="button" wire:loading.attr="disabled" wire:click="mountInfolistAction('updateUserName', '.updateUserNameAction', 'infolist')"></button>
Thanks Leandro, helped a lot 🙏
LeandroFerreira
LeandroFerreira8mo ago
I think if we encounter any issues or need to test specific scenarios, we can use ->call(). In addition, ->callInfolistAction('.updateUserNameAction', 'updateUserName') with this example, should have the same result.
Mark Chaney
Mark Chaney8mo ago
this worked. now i can remove all that custom entry component that i was using. thanks!
Want results from more Discord servers?
Add your server