softDeletes()`; `app/Models/Person.php` lines 18 + 24 carry * the `SoftDeletes` trait). No code change required — this file is the * behavioural contract. */ final class PersonSoftDeleteTest extends TestCase { use RefreshDatabase; private Person $person; protected function setUp(): void { parent::setUp(); $organisation = Organisation::factory()->create(); $event = Event::factory()->for($organisation)->create(); $crowdType = CrowdType::factory()->for($organisation)->create(); $this->person = Person::factory() ->for($event) ->for($crowdType) ->create(); } public function test_delete_sets_deleted_at_and_hides_row_from_default_queries(): void { $id = $this->person->id; $this->person->delete(); $this->assertNotNull($this->person->fresh()?->deleted_at); $this->assertNull( Person::query()->find($id), 'Soft-deleted person must not appear in default queries' ); } public function test_with_trashed_returns_deleted_row(): void { $id = $this->person->id; $this->person->delete(); $trashed = Person::withTrashed()->find($id); $this->assertNotNull($trashed); $this->assertSame($id, $trashed->id); } public function test_only_trashed_counts_soft_deleted_rows(): void { $this->assertSame(0, Person::onlyTrashed()->count()); $this->person->delete(); $this->assertSame(1, Person::onlyTrashed()->count()); } public function test_restore_clears_deleted_at(): void { $this->person->delete(); $this->assertNotNull($this->person->fresh()?->deleted_at); $this->person->restore(); $this->assertNull($this->person->fresh()?->deleted_at); $this->assertNotNull(Person::query()->find($this->person->id)); } public function test_force_delete_removes_row_permanently(): void { $id = $this->person->id; $this->person->forceDelete(); $this->assertNull(Person::withTrashed()->find($id)); } }