fix parent pages and teachers and admin
API CI/CD / Validate (composer + pint) (push) Successful in 3m8s
API CI/CD / Build frontend assets (push) Successful in 1m2s
API CI/CD / Test (PHPUnit) (push) Failing after 6m5s
API CI/CD / Security audit (push) Failing after 52s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped

This commit is contained in:
root
2026-07-09 13:56:22 -04:00
parent 21c9322127
commit 02ba2fe6b6
34 changed files with 2306 additions and 99 deletions
@@ -73,6 +73,23 @@ class ClassProgressControllerTest extends TestCase
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('classSection')->insert([
'id' => 8,
'class_id' => 8,
'class_section_id' => 808,
'class_section_name' => '8-A',
'semester' => 'Fall',
'school_year' => '2024-2025',
]);
DB::table('teacher_class')->insert([
'class_section_id' => 808,
'teacher_id' => $user->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2024-2025',
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('subject_curriculum_items')->insert([
'class_id' => 9,
'school_year' => null,
@@ -83,6 +100,16 @@ class ClassProgressControllerTest extends TestCase
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('subject_curriculum_items')->insert([
'class_id' => 9,
'school_year' => null,
'subject' => 'Quran/Arabic',
'unit_number' => 2,
'unit_title' => 'Surah Review',
'chapter_name' => 'Al-Fatiha',
'created_at' => now(),
'updated_at' => now(),
]);
Sanctum::actingAs($user);
@@ -93,8 +120,12 @@ class ClassProgressControllerTest extends TestCase
$response->assertJsonPath('data.defaults.school_year', '2025-2026');
$response->assertJsonPath('data.defaults.semester', 'Fall');
$response->assertJsonPath('data.defaults.class_section_id', 909);
$this->assertCount(1, $response->json('data.classes'));
$response->assertJsonPath('data.classes.0.class_section_id', 909);
$response->assertJsonPath('data.curriculum.islamic.0.chapter_name', 'Intro');
$response->assertJsonPath('data.unit_options.islamic.0.label', 'Unit 1 - Faith');
$response->assertJsonPath('data.curriculum.quran.0.chapter_name', 'Al-Fatiha');
$response->assertJsonPath('data.unit_options.quran.0.label', 'Unit 2 - Surah Review');
}
public function test_index_returns_paginated_reports(): void
@@ -115,10 +146,184 @@ class ClassProgressControllerTest extends TestCase
$this->assertCount(2, $response->json('data.items'));
}
public function test_teacher_history_is_scoped_to_assigned_class_sections(): void
{
$teacher = $this->createUser();
$otherTeacher = $this->createUser('other-history-teacher@example.com');
$this->assignRole($teacher->id, 'teacher');
$this->seedClassSection();
DB::table('classSection')->insert([
'id' => 2,
'class_id' => 2,
'class_section_id' => 202,
'class_section_name' => '2-A',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
$this->assignTeacher($teacher->id, 1);
$this->assignTeacher($teacher->id, 202);
$assignedOwnReport = ClassProgressReport::factory()->create([
'teacher_id' => $teacher->id,
'class_section_id' => 101,
'school_year' => '2025-2026',
'week_start' => '2025-09-07',
]);
$assignedSectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 101,
'school_year' => '2025-2026',
'week_start' => '2025-09-14',
]);
$otherSectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $teacher->id,
'class_section_id' => 202,
'school_year' => '2025-2026',
'week_start' => '2025-09-21',
]);
Sanctum::actingAs($teacher);
$response = $this->getJson('/api/v1/teacher/class-progress-history?school_year=2025-2026&class_section_id=1');
$response->assertOk();
$ids = collect($response->json('data.items'))->pluck('id')->all();
$this->assertContains($assignedOwnReport->id, $ids);
$this->assertContains($assignedSectionReport->id, $ids);
$this->assertNotContains($otherSectionReport->id, $ids);
$detailResponse = $this->getJson('/api/v1/class-progress/'.$assignedSectionReport->id);
$detailResponse->assertOk();
$detailResponse->assertJsonPath('data.report.id', $assignedSectionReport->id);
$unfilteredResponse = $this
->withSession(['class_section_id' => 202])
->getJson('/api/v1/teacher/class-progress-history?school_year=2025-2026');
$unfilteredResponse->assertOk();
$unfilteredIds = collect($unfilteredResponse->json('data.items'))->pluck('id')->all();
$this->assertNotContains($assignedOwnReport->id, $unfilteredIds);
$this->assertNotContains($assignedSectionReport->id, $unfilteredIds);
$this->assertContains($otherSectionReport->id, $unfilteredIds);
}
public function test_teacher_history_accepts_legacy_progress_rows_saved_with_section_pk(): void
{
$teacher = $this->createUser();
$otherTeacher = $this->createUser('legacy-pk-history-teacher@example.com');
$this->assignRole($teacher->id, 'teacher_assistant');
$this->seedClassSection();
$this->assignTeacher($teacher->id, 101);
$legacyPkReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 1,
'school_year' => '2025-2026',
'week_start' => '2025-09-28',
]);
Sanctum::actingAs($teacher);
$response = $this->getJson('/api/v1/teacher/class-progress-history?school_year=2025-2026&class_section_id=101');
$response->assertOk();
$ids = collect($response->json('data.items'))->pluck('id')->all();
$this->assertContains($legacyPkReport->id, $ids);
}
public function test_teacher_history_without_section_uses_logged_in_teacher_assignment(): void
{
$teacher = $this->createUser();
$otherTeacher = $this->createUser('assignment-history-teacher@example.com');
$this->assignRole($teacher->id, 'teacher');
$this->seedClassSection();
DB::table('classSection')->insert([
'id' => 2,
'class_id' => 2,
'class_section_id' => 202,
'class_section_name' => '2-A',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
$this->assignTeacher($teacher->id, 1);
$sameSectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 101,
'school_year' => '2025-2026',
'week_start' => '2025-10-05',
]);
$wrongSectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 202,
'school_year' => '2025-2026',
'week_start' => '2025-10-12',
]);
Sanctum::actingAs($teacher);
$response = $this->getJson('/api/v1/teacher/class-progress-history?school_year=2025-2026');
$response->assertOk();
$ids = collect($response->json('data.items'))->pluck('id')->all();
$this->assertContains($sameSectionReport->id, $ids);
$this->assertNotContains($wrongSectionReport->id, $ids);
}
public function test_teacher_history_without_section_does_not_422_for_multiple_assignments(): void
{
$teacher = $this->createUser();
$otherTeacher = $this->createUser('multi-assignment-history-teacher@example.com');
$this->assignRole($teacher->id, 'teacher');
$this->seedClassSection();
DB::table('classSection')->insert([
'id' => 2,
'class_id' => 2,
'class_section_id' => 202,
'class_section_name' => '2-A',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
$this->assignTeacher($teacher->id, 1);
$this->assignTeacher($teacher->id, 202);
$primarySectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 101,
'school_year' => '2025-2026',
'week_start' => '2025-10-19',
]);
$otherSectionReport = ClassProgressReport::factory()->create([
'teacher_id' => $otherTeacher->id,
'class_section_id' => 202,
'school_year' => '2025-2026',
'week_start' => '2025-10-26',
]);
Sanctum::actingAs($teacher);
$response = $this->getJson('/api/v1/teacher/class-progress-history?school_year=2025-2026&per_page=100&sort_by=week_start&sort_dir=desc');
$response->assertOk();
$ids = collect($response->json('data.items'))->pluck('id')->all();
$this->assertContains($primarySectionReport->id, $ids);
$this->assertNotContains($otherSectionReport->id, $ids);
}
public function test_admin_grouped_index_uses_school_year_name_and_includes_legacy_rows(): void
{
$admin = $this->createUser('admin@example.com');
$this->assignRole($admin->id, 'administrator');
DB::table('configuration')->updateOrInsert(
['config_key' => 'semester'],
['config_value' => 'Fall']
);
$this->seedClassSection();
DB::table('classSection')->where('class_section_id', 101)->update([
'semester' => '',
@@ -286,6 +491,74 @@ class ClassProgressControllerTest extends TestCase
$this->assertDatabaseCount('class_progress_reports', 2);
}
public function test_teacher_store_uses_logged_in_teacher_assignment_for_section(): void
{
Storage::fake('public');
$user = $this->createUser();
$this->assignRole($user->id, 'teacher');
$this->seedClassSection();
DB::table('classSection')->insert([
'id' => 2,
'class_id' => 2,
'class_section_id' => 202,
'class_section_name' => '2-A',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
$this->assignTeacher($user->id, 101);
Sanctum::actingAs($user);
$payload = [
'class_section_id' => 202,
'week_start' => '2025-09-07',
'week_end' => '2025-09-13',
'covered_islamic' => 'Lesson A',
'covered_quran' => 'Lesson B',
'unit_islamic' => ['Unit 1'],
'chapter_islamic' => ['Chapter A'],
'school_year' => '2025-2026',
];
$response = $this->postJson('/api/v1/teacher/class-progress-submit', $payload);
$response->assertStatus(201);
$this->assertDatabaseHas('class_progress_reports', [
'teacher_id' => $user->id,
'class_section_id' => 101,
'subject' => 'Islamic Studies',
]);
$this->assertDatabaseMissing('class_progress_reports', [
'teacher_id' => $user->id,
'class_section_id' => 202,
]);
}
public function test_teacher_store_without_section_uses_logged_in_teacher_assignment(): void
{
Storage::fake('public');
$user = $this->createUser();
$this->assignRole($user->id, 'teacher');
$this->seedClassSection();
$this->assignTeacher($user->id, 101);
Sanctum::actingAs($user);
$response = $this->postJson('/api/v1/teacher/class-progress-submit', [
'week_start' => '2025-09-07',
'week_end' => '2025-09-13',
'covered_islamic' => 'Lesson A',
'unit_islamic' => ['Unit 1'],
'chapter_islamic' => ['Chapter A'],
'school_year' => '2025-2026',
]);
$response->assertStatus(201);
$this->assertDatabaseHas('class_progress_reports', [
'teacher_id' => $user->id,
'class_section_id' => 101,
'subject' => 'Islamic Studies',
]);
}
public function test_show_returns_weekly_reports(): void
{
$user = $this->createUser();