diff --git a/api/tests/Feature/Person/PersonSoftDeleteTest.php b/api/tests/Feature/Person/PersonSoftDeleteTest.php new file mode 100644 index 00000000..019a828e --- /dev/null +++ b/api/tests/Feature/Person/PersonSoftDeleteTest.php @@ -0,0 +1,100 @@ +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)); + } +} diff --git a/dev-docs/BACKLOG.md b/dev-docs/BACKLOG.md index 4dae1366..ab9b2132 100644 --- a/dev-docs/BACKLOG.md +++ b/dev-docs/BACKLOG.md @@ -373,6 +373,19 @@ form-builder UI), omdat screenshots pas zin hebben als de UI staat. --- +### DOC-04 — `scripts/install-claude-sync-hooks.sh` opnemen in SETUP/onboarding + +**Aanleiding:** WS-4 pre-flight audit vond dat `scripts/sync-claude-docs.sh` +bestaat en door de post-commit hook draait, maar de hook-installer +(`scripts/install-claude-sync-hooks.sh`) is niet terug te vinden in de +developer onboarding-instructies. Nieuwe clones missen de hook. +**Wat:** Voeg een regel aan `dev-docs/SETUP.md` (of een post-install +checklist) toe die nieuwe developers opdraagt `install-claude-sync-hooks.sh` +te runnen. 1 regel, geen scope-impact. +**Prioriteit:** Laag — nice-to-have, niet blokkerend voor dev of CI. + +--- + ### FORM-05 — Smart identity-match on public submission values **Stub-status (S3a PR 2, 2026-04-23):** Public event_registration