callInfolistAction() returns getInfolist() on null while testing a Infolist Action
What I am trying to do
I have an Infolist Action (
Digging in,
CreateApiTokenAction
) that generates an API token for a user.
In the UI everything works as expected—clicking the action creates the token and shows a success notification.
What I did
1. Added the action to my user view page (ViewUser
), inside the hintActions()
of a TextEntry
.
2. Wrote a test that authenticates a user and calls the action with callInfolistAction()
.
My issue / the error
Running the test throws:
Error : Call to a member function getInfolist() on null
vendor/filament/infolists/src/Testing/TestsActions.php:542
Error : Call to a member function getInfolist() on null
vendor/filament/infolists/src/Testing/TestsActions.php:542
$this->instance()
inside TestsActions.php
is null, so getInfolist()
naturally fails.
Code
// app/Filament/Actions/Infolists/CreateApiTokenAction.php
<?php
declare(strict_types=1);
namespace App\Filament\Actions\Infolists;
use App\Models\User;
use Filament\Infolists\Components\Actions\Action;
use Filament\Notifications\Notification;
use Illuminate\Database\Eloquent\Model;
final class CreateApiTokenAction extends Action
{
protected function setUp(): void
{
parent::setUp();
$this->label('Create token')
->icon('heroicon-m-key')
->color('info')
->action(function (Model $record): void {
/** @var User $record */
$record->createToken('api', ['*']);
Notification::make()
->title('Token created')
->body('API token generated successfully.')
->success()
->send();
});
}
public static function getDefaultName(): ?string
{
return 'createApiToken';
}
}
// app/Filament/Actions/Infolists/CreateApiTokenAction.php
<?php
declare(strict_types=1);
namespace App\Filament\Actions\Infolists;
use App\Models\User;
use Filament\Infolists\Components\Actions\Action;
use Filament\Notifications\Notification;
use Illuminate\Database\Eloquent\Model;
final class CreateApiTokenAction extends Action
{
protected function setUp(): void
{
parent::setUp();
$this->label('Create token')
->icon('heroicon-m-key')
->color('info')
->action(function (Model $record): void {
/** @var User $record */
$record->createToken('api', ['*']);
Notification::make()
->title('Token created')
->body('API token generated successfully.')
->success()
->send();
});
}
public static function getDefaultName(): ?string
{
return 'createApiToken';
}
}
// app/Filament/Resources/UserResource/Pages/ViewUser.php
<?php
declare(strict_types=1);
namespace App\Filament\Resources\UserResource\Pages;
use App\Filament\Actions\Infolists\CreateApiTokenAction;
use App\Filament\Resources\UserResource;
use App\Models\User;
use Filament\Actions;
use Filament\Infolists;
use Filament\Infolists\Infolist;
use Filament\Resources\Pages\ViewRecord;
final class ViewUser extends ViewRecord
{
protected static string $resource = UserResource::class;
public function infolist(Infolist $infolist): Infolist
{
return $infolist->schema([
Infolists\Components\TextEntry::make('token')
->state(fn (?User $record) => $record?->tokens()->where('name', 'api')->first()?->token)
->hintActions([
CreateApiTokenAction::make(),
]),
]);
}
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}
// app/Filament/Resources/UserResource/Pages/ViewUser.php
<?php
declare(strict_types=1);
namespace App\Filament\Resources\UserResource\Pages;
use App\Filament\Actions\Infolists\CreateApiTokenAction;
use App\Filament\Resources\UserResource;
use App\Models\User;
use Filament\Actions;
use Filament\Infolists;
use Filament\Infolists\Infolist;
use Filament\Resources\Pages\ViewRecord;
final class ViewUser extends ViewRecord
{
protected static string $resource = UserResource::class;
public function infolist(Infolist $infolist): Infolist
{
return $infolist->schema([
Infolists\Components\TextEntry::make('token')
->state(fn (?User $record) => $record?->tokens()->where('name', 'api')->first()?->token)
->hintActions([
CreateApiTokenAction::make(),
]),
]);
}
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}
// tests/Feature/Filament/Actions/Infolists/CreateApiTokenActionTest.php
it('can create a token', function () {
actingAs(user()); // helper that returns an admin user
$record = \App\Models\User::factory()->create();
livewire(\App\Filament\Resources\UserResource\Pages\ViewUser::class, [
'record' => $record->getRouteKey(),
])->callInfolistAction('token', ['createApiToken']);
expect($record->refresh())
->tokens()->count()->toBe(1);
});
// tests/Feature/Filament/Actions/Infolists/CreateApiTokenActionTest.php
it('can create a token', function () {
actingAs(user()); // helper that returns an admin user
$record = \App\Models\User::factory()->create();
livewire(\App\Filament\Resources\UserResource\Pages\ViewUser::class, [
'record' => $record->getRouteKey(),
])->callInfolistAction('token', ['createApiToken']);
expect($record->refresh())
->tokens()->count()->toBe(1);
});
1 Reply