Write Phpunit Test for Filament PHP Resource
Officially filament php use pest for testing purpose. All the example of it’s documentation is depends on PEST which might be bit challenging for developers (like me) those are not used to pest. In this post, I will show you how can you write tests for a resources via phpunit. Let’s jump into it.
I will write a test for user resources. The user resource allows me:
- View list of the users
- Create a new user
- Edit a user
Generate the test file
Let’s create a test file:
php artisan make:test UserResourceTest
Minimum Setup
I need to do minimum setup because all tests are required:
- Database interaction
- Authentication
Let’s add following in the UserResourceTest
class.
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->actingAs(User::factory()->create());
}
Test for /index
page listing
The following test basically confirm me that the /users
page is loading successfully.
/** @test */
public function it_can_render_page()
{
$this->get(UserResource::getUrl('index'))
->assertSuccessful();
}
Now, let’s test it loads the respective records.
# Don't forget to import this
use Livewire\Livewire;
/** @test */
public function it_can_list_users()
{
$users = User::factory()->count(10)->create();
Livewire::test(ListUsers::class)
->assertSee($users->pluck('email')->toArray());
}
Test for /create
page
Let’s write test that confirm the create a new user page is loading successfully.
/** @test */
public function it_can_render_create_page()
{
$this->get(UserResource::getUrl('create'))
->assertSuccessful();
}
Now, let’s confirm that it create a new user when we submit the form with the data.
use Livewire\Livewire;
/** @test */
public function it_can_crate_user()
{
// Arrange
$newUser = User::factory()->make();
// Pre-assertion
$this->assertDatabaseIsEmpty('users');
// Act
Livewire::test(CreateUser::class)
// Setting the orm value
->set('data.name', $newUser->name)
->set('data.email', $newUser->email)
->set('data.password', $newUser->password)
->set('data.type', $newUser->type)
// Trying to hook the data store mechanism
->call('create')
->assertHasNoErrors();
// Assert
$this->assertDatabaseCount('users', 1);
$this->assertDatabaseHas('users', [
'name' => $newUser->name,
'email' => $newUser->email,
'password' => $newUser->password,
'type' => $newUser->type,
]);
}
Now, let’s confirm a field e.g. email
is required to create a user.
use Livewire\Livewire;
/** @test */
public function email_is_required_for_creating_user()
{
$this->assertDatabaseIsEmpty('users');
$newUser = User::factory()->make();
Livewire::test(CreateUser::class)
->set('data.email', NULL) // Explicitly set the email value is "NULL"
->set('data.name', $newUser->name)
->set('data.password', $newUser->password)
->set('data.type', $newUser->type)
->call('create')
->assertHasFormErrors(['email' => 'required']);
$this->assertDatabaseIsEmpty('users');
}
Test for /edit
a user
First, let’s confirm that the edit a user page is loading successfully.
use Livewire\Livewire;
/** @test */
public function it_can_render_edit_page()
{
$user = User::factory()->create();
Livewire::test(EditUser::class, [
'record' => $user->getRouteKey(),
])->assertSuccessful();
}
Secondly, let’s confirm the form has loaded with the right user’s data.
use Livewire\Livewire;
/** @test */
public function it_can_retrieve_data()
{
$user = User::factory()->create();
Livewire::test(EditUser::class, [
'record' => $user->getRouteKey(),
])
->set('data.name', $user->name)
->set('data.slug', $user->slug)
->set('data.email', $user->email)
->set('data.type', $user->type)
->assertHasNoFormErrors();
}
Finally, let’s confirm the behavior by changing a user’s data.
/** @test */
public function it_can_update_user_data()
{
// Arrange
$user = User::factory()->create();
$newData = User::factory()->make();
// Act
Livewire::test(EditUser::class, [
'record' => $user->getRouteKey(),
])
// Set the changed data
->set('data.name', $newData->name)
->set('data.slug', $newData->slug)
->set('data.email', $newData->email)
->set('data.type', $newData->type)
// Hook the update mechanism
->call('save')
->assertHasNoFormErrors();
// Assert
$this->assertDatabaseHas('users', [
'name' => $newData->name,
'email' => $newData->email,
'password' => $newData->password,
'type' => $newData->type,
]);
}
Disclaimer: I totally aware that, I didn’t cover the delete and form required test for edit. If you need to extends that, at least you can get idea how to continue from here.
I hope it will work for you. Thanks for reading.