Appearance
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:
| Method | Purpose |
|---|---|
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');
});