Skip to main content

Testing Strategy

All tests are written with Pest PHP. PHPUnit is the underlying runner. Pest adds an expressive, function-based syntax that reduces boilerplate and makes test intent clear.


Three Test Layers

LayerLocationToolWhat it tests
API feature teststests/Feature/Api/Pest + actingAs()HTTP endpoints end-to-end
Filament teststests/Feature/Filament/Pest + Livewire test helpersPanel resources, actions, filters
Unit teststests/Unit/PestDomain services in isolation

Conventions

Every test runs in a database transaction. The RefreshDatabase trait rolls back after each test — no test pollution between runs.

Every test establishes a tenant. The first line of every feature test creates a LawFirm and sets it as the Filament tenant:

beforeEach(function () {
$this->firm = LawFirm::factory()->create();
$this->actingAsPanel($this->firm); // custom helper — sets tenant + auth guard
});

Three user factory helpers match the three user types:

staffUser(role: 'LAWYER')    // creates User + FirmUserProfile + UserRoleAssignment
clientUser() // creates User + ClientUser + ClientContact
partnerUser() // creates User + PartnerAttorneyUser + PartnerAttorney

Every endpoint is tested for five standard cases:

CaseExpected
Happy path (authenticated + authorized)200 / 201 / 204
Unauthenticated401
Wrong role (authenticated, insufficient permission)403
Cross-tenant access (valid user, wrong firm)403
Invalid input422

Running Tests

# All tests
php artisan test

# Feature tests only
php artisan test --testsuite=Feature

# Single file
php artisan test tests/Feature/Api/Cases/CaseCreateTest.php

# With coverage (requires Xdebug or PCOV)
php artisan test --coverage --min=80

Test File Structure

tests/
├── Feature/
│ ├── Api/ # REST endpoint tests (see api-tests.md)
│ ├── Admin/ # Admin API tests (see admin-api-tests.md)
│ └── Filament/ # Panel resource tests (see filament-tests.md)
├── Unit/
│ ├── Services/ # Domain service tests (see service-unit-tests.md)
│ └── Models/
│ └── AppendOnlyModelTest.php
├── Datasets/
│ ├── users.php
│ ├── matters.php
│ └── billing.php
└── Helpers/
└── PanelTestHelper.php # actingAsPanel(), staffUser(), etc.

Coverage Targets

LayerTarget
Domain services (app/Services/)95%+
API controllers (app/Http/Controllers/Api/)90%+
Policies (app/Policies/)90%+
Filament resources70%+
Overall80%+

Financial logic (RateResolutionService, InvoiceGeneratorService) must have 100% branch coverage — every code path exercised by a test.