arrow_back Back to Course |

Personal finance with Laravel and Filament

Lesson 4 / 7
Lesson 4

Testing Filament Resources

Now that we have our resources set up, it’s time to ensure they work as expected—and stay that way. In this lesson, we’re going to write feature tests for our BankAccount, Budget, and Category resources. We’ll focus particularly on ensuring that users can only see their own data.

Setting up Pest

First, we need to add Pest to our project. Pest is a testing framework with a focus on simplicity and elegance.

bash
composer require pestphp/pest --dev --with-all-dependencies
php artisan pest:install

We also need to make sure our User model is ready for Filament testing. To properly simulate a Filament user in our tests, our User model should implement the FilamentUser contract. This ensures that when we use actingAs, the user is correctly recognized as having access to the panel.

Update app/Models/User.php:

php
use Filament\Models\Contracts\FilamentUser;
// ...

class User extends Authenticatable implements FilamentUser
{
    // ...

    public function canAccessPanel(\Filament\Panel $panel): bool
    {
        return true;
    }
}

You can view the setup and model changes in this commit.

Testing the Bank Account Resource

Let’s start with the BankAccountResource. We want to verify that we can:

  1. Render the page.
  2. List bank accounts belonging to the user.
  3. NOT list bank accounts belonging to other users.
  4. Create, edit, and delete accounts.

Create a new test file: tests/Feature/Filament/Resources/BankAccountResourceTest.php.

Rendering and Listing

We use actingAs($user) to sign in as a user, and then access the page URL.

php
use App\Filament\Resources\BankAccounts\Pages\ManageBankAccounts;
use App\Models\BankAccount;
use App\Models\User;
use Livewire\Livewire;
use function Pest\Laravel\actingAs;

it('can render page', function () {
    $user = User::factory()->create();

    actingAs($user)
        ->get(ManageBankAccounts::getUrl())
        ->assertSuccessful();
});

it('can list bank accounts', function () {
    $user = User::factory()->create();
    $bankAccount = BankAccount::factory()->for($user)->create();

    Livewire::actingAs($user)
        ->test(ManageBankAccounts::class)
        ->assertCanSeeTableRecords([$bankAccount]);
});

Testing Scope (The “Other User” Test)

This is a critical test. We create a user and another user. We expect the current user effectively not to see the other user’s record.

php
it('cannot see other users bank accounts', function () {
    $user = User::factory()->create();
    $otherUser = User::factory()->create();
    $otherBankAccount = BankAccount::factory()->for($otherUser)->create();

    Livewire::actingAs($user)
        ->test(ManageBankAccounts::class)
        ->assertCanNotSeeTableRecords([$otherBankAccount]);
});

Actions: Create, Edit, Delete

Filament provides excellent helpers to test actions directly.

php
it('can create bank account', function () {
    $user = User::factory()->create();

    Livewire::actingAs($user)
        ->test(ManageBankAccounts::class)
        ->mountAction('create')
        ->setActionData([
            'name' => 'My Main Bank',
            'balance' => '1000.50',
        ])
        ->callMountedAction()
        ->assertHasNoActionErrors();

    assertDatabaseHas('bank_accounts', [
        'user_id' => $user->id,
        'name' => 'My Main Bank',
        'balance' => 100050, // Value as integer thanks to our Caster
    ]);
});

Notice how we assert the database has the value 100050 because of our logic handling money as integers!

You can see the full test suite for the Bank Account resource in this commit.

Budget and Category Resources

The tests for BudgetResource and CategoryResource follow the exact same pattern. We need to ensure that detailed actions like creating and editing work, but most importantly, we must verify the scoping rules.

For example, the Category tests ensure that a user can only edit their own categories.

You can check the implementation for the Budget resource tests here and the Category resource tests here.

Running the Tests

Finally, let’s run our test suite to see everything green!

bash
php artisan test

You should see an output confirming that all resource tests are passing:

text
PASS Tests\Feature\Filament\Resources\BankAccountResourceTest
✓ it can render page
✓ it can list bank accounts
✓ it cannot see other users bank accounts
...

Happy coding!

quiz

Knowledge Check

1. Which trait is commonly used in Pest tests to reset the database state between tests?

2. What is the primary purpose of the `assertCanSeeTableRecords` method in Filament tests?

3. Why is it important to test that a user cannot see another user's bank accounts?