Testing Filament with Pest: Resources &amp; Actions | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Testing Filament Resources, Actions, and Form Assertions with Pest        On this page       1. [  Testing Filament Resources, Actions, and Form Assertions with Pest ](#testing-filament-resources-actions-and-form-assertions-with-pest)
2. [  Setting Up the Test Environment ](#setting-up-the-test-environment)
3. [  Testing the List Page ](#testing-the-list-page)
4. [  Asserting Table Actions ](#asserting-table-actions)
5. [  Testing Create and Edit Forms ](#testing-create-and-edit-forms)
6. [  Testing Header Actions and Modals ](#testing-header-actions-and-modals)
7. [  Infolist Assertions (Filament v4) ](#infolist-assertions-filament-v4)
8. [  Key Takeaways ](#key-takeaways)

  ![Testing Filament Resources, Actions, and Form Assertions with Pest](https://cdn.msaied.com/304/2d16aec8179bbaae9647506470a85e40.png)

  #filament   #pest   #testing   #laravel  

 Testing Filament Resources, Actions, and Form Assertions with Pest 
====================================================================

     27 Jun 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Testing Filament Resources, Actions, and Form Assertions with Pest  ](#testing-filament-resources-actions-and-form-assertions-with-pest)
2. [  02   Setting Up the Test Environment  ](#setting-up-the-test-environment)
3. [  03   Testing the List Page  ](#testing-the-list-page)
4. [  04   Asserting Table Actions  ](#asserting-table-actions)
5. [  05   Testing Create and Edit Forms  ](#testing-create-and-edit-forms)
6. [  06   Testing Header Actions and Modals  ](#testing-header-actions-and-modals)
7. [  07   Infolist Assertions (Filament v4)  ](#infolist-assertions-filament-v4)
8. [  08   Key Takeaways  ](#key-takeaways)

 Testing Filament Resources, Actions, and Form Assertions with Pest
------------------------------------------------------------------

Filament ships with a first-class testing API built on top of Livewire's test utilities. Yet most teams either skip tests entirely or write fragile assertions against rendered HTML. This article shows you how to write meaningful, maintainable Pest tests for Filament resources — covering list pages, table actions, create/edit forms, and infolist assertions.

### Setting Up the Test Environment

Filament tests need an authenticated user and an active panel. Use the `actingAs` helper combined with `filament()->setCurrentPanel()`:

```php
use App\Models\User;
use function Pest\Laravel\actingAs;

beforeEach(function () {
    actingAs(User::factory()->create());
});

```

For multi-panel setups, resolve the panel explicitly:

```php
use Filament\Facades\Filament;

beforeEach(function () {
    $panel = Filament::getPanel('admin');
    Filament::setCurrentPanel($panel);
    actingAs(User::factory()->create());
});

```

### Testing the List Page

Filament exposes `livewire()` helpers that understand resource routing. Use `Livewire::test()` with the resource's list page class:

```php
use App\Filament\Resources\OrderResource\Pages\ListOrders;
use Livewire\Livewire;

it('renders the orders list', function () {
    Order::factory()->count(3)->create();

    Livewire::test(ListOrders::class)
        ->assertCanSeeTableRecords(Order::all());
});

```

`assertCanSeeTableRecords` checks that the Eloquent models are present in the rendered table — no CSS selectors required.

### Asserting Table Actions

Table row actions are tested by passing the action name and the target record:

```php
it('soft-deletes an order via table action', function () {
    $order = Order::factory()->create();

    Livewire::test(ListOrders::class)
        ->callTableAction('delete', $order)
        ->assertHasNoTableActionErrors();

    expect($order->fresh()->deleted_at)->not->toBeNull();
});

```

For bulk actions, use `callTableBulkAction`:

```php
it('exports selected orders', function () {
    $orders = Order::factory()->count(5)->create();

    Livewire::test(ListOrders::class)
        ->callTableBulkAction('export', $orders)
        ->assertHasNoTableActionErrors();
});

```

### Testing Create and Edit Forms

Form assertions use `fillForm` and `assertHasNoFormErrors`. Target the specific form by name when a page has multiple:

```php
use App\Filament\Resources\OrderResource\Pages\CreateOrder;

it('creates an order with valid data', function () {
    $customer = Customer::factory()->create();

    Livewire::test(CreateOrder::class)
        ->fillForm([
            'customer_id' => $customer->id,
            'status'      => 'pending',
            'total'       => 199.99,
        ])
        ->call('create')
        ->assertHasNoFormErrors();

    expect(Order::where('customer_id', $customer->id)->exists())->toBeTrue();
});

```

Validation failures are equally straightforward:

```php
it('requires a customer', function () {
    Livewire::test(CreateOrder::class)
        ->fillForm(['status' => 'pending'])
        ->call('create')
        ->assertHasFormErrors(['customer_id' => 'required']);
});

```

### Testing Header Actions and Modals

Header actions (e.g., a custom "Approve" action with a confirmation modal) are called via `callAction`:

```php
use App\Filament\Resources\OrderResource\Pages\EditOrder;

it('approves an order through the header action', function () {
    $order = Order::factory()->state(['status' => 'pending'])->create();

    Livewire::test(EditOrder::class, ['record' => $order->getRouteKey()])
        ->callAction('approve')
        ->assertHasNoActionErrors();

    expect($order->fresh()->status)->toBe('approved');
});

```

If the action opens a modal with its own form, chain `fillActionForm` before `callAction`:

```php
->fillActionForm(['reason' => 'Verified by finance'])
->callAction('approve')

```

### Infolist Assertions (Filament v4)

Filament v4 infolists expose `assertSeeInInfolist`:

```php
use App\Filament\Resources\OrderResource\Pages\ViewOrder;

it('displays the order total in the infolist', function () {
    $order = Order::factory()->create(['total' => 250.00]);

    Livewire::test(ViewOrder::class, ['record' => $order->getRouteKey()])
        ->assertSeeInInfolist('order_details', '250');
});

```

### Key Takeaways

- Use `assertCanSeeTableRecords` and `assertCanNotSeeTableRecords` instead of asserting raw HTML.
- `callTableAction` / `callTableBulkAction` are the stable API for row and bulk actions.
- `fillForm` + `assertHasNoFormErrors` / `assertHasFormErrors` covers the full validation surface.
- Always set the active panel in `beforeEach` for multi-panel apps to avoid resolver exceptions.
- Test the database state after actions — Livewire assertions confirm UI, not persistence.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ftesting-filament-resources-actions-and-form-assertions-with-pest-1&text=Testing+Filament+Resources%2C+Actions%2C+and+Form+Assertions+with+Pest) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Ftesting-filament-resources-actions-and-form-assertions-with-pest-1) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Do Filament tests require a real database or can I use mocks?        Filament's testing API resolves Eloquent models directly, so you need a real (or in-memory SQLite) database. Use RefreshDatabase in your Pest test suite and factories to seed state. Mocking Eloquent at this layer adds more complexity than it saves. 

      Q02  How do I test a table filter in Filament?        Use `filterTable('filter_name', ['value' =&gt; 'x'])` on the Livewire test instance, then follow up with `assertCanSeeTableRecords` or `assertCanNotSeeTableRecords` to verify the filtered result set. 

      Q03  Can I test custom Filament actions that dispatch jobs or events?        Yes. Wrap the `callAction` call between `Queue::fake()` / `Event::fake()` and then assert with `Queue::assertPushed()` or `Event::assertDispatched()` as you would in any Laravel feature test. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Livewire v3 Performance: Optimistic UI, Wire:model.live Debouncing, and Dirty State](https://cdn.msaied.com/305/98e4a28fdff5a8448e19534c07bb391d.png) livewire laravel performance 

### Livewire v3 Performance: Optimistic UI, Wire:model.live Debouncing, and Dirty State

Practical techniques for squeezing real performance out of Livewire v3: controlling when the server round-trip...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 27 Jun 2026     3 min read  

  Read    

 ](https://msaied.com/articles/livewire-v3-performance-optimistic-ui-wiremodellive-debouncing-and-dirty-state) [ ![PostgreSQL CTEs, Window Functions, and Lateral Joins in Laravel](https://cdn.msaied.com/303/bbdbe4ee10b30fa9dfecef00698a1c9f.png) laravel postgresql query-builder 

### PostgreSQL CTEs, Window Functions, and Lateral Joins in Laravel

Go beyond basic Eloquent queries. Learn how to harness PostgreSQL CTEs, window functions, and LATERAL joins di...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 27 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/postgresql-ctes-window-functions-and-lateral-joins-in-laravel-1) [ ![Eloquent N+1 at Scale: Eager Loading Strategies, Subquery Selects, and Lazy Eager Loading](https://cdn.msaied.com/302/40500f25f8a29e6cd6eac4938f7211d0.png) laravel eloquent performance 

### Eloquent N+1 at Scale: Eager Loading Strategies, Subquery Selects, and Lazy Eager Loading

N+1 queries silently kill throughput in production. This guide goes beyond basic with() calls to cover subquer...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 27 Jun 2026     4 min read  

  Read    

 ](https://msaied.com/articles/eloquent-n1-at-scale-eager-loading-strategies-subquery-selects-and-lazy-eager-loading) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
