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 Koch3mo ago
I guess it should be something like this: ->callInfolistAction('cancelBooking', ['booking' => $booking]);
Bruno Silva
Bruno Silva3mo 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
awcodes3mo ago
I think you need to mountInfoListAction() before you call it.
Mark Chaney
Mark Chaney2mo ago
@Bruno Silva figure this out? I am in the same boat. Can't get past teh getKey error
Bruno Silva
Bruno Silva2mo 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
LeandroFerreira2mo 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 Silva2mo ago
I can make it, I'll send it later tonight
LeandroFerreira
LeandroFerreira2mo ago
let me know please
Mark Chaney
Mark Chaney2mo 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 Silva2mo 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 Silva2mo 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
LeandroFerreira2mo ago
@Bruno Silva use this
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
->call('mountInfolistAction', 'updateUserName', '.updateUserNameAction', 'infolist')
Mark Chaney
Mark Chaney2mo ago
@Leandro Ferreira shouldn’t it work with the helper though? I’m assuming this is a workaround?
Bruno Silva
Bruno Silva2mo 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
LeandroFerreira2mo 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 Chaney2mo 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
More Posts
How to validate size and count of image uploads in RichEditor and MarkdownEditor?How to validate size and count of image uploads in RichEditor and MarkdownEditor?Please guys, is this the sidebar header supposed to be scrollable by default?Can someone explain to my why ->dehydrated() works for storing data on disabled fields?I have been using the `->saveRelationshipsWhenDisabled()` method in my `Select` relationship fields,How to access row data in relationship managerI want to make column visible based on field value but cannot work out what to use? I have tried ->How to set setting values from DB to use accross the project.vat_rate is a value of set in in the DB, where it is a kind of global setting across all classes in How to use $get() to get data from other section or other stepper ?From filament demo : https://github.com/filamentphp/demo/blob/04c41de3dc711cbcb6b4703d9f64e5b3f9f650Call to a member function associate() on nullI got the error like this when tried to create new item or edit seeded data local.ERROR: Call to a SelectFIlter & AsEnumCollectionI have a model `Caliber`. It has a `casts` like this: ```php public function casts(): array { Unable to add Actions Inside Placeholder content of edit modal form.How can I add an action inside Placehoder inside form widget. Here is how I have used Placeholder: PCorrect way to apply a `withCount()` and `->having()` in a SelectFilter?I have a `Domain` that has many `Sites` and I want to filter by the total number of sites each domai