From 96b95e8c56696bd512aafe4c033a637c3a7c286d Mon Sep 17 00:00:00 2001 From: Ashwin Chandran Date: Wed, 10 Jun 2026 10:29:12 +0200 Subject: [PATCH 1/2] added 'components.group' to the allowed includes under incident and schedule controllers --- src/Http/Controllers/Api/IncidentController.php | 1 + src/Http/Controllers/Api/ScheduleController.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Http/Controllers/Api/IncidentController.php b/src/Http/Controllers/Api/IncidentController.php index 5ed3cf27..f8be581f 100644 --- a/src/Http/Controllers/Api/IncidentController.php +++ b/src/Http/Controllers/Api/IncidentController.php @@ -28,6 +28,7 @@ class IncidentController extends Controller */ public const ALLOWED_INCLUDES = [ 'components', + 'components.group', 'updates', 'user', ]; diff --git a/src/Http/Controllers/Api/ScheduleController.php b/src/Http/Controllers/Api/ScheduleController.php index 57dc4f0a..04ede690 100644 --- a/src/Http/Controllers/Api/ScheduleController.php +++ b/src/Http/Controllers/Api/ScheduleController.php @@ -34,7 +34,7 @@ class ScheduleController extends Controller public function index() { $schedules = QueryBuilder::for(Schedule::class) - ->allowedIncludes(['components', 'updates', 'user']) + ->allowedIncludes(['components', 'components.group', 'updates', 'user']) ->allowedFilters(['name', AllowedFilter::custom('status', new ScheduleStatusFilter)]) ->allowedSorts(['name', 'id', 'scheduled_at', 'completed_at']) ->simplePaginate(request('per_page', 15)); @@ -60,7 +60,7 @@ public function store(CreateScheduleRequestData $data, CreateSchedule $createSch public function show(Schedule $schedule) { $scheduleQuery = QueryBuilder::for(Schedule::class) - ->allowedIncludes(['components', 'updates', 'user']) + ->allowedIncludes(['components', 'components.group', 'updates', 'user']) ->find($schedule->id); return ScheduleResource::make($scheduleQuery) From c9fd1f48040ce786bfe5310ac96d2f45c60ce2f7 Mon Sep 17 00:00:00 2001 From: Ashwin Chandran Date: Wed, 10 Jun 2026 14:18:11 +0200 Subject: [PATCH 2/2] add nested includes test for incident and schedules --- tests/Feature/Api/IncidentTest.php | 17 +++++++++++++++++ tests/Feature/Api/ScheduleTest.php | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/tests/Feature/Api/IncidentTest.php b/tests/Feature/Api/IncidentTest.php index d140c0e5..286eac36 100644 --- a/tests/Feature/Api/IncidentTest.php +++ b/tests/Feature/Api/IncidentTest.php @@ -3,6 +3,7 @@ use Cachet\Enums\ComponentStatusEnum; use Cachet\Enums\IncidentStatusEnum; use Cachet\Models\Component; +use Cachet\Models\ComponentGroup; use Cachet\Models\Incident; use Cachet\Models\IncidentTemplate; use Laravel\Sanctum\Sanctum; @@ -188,6 +189,22 @@ ]); }); +it('can get an incident with components and their groups', function () { + $group = ComponentGroup::factory()->create(); + $component = Component::factory()->for($group, 'group')->create(); + $incident = Incident::factory()->create(); + $incident->components()->attach($component, ['component_status' => ComponentStatusEnum::partial_outage->value]); + + $response = getJson('/status/api/incidents/'.$incident->id.'?include=components.group'); + + $response->assertOk(); + + $included = collect($response->json('included')); + + expect($included->firstWhere('id', (string) $component->id))->not->toBeNull() + ->and($included->firstWhere('attributes.name', $group->name))->not->toBeNull(); +}); + it('cannot create an incident if not authenticated', function () { $response = postJson('/status/api/incidents', [ 'name' => 'New Incident Occurred', diff --git a/tests/Feature/Api/ScheduleTest.php b/tests/Feature/Api/ScheduleTest.php index 3e74efcb..dac25218 100644 --- a/tests/Feature/Api/ScheduleTest.php +++ b/tests/Feature/Api/ScheduleTest.php @@ -1,7 +1,9 @@ create(); + $component = Component::factory()->for($group, 'group')->create(); + $schedule = Schedule::factory()->create(); + $schedule->components()->attach($component, ['component_status' => ComponentStatusEnum::partial_outage->value]); + + $response = getJson('/status/api/schedules/'.$schedule->id.'?include=components.group'); + + $response->assertOk(); + + $included = collect($response->json('included')); + + expect($included->firstWhere('id', (string) $component->id))->not->toBeNull() + ->and($included->firstWhere('attributes.name', $group->name))->not->toBeNull(); +}); + it('cannot create a schedule if not authenticated', function () { $response = postJson('/status/api/schedules', [ 'name' => 'New Scheduled Maintenance',