Testing Packages
Package tests should prove the package boots, registers its extension points, and owns its behavior.
Test Case
Section titled “Test Case”Create a package test case that registers only the providers the package needs.
protected function getPackageProviders($app): array{ return [ \Capell\Core\Providers\CapellServiceProvider::class, \Capell\Admin\Providers\AdminServiceProvider::class, \Capell\Example\Providers\ExampleServiceProvider::class, \Capell\Example\Providers\AdminServiceProvider::class, ];}Force packages installed in tests when testing installed-only behavior:
CapellCore::forcePackageInstalled('capell-app/example');Manifest Tests
Section titled “Manifest Tests”Every package with capell.json should test that required manifest fields exist and providers are loadable.
Provider Tests
Section titled “Provider Tests”Provider tests should assert:
- package metadata is registered.
- admin pages are registered through
CapellAdmin. - dashboard widgets are registered in the correct dashboard slot.
- settings schemas are registered when present.
it('registers package metadata', function (): void { $package = CapellCore::getPackage('capell-app/example');
expect($package->name)->toBe('capell-app/example');});Action Tests
Section titled “Action Tests”Test Actions directly. Avoid HTTP tests unless the route or Filament page behavior is the subject.
it('builds the package output data', function (): void { $data = BuildExampleOutputAction::run($input);
expect($data)->toBeInstanceOf(ExampleOutputData::class);});Admin Extension Tests
Section titled “Admin Extension Tests”Test direct registration first, then add one render test for the user-facing surface.
it('tags the page schema extender', function (): void { $extenders = collect(app()->tagged(PageSchemaExtender::TAG));
expect($extenders) ->toContain(fn (PageSchemaExtender $extender): bool => $extender instanceof ExamplePageSchemaExtender);});it('registers an extension settings page', function (): void { CapellCore::forcePackageInstalled('capell-app/example');
expect(resolve(ExtensionPageRegistry::class)->get('capell-app/example')) ->toBe(ExampleSettingsPage::class);});Frontend Output Tests
Section titled “Frontend Output Tests”Any package that renders public HTML needs presence and absence assertions.
it('renders public package output without authoring state', function (): void { $response = $this->get('/example-page');
$response->assertOk();
expect($response->getContent()) ->toContain('Expected public copy') ->not->toContain('data-capell-editor') ->not->toContain('field_path') ->not->toContain('signed');});Marketplace Tests
Section titled “Marketplace Tests”Marketplace-adjacent packages should prove local compatibility and authorization state handling without treating remote metadata as trusted code.
it('records install intent only when an instance is connected', function (): void { MarketplaceInstance::factory()->create();
$acquisition = CreateExtensionAcquisitionAction::run($listing);
expect($acquisition->composerCommand)->toContain('composer require');});Architecture Tests
Section titled “Architecture Tests”Use arch tests to prevent package boundary regressions:
- package code should not import app-specific classes.
- frontend providers should not import Filament.
- admin providers should not run on frontend-only contexts.
- packages should not import sibling packages unless Composer requires them.
Narrow Commands
Section titled “Narrow Commands”Run the package suite during implementation:
vendor/bin/pest packages/example/tests --configuration=phpunit.xmlRun the host suite only when the package touches shared contracts, public rendering, install/upgrade, or admin boot:
composer test