org = Organisation::factory()->create(); $this->otherOrg = Organisation::factory()->create(); // Flat event (no parent, no children) $this->flatEvent = Event::factory()->create([ 'organisation_id' => $this->org->id, 'event_type' => 'event', 'parent_event_id' => null, ]); // Festival with 3 sub-events $this->festival = Event::factory()->festival()->create([ 'organisation_id' => $this->org->id, ]); $this->subEvent1 = Event::factory()->subEvent($this->festival)->create([ 'name' => 'Vrijdag', ]); $this->subEvent2 = Event::factory()->subEvent($this->festival)->create([ 'name' => 'Zaterdag', ]); $this->subEvent3 = Event::factory()->subEvent($this->festival)->create([ 'name' => 'Zondag', ]); // Event in a different organisation (must never appear) $this->otherOrgEvent = Event::factory()->create([ 'organisation_id' => $this->otherOrg->id, 'event_type' => 'event', 'parent_event_id' => null, ]); } // --- scopeTopLevel --- public function test_scope_top_level_returns_only_events_without_parent(): void { $results = Event::withoutGlobalScopes()->topLevel()->pluck('id'); $this->assertTrue($results->contains($this->flatEvent->id)); $this->assertTrue($results->contains($this->festival->id)); $this->assertTrue($results->contains($this->otherOrgEvent->id)); $this->assertFalse($results->contains($this->subEvent1->id)); $this->assertFalse($results->contains($this->subEvent2->id)); $this->assertFalse($results->contains($this->subEvent3->id)); } // --- scopeChildren --- public function test_scope_children_returns_only_events_with_parent(): void { $results = Event::withoutGlobalScopes()->children()->pluck('id'); $this->assertTrue($results->contains($this->subEvent1->id)); $this->assertTrue($results->contains($this->subEvent2->id)); $this->assertTrue($results->contains($this->subEvent3->id)); $this->assertFalse($results->contains($this->flatEvent->id)); $this->assertFalse($results->contains($this->festival->id)); $this->assertFalse($results->contains($this->otherOrgEvent->id)); } // --- scopeWithChildren --- public function test_scope_with_children_returns_parent_and_its_children(): void { $results = Event::withoutGlobalScopes() ->withChildren($this->festival->id) ->pluck('id'); $this->assertCount(4, $results); $this->assertTrue($results->contains($this->festival->id)); $this->assertTrue($results->contains($this->subEvent1->id)); $this->assertTrue($results->contains($this->subEvent2->id)); $this->assertTrue($results->contains($this->subEvent3->id)); $this->assertFalse($results->contains($this->flatEvent->id)); $this->assertFalse($results->contains($this->otherOrgEvent->id)); } public function test_scope_with_children_for_flat_event_returns_only_self(): void { $results = Event::withoutGlobalScopes() ->withChildren($this->flatEvent->id) ->pluck('id'); $this->assertCount(1, $results); $this->assertTrue($results->contains($this->flatEvent->id)); } // --- scopeFestivals --- public function test_scope_festivals_returns_only_festival_and_series_types(): void { $series = Event::factory()->series()->create([ 'organisation_id' => $this->org->id, ]); $results = Event::withoutGlobalScopes()->festivals()->pluck('id'); $this->assertTrue($results->contains($this->festival->id)); $this->assertTrue($results->contains($series->id)); $this->assertFalse($results->contains($this->flatEvent->id)); $this->assertFalse($results->contains($this->subEvent1->id)); $this->assertFalse($results->contains($this->otherOrgEvent->id)); } // --- scopeForFestival --- public function test_scope_for_festival_given_child_returns_parent_and_all_siblings(): void { $results = Event::withoutGlobalScopes() ->forFestival($this->subEvent1) ->pluck('id'); $this->assertCount(4, $results); $this->assertTrue($results->contains($this->festival->id)); $this->assertTrue($results->contains($this->subEvent1->id)); $this->assertTrue($results->contains($this->subEvent2->id)); $this->assertTrue($results->contains($this->subEvent3->id)); } public function test_scope_for_festival_given_parent_returns_self_and_all_children(): void { $results = Event::withoutGlobalScopes() ->forFestival($this->festival) ->pluck('id'); $this->assertCount(4, $results); $this->assertTrue($results->contains($this->festival->id)); $this->assertTrue($results->contains($this->subEvent1->id)); $this->assertTrue($results->contains($this->subEvent2->id)); $this->assertTrue($results->contains($this->subEvent3->id)); } public function test_scope_for_festival_given_flat_event_returns_only_self(): void { $results = Event::withoutGlobalScopes() ->forFestival($this->flatEvent) ->pluck('id'); $this->assertCount(1, $results); $this->assertTrue($results->contains($this->flatEvent->id)); } // --- OrganisationScope respect --- public function test_scopes_respect_organisation_scope(): void { $scopedQuery = Event::withoutGlobalScopes() ->withGlobalScope('organisation', new OrganisationScope($this->org->id)); // topLevel within org should not contain other org's event $topLevel = (clone $scopedQuery)->topLevel()->pluck('id'); $this->assertTrue($topLevel->contains($this->flatEvent->id)); $this->assertTrue($topLevel->contains($this->festival->id)); $this->assertFalse($topLevel->contains($this->otherOrgEvent->id)); // children within org $children = (clone $scopedQuery)->children()->pluck('id'); $this->assertTrue($children->contains($this->subEvent1->id)); $this->assertFalse($children->contains($this->otherOrgEvent->id)); // withChildren within org $withChildren = (clone $scopedQuery)->withChildren($this->festival->id)->pluck('id'); $this->assertCount(4, $withChildren); $this->assertFalse($withChildren->contains($this->otherOrgEvent->id)); // festivals within org $festivals = (clone $scopedQuery)->festivals()->pluck('id'); $this->assertTrue($festivals->contains($this->festival->id)); $this->assertFalse($festivals->contains($this->otherOrgEvent->id)); // forFestival within org $forFestival = (clone $scopedQuery)->forFestival($this->subEvent1)->pluck('id'); $this->assertCount(4, $forFestival); $this->assertFalse($forFestival->contains($this->otherOrgEvent->id)); } }