create([ 'role' => 'administrator', 'firstname' => 'Admin', 'lastname' => 'User', 'email' => 'admin@example.com', ]); return $admin; } protected function seedSchoolConfig(): void { DB::table('configurations')->insert([ ['config_key' => 'semester', 'config_value' => 'Fall'], ['config_key' => 'school_year', 'config_value' => '2025-2026'], ]); } /** @test */ public function admin_can_fetch_teacher_submission_report(): void { $admin = $this->createAdmin(); $this->seedSchoolConfig(); // Minimal records to allow report query to run DB::table('classSection')->insert([ 'class_section_id' => 1, 'class_section_name' => 'Grade 5 - A', ]); $teacher = User::factory()->create([ 'firstname' => 'Fatima', 'lastname' => 'Teacher', 'email' => 'teacher1@example.com', ]); DB::table('teacher_class')->insert([ 'teacher_id' => $teacher->id, 'class_section_id' => 1, 'position' => 'main', 'semester' => 'Fall', 'school_year' => '2025-2026', ]); $response = $this->actingAs($admin, 'sanctum') ->getJson('/api/admin/teacher-submissions/report'); $response->assertOk() ->assertJsonStructure([ 'semester', 'school_year', 'rows', 'notification_history', 'summary' => [ 'total_items', 'missing_items', 'submitted_items', 'submission_percentage', ], ]); } /** @test */ public function admin_can_send_teacher_submission_notifications(): void { Mail::fake(); $admin = $this->createAdmin(); $this->seedSchoolConfig(); DB::table('classSection')->insert([ 'class_section_id' => 2, 'class_section_name' => 'Grade 6 - B', ]); $teacher = User::factory()->create([ 'firstname' => 'Amina', 'lastname' => 'Smith', 'email' => 'amina@example.com', ]); // optional history table insert compatibility depends on schema; no need to seed rows $payload = [ 'notify' => [ 2 => [ $teacher->id => 1, ], ], 'missing_items' => [ 2 => [ $teacher->id => base64_encode(json_encode(['midterm scores', 'PTAP comments'])), ], ], ]; $response = $this->actingAs($admin, 'sanctum') ->postJson('/api/admin/teacher-submissions/notifications', $payload); $response->assertOk() ->assertJsonStructure([ 'message', 'sent', 'failed', 'results' => [ '*' => [ 'teacher_id', 'class_section_id', 'teacher_name', 'section_name', 'email', 'status', 'missing_items', 'error', ], ], ]); Mail::assertSentCount(1); } /** @test */ public function teacher_submission_notifications_requires_notify_payload(): void { $admin = $this->createAdmin(); $response = $this->actingAs($admin, 'sanctum') ->postJson('/api/admin/teacher-submissions/notifications', []); $response->assertStatus(422) ->assertJsonValidationErrors(['notify']); } /** @test */ public function non_admin_cannot_access_teacher_submission_endpoints(): void { $user = User::factory()->create(['role' => 'teacher']); $this->actingAs($user, 'sanctum') ->getJson('/api/admin/teacher-submissions/report') ->assertStatus(403); } }