createMock(BaseConnection::class), $this->createMock(\App\Models\AdminNotificationSubjectModel::class) ); $this->assertSame([ 'academics' => 'Academics', 'attendance' => 'Attendance', 'events' => 'Events', 'finance' => 'Finance', 'general' => 'General', 'print_requests' => 'Print Requests', ], $service->subjectOptions()); } public function testAdminNotificationExcludedRolesIncludeParentAndTeacher(): void { $service = new AdminNotificationSettingsService( $this->createMock(BaseConnection::class), $this->createMock(\App\Models\AdminNotificationSubjectModel::class) ); $excluded = $service->excludedRoles(); $this->assertContains('parent', $excluded); $this->assertContains('teacher', $excluded); $this->assertContains('teacher_assistant', $excluded); } public function testDashboardCountUniqueEntitiesDedupesIds(): void { $service = new AdministratorDashboardService( $this->createMock(BaseConnection::class), $this->createMock(\App\Models\UserModel::class), $this->createMock(\App\Models\LoginActivityModel::class) ); $count = $this->invoke($service, 'countUniqueEntities', [[ ['id' => 1], ['id' => 1], ['user_id' => 2], ['user_id' => 2], ['name' => 'ignored'], ]]); $this->assertSame(2, $count); } public function testStudentDecisionClassLabelHelpers(): void { $service = new StudentDecisionService( $this->createMock(BaseConnection::class), $this->createMock(\App\Models\ConfigurationModel::class), $this->createMock(\App\Models\StudentModel::class), $this->createMock(\App\Models\StudentClassModel::class), $this->createMock(\App\Models\UserModel::class) ); $this->assertSame('Class 8A', $this->invoke($service, 'classOnlyLabel', ['Class 8A'])); $this->assertSame('Class 8', $this->invoke($service, 'classOnlyLabel', ['Class 8-A'])); $this->assertTrue($this->invoke($service, 'isKgClass', ['KG'])); $this->assertTrue($this->invoke($service, 'isKgClass', ['Kindergarten'])); $this->assertFalse($this->invoke($service, 'isKgClass', ['Class 1'])); } public function testNextYearPlacementLabelUsesDeliberationDecision(): void { $service = new StudentDecisionService( $this->createMock(BaseConnection::class), $this->createMock(\App\Models\ConfigurationModel::class), $this->createMock(\App\Models\StudentModel::class), $this->createMock(\App\Models\StudentClassModel::class), $this->createMock(\App\Models\UserModel::class) ); $repeat = $this->invoke($service, 'nextYearPlacementLabel', [ DeliberationDecision::REPEAT_CLASS, 'Class 5', '5A', '2015-01-01', '2024-2025', ]); $this->assertSame('Class 5', $repeat); $passed = $this->invoke($service, 'nextYearPlacementLabel', [ DeliberationDecision::PASSED, 'Class 5', '5A', '2015-01-01', '2024-2025', ]); $this->assertSame('', $passed); } private function invoke(object $service, string $method, array $args = []): mixed { $ref = new \ReflectionMethod($service, $method); $ref->setAccessible(true); return $ref->invokeArgs($service, $args); } }