seed(RoleSeeder::class); $this->organisation = Organisation::factory()->create(); $this->otherOrganisation = Organisation::factory()->create(); $this->orgAdmin = User::factory()->create(); $this->organisation->users()->attach($this->orgAdmin, ['role' => 'org_admin']); $this->outsider = User::factory()->create(); $this->otherOrganisation->users()->attach($this->outsider, ['role' => 'org_admin']); $this->event = Event::factory()->create(['organisation_id' => $this->organisation->id]); $this->crowdType = CrowdType::factory()->systemType('VOLUNTEER')->create([ 'organisation_id' => $this->organisation->id, ]); } public function test_index_returns_persons_for_event(): void { Person::factory()->count(3)->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, ]); Sanctum::actingAs($this->orgAdmin); $response = $this->getJson("/api/v1/events/{$this->event->id}/persons"); $response->assertOk(); $this->assertCount(3, $response->json('data')); } public function test_index_filters_by_crowd_type_id(): void { $otherCrowdType = CrowdType::factory()->systemType('CREW')->create([ 'organisation_id' => $this->organisation->id, ]); Person::factory()->count(2)->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, ]); Person::factory()->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $otherCrowdType->id, ]); Sanctum::actingAs($this->orgAdmin); $response = $this->getJson("/api/v1/events/{$this->event->id}/persons?crowd_type_id={$this->crowdType->id}"); $response->assertOk(); $this->assertCount(2, $response->json('data')); } public function test_index_other_event_returns_403(): void { $otherEvent = Event::factory()->create(['organisation_id' => $this->otherOrganisation->id]); Sanctum::actingAs($this->outsider); // Outsider tries to access event from other org Sanctum::actingAs($this->outsider); $response = $this->getJson("/api/v1/events/{$this->event->id}/persons"); $response->assertForbidden(); } public function test_show_returns_person_with_crowd_type(): void { $person = Person::factory()->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, ]); Sanctum::actingAs($this->orgAdmin); $response = $this->getJson("/api/v1/events/{$this->event->id}/persons/{$person->id}"); $response->assertOk() ->assertJsonPath('data.crowd_type.system_type', 'VOLUNTEER'); } public function test_store_creates_person(): void { Sanctum::actingAs($this->orgAdmin); $response = $this->postJson("/api/v1/events/{$this->event->id}/persons", [ 'crowd_type_id' => $this->crowdType->id, 'name' => 'Jan de Vries', 'email' => 'jan@test.nl', 'phone' => '0612345678', ]); $response->assertCreated() ->assertJson(['data' => ['name' => 'Jan de Vries', 'email' => 'jan@test.nl', 'status' => 'pending']]); $this->assertDatabaseHas('persons', [ 'event_id' => $this->event->id, 'name' => 'Jan de Vries', 'email' => 'jan@test.nl', ]); } public function test_update_status(): void { $person = Person::factory()->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, 'status' => 'pending', ]); Sanctum::actingAs($this->orgAdmin); $response = $this->putJson("/api/v1/events/{$this->event->id}/persons/{$person->id}", [ 'status' => 'approved', ]); $response->assertOk() ->assertJsonPath('data.status', 'approved'); } public function test_approve_sets_status_to_approved(): void { $person = Person::factory()->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, 'status' => 'pending', ]); Sanctum::actingAs($this->orgAdmin); $response = $this->postJson("/api/v1/events/{$this->event->id}/persons/{$person->id}/approve"); $response->assertOk() ->assertJsonPath('data.status', 'approved'); $this->assertDatabaseHas('persons', [ 'id' => $person->id, 'status' => 'approved', ]); } public function test_destroy_soft_deletes_person(): void { $person = Person::factory()->create([ 'event_id' => $this->event->id, 'crowd_type_id' => $this->crowdType->id, ]); Sanctum::actingAs($this->orgAdmin); $response = $this->deleteJson("/api/v1/events/{$this->event->id}/persons/{$person->id}"); $response->assertNoContent(); $this->assertSoftDeleted('persons', ['id' => $person->id]); } public function test_unauthenticated_returns_401(): void { $response = $this->getJson("/api/v1/events/{$this->event->id}/persons"); $response->assertUnauthorized(); } }