Files
alrahma_sunday_school_api/tests/Feature/Api/V1/AssignmentApiTest.php
T
2026-06-09 02:32:58 -04:00

246 lines
8.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Tests\Feature\Api;
use App\Models\User;
use App\Models\Student;
use App\Models\StudentClass;
use App\Models\TeacherClass;
use App\Models\ClassSection;
use App\Models\Configuration;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Sanctum\Sanctum;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class AssignmentApiTest extends TestCase
{
use RefreshDatabase;
protected User $user;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create();
// Seed config values used by AssignmentService
Configuration::query()->updateOrCreate(
['config_key' => 'semester'],
['config_value' => 'Fall']
);
Configuration::query()->updateOrCreate(
['config_key' => 'school_year'],
['config_value' => '2025-2026']
);
}
#[Test]
public function it_returns_assignment_sections_json(): void
{
Sanctum::actingAs($this->user);
$section = ClassSection::factory()->create([
'class_section_name' => 'Grade 5 - A',
]);
$teacher = User::factory()->create([
'firstname' => 'Ahmad',
'lastname' => 'Ali',
]);
TeacherClass::query()->create([
'teacher_id' => $teacher->id,
'class_section_id' => $section->class_section_id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Main teacher assignment',
]);
$student = Student::factory()->create([
'firstname' => 'Sara',
'lastname' => 'Yousef',
'is_active' => 1,
'gender' => 'F',
'registration_grade' => '5',
'photo_consent' => 1,
'tuition_paid' => 1,
'school_id' => 'SCH-1001',
]);
StudentClass::query()->create([
'student_id' => $student->id,
'class_section_id' => $section->class_section_id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Student assigned',
'is_active' => 1, // remove if your table doesnt have this column
]);
$response = $this->getJson('/api/assignments');
$response->assertOk()
->assertJsonStructure([
'message',
'data' => [
'classSections' => [
'*' => [
'class_section_id',
'class_section_name',
'main_teachers',
'teacher_assistants',
'students',
'semester',
'school_year',
'description',
]
],
'schoolYears',
'selectedYear',
'selectedSemester',
'semester',
'current_school_year',
],
]);
$response->assertJsonPath('data.classSections.0.class_section_id', $section->class_section_id);
$response->assertJsonPath('data.classSections.0.main_teachers.0', 'Ahmad Ali');
$response->assertJsonPath('data.classSections.0.students.0.id', $student->id);
}
#[Test]
public function it_filters_assignments_by_school_year(): void
{
Sanctum::actingAs($this->user);
$section1 = ClassSection::factory()->create(['class_section_name' => 'Grade 4']);
$section2 = ClassSection::factory()->create(['class_section_name' => 'Grade 6']);
$teacher = User::factory()->create(['firstname' => 'Test', 'lastname' => 'Teacher']);
TeacherClass::query()->create([
'teacher_id' => $teacher->id,
'class_section_id' => $section1->class_section_id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2024-2025',
]);
TeacherClass::query()->create([
'teacher_id' => $teacher->id,
'class_section_id' => $section2->class_section_id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
$response = $this->getJson('/api/assignments?school_year=2025-2026');
$response->assertOk();
$sections = $response->json('data.classSections');
$ids = collect($sections)->pluck('class_section_id')->all();
$this->assertContains($section2->class_section_id, $ids);
$this->assertNotContains($section1->class_section_id, $ids);
$response->assertJsonPath('data.selectedYear', '2025-2026');
}
#[Test]
public function it_creates_or_updates_student_assignment(): void
{
Sanctum::actingAs($this->user);
$student = Student::factory()->create(['is_active' => 1]);
$section = ClassSection::factory()->create();
$payload = [
'student_id' => $student->id,
'class_section_id' => $section->class_section_id,
'semester' => 'Spring',
'school_year' => '2025-2026',
'description' => 'Moved after placement review',
];
$response = $this->postJson('/api/assignments', $payload);
$response->assertCreated()
->assertJsonPath('message', 'Assignment saved successfully.');
$this->assertDatabaseHas('student_class', [
'student_id' => $student->id,
'class_section_id' => $section->class_section_id,
'semester' => 'Spring',
'school_year' => '2025-2026',
]);
}
#[Test]
public function it_validates_required_fields_when_storing_assignment(): void
{
Sanctum::actingAs($this->user);
$response = $this->postJson('/api/assignments', []);
$response->assertStatus(422)
->assertJsonValidationErrors([
'student_id',
'class_section_id',
]);
}
#[Test]
public function store_is_idempotent_for_same_student_semester_and_year(): void
{
Sanctum::actingAs($this->user);
$student = Student::factory()->create(['is_active' => 1]);
$sectionA = ClassSection::factory()->create();
$sectionB = ClassSection::factory()->create();
// First create
$this->postJson('/api/assignments', [
'student_id' => $student->id,
'class_section_id' => $sectionA->class_section_id,
'semester' => 'Fall',
'school_year' => '2025-2026',
])->assertCreated();
// Second call same unique key should update (per service updateOrCreate)
$this->postJson('/api/assignments', [
'student_id' => $student->id,
'class_section_id' => $sectionA->class_section_id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Reassigned',
])->assertCreated();
$this->assertEquals(
1,
StudentClass::query()
->where('student_id', $student->id)
->where('semester', 'Fall')
->where('school_year', '2025-2026')
->count()
);
$this->assertDatabaseHas('student_class', [
'student_id' => $student->id,
'class_section_id' => $sectionA->class_section_id,
'semester' => 'Fall',
'school_year' => '2025-2026',
]);
}
#[Test]
public function guest_cannot_access_assignment_api_when_auth_is_required(): void
{
$response = $this->getJson('/api/assignments');
$response->assertStatus(401);
}
}