Skip to content

Testing Sections

Use SectionDataFactory to build a fully-resolved SectionData fixture in your Pest tests:

php
use FilamentCraft\Testing\SectionDataFactory;

it('renders the heading', function (): void {
    $section = SectionDataFactory::for(MyHeroSection::class)
        ->settings(['heading' => 'Hello'])
        ->blocks([['id' => 'p1', 'type' => 'proof', 'settings' => ['value' => '3x']]])
        ->make();

    expect($section->settings->get('heading'))->toBe('Hello');
});

The factory exercises the same SectionData::fromArray() pipeline the editor uses, so transformer-resolved values (ImageValue, LinkValue, ColorSchemeValue) are produced exactly as in production.

Factory methods

Beyond settings() and blocks(), the builder exposes:

MethodPurpose
id(string $id)Section instance id (defaults to section-1).
withSite(Site $site)Attach a Site — required for sections that read $section->site.
locale(string $locale)Render locale for locale-aware settings.
pageColorScheme(string $slug)Page-level color scheme the section inherits.
designMode(bool $value = true)Build as the editor preview would (design mode) instead of published.
php
use FilamentCraft\Testing\SectionDataFactory;

$section = SectionDataFactory::for(MyHeroSection::class)
    ->withSite($site)
    ->locale('fr')
    ->pageColorScheme('modern')
    ->make();

Testing interactive sections

A LivewireSection is a real Livewire component, so test its behaviour with Livewire's own test helper — pass the SectionData fixture as the section mount argument and drive its wire actions. The $section property round-trips across requests, so assertions hold after a call():

php
use FilamentCraft\Testing\SectionDataFactory;
use Livewire\Livewire;

it('subscribes the visitor', function (): void {
    $data = SectionDataFactory::for(NewsletterSection::class)
        ->settings(['heading' => 'Join the list'])
        ->make();

    Livewire::test(NewsletterSection::class, ['section' => $data])
        ->assertSee('Join the list')
        ->set('email', 'a@b.test')
        ->call('subscribe')
        ->assertSet('subscribed', true)
        ->assertSee('Join the list'); // $section still resolves after the round-trip
});

Livewire::test() passes even for unregistered sections

Livewire::test(SomeSection::class) mounts the class directly, so it succeeds even when the section was never registered with FilamentCraft. On the live storefront, though, every wire action on an unregistered LivewireSection fails with a 419 "page expired" — registration is what binds the class to a stable Livewire component alias, and without it the stateless /livewire/update request can't resolve the component back to its class. Register the section via the plugin (->registerSection(...)) or filamentcraft.sections.register, and browser-verify interactive features on a real page at least once — a unit test can't catch this failure mode.

One-call shortcut: ->test()

SectionDataFactory::test() builds the SectionData and mounts the LivewireSection for you, returning Livewire's Testable — so you skip the explicit Livewire::test(...) wiring. It throws if the class isn't a LivewireSection (static sections have nothing to drive — use make() for those). Pass extra mount arguments as ->test(['foo' => 'bar']); they're merged over the section argument.

The shipped NewsletterSection and ContactSection dispatch NewsletterSubscribed / ContactFormSubmitted on submit — assert them with Event::fake():

php
use FilamentCraft\Events\NewsletterSubscribed;
use FilamentCraft\Testing\SectionDataFactory;
use Illuminate\Support\Facades\Event;

it('dispatches the subscribe event', function (): void {
    Event::fake();

    SectionDataFactory::for(NewsletterSection::class)
        ->test()
        ->set('email', 'a@b.test')
        ->call('subscribe')
        ->assertSet('subscribed', true);

    Event::assertDispatched(NewsletterSubscribed::class, fn ($e) => $e->email === 'a@b.test');
});