reconstruction of the project

This commit is contained in:
root
2026-03-08 16:33:24 -04:00
parent 23b7db1107
commit c8de5f7edc
9157 changed files with 77877 additions and 1073823 deletions
+367 -60
View File
@@ -2,82 +2,389 @@
namespace Tests\Unit\Services;
use App\Models\ClassSection;
use App\Models\Configuration;
use App\Models\Student;
use App\Models\StudentClass;
use App\Models\TeacherClass;
use App\Models\User;
use App\Services\AssignmentService;
use Mockery;
use PHPUnit\Framework\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class AssignmentServiceTest extends TestCase
{
protected function tearDown(): void
use RefreshDatabase;
protected AssignmentService $service;
protected User $teacherMain;
protected User $teacherAssistant;
protected User $updatedByUser;
protected ClassSection $sectionA;
protected ClassSection $sectionB;
protected Student $studentOne;
protected Student $studentTwo;
protected function setUp(): void
{
Mockery::close();
parent::tearDown();
parent::setUp();
$this->service = app(AssignmentService::class);
Configuration::query()->create([
'config_key' => 'semester',
'config_value' => 'Fall',
]);
Configuration::query()->create([
'config_key' => 'school_year',
'config_value' => '2025-2026',
]);
$this->updatedByUser = User::factory()->create();
$this->teacherMain = User::factory()->create([
'firstname' => 'John',
'lastname' => 'Doe',
]);
$this->teacherAssistant = User::factory()->create([
'firstname' => 'Jane',
'lastname' => 'Smith',
]);
$this->sectionA = ClassSection::factory()->create([
'section_name' => 'Alpha Section',
]);
$this->sectionB = ClassSection::factory()->create([
'section_name' => 'Beta Section',
]);
$this->studentOne = Student::factory()->create([
'firstname' => 'Ali',
'lastname' => 'One',
'age' => 10,
'gender' => 'Male',
'registration_grade' => 'Grade 4',
'photo_consent' => 1,
'tuition_paid' => 0,
'school_id' => 'S-100',
'is_active' => 1,
]);
$this->studentTwo = Student::factory()->create([
'firstname' => 'Maya',
'lastname' => 'Two',
'age' => 11,
'gender' => 'Female',
'registration_grade' => 'Grade 5',
'photo_consent' => 0,
'tuition_paid' => 1,
'school_id' => 'S-101',
'is_active' => 1,
]);
}
/** @test */
public function save_student_assignment_uses_config_defaults_and_calls_update_or_create(): void
public function test_get_current_semester_returns_config_value(): void
{
$userModel = Mockery::mock();
$studentModel = Mockery::mock();
$classSectionModel = Mockery::mock();
$teacherClassModel = Mockery::mock();
$this->assertSame('Fall', $this->service->getCurrentSemester());
}
$configModel = Mockery::mock();
$studentClassModel = Mockery::mock();
$studentClassQuery = Mockery::mock();
public function test_get_current_school_year_returns_config_value(): void
{
$this->assertSame('2025-2026', $this->service->getCurrentSchoolYear());
}
// Config defaults
$configModel->shouldReceive('getConfig')->with('semester')->andReturn('Fall');
$configModel->shouldReceive('getConfig')->with('school_year')->andReturn('2025-2026');
public function test_get_assignments_overview_returns_grouped_sections(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
// Eloquent chain: newQuery()->updateOrCreate(...)
$studentClassModel->shouldReceive('newQuery')->once()->andReturn($studentClassQuery);
TeacherClass::query()->create([
'teacher_id' => $this->teacherAssistant->id,
'class_section_id' => $this->sectionA->id,
'position' => 'ta',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
$expectedRecord = (object) [
'id' => 99,
'student_id' => 10,
'class_section_id' => 7,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Auto-assigned',
'updated_by' => 55,
];
StudentClass::query()->create([
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
'updated_by' => $this->updatedByUser->id,
]);
$studentClassQuery->shouldReceive('updateOrCreate')
->once()
->with(
[
'student_id' => 10,
'school_year' => '2025-2026',
'semester' => 'Fall',
],
Mockery::on(function ($payload) {
return $payload['student_id'] === 10
&& $payload['class_section_id'] === 7
&& $payload['semester'] === 'Fall'
&& $payload['school_year'] === '2025-2026'
&& $payload['description'] === 'Auto-assigned'
&& $payload['updated_by'] === 55;
})
)
->andReturn($expectedRecord);
$result = $this->service->getAssignmentsOverview('2025-2026', 'Fall');
$service = new AssignmentService(
$userModel,
$configModel,
$studentModel,
$classSectionModel,
$teacherClassModel,
$studentClassModel
$this->assertSame('2025-2026', $result['schoolYear']);
$this->assertSame('2025-2026', $result['selectedYear']);
$this->assertSame('Fall', $result['selectedSemester']);
$this->assertSame('Fall', $result['semester']);
$this->assertSame('2025-2026', $result['current_school_year']);
$this->assertCount(1, $result['classSections']);
$section = $result['classSections'][0];
$this->assertSame($this->sectionA->id, $section['class_section_id']);
$this->assertSame('Alpha Section', $section['class_section_name']);
$this->assertSame(['John Doe'], $section['main_teachers']);
$this->assertSame(['Jane Smith'], $section['teacher_assistants']);
$this->assertSame('Fall', $section['semester']);
$this->assertSame('2025-2026', $section['school_year']);
$this->assertSame('Alpha description', $section['description']);
$this->assertCount(1, $section['students']);
$this->assertSame('Ali', $section['students'][0]['firstname']);
}
public function test_get_assignments_overview_uses_fallback_config_values_when_metadata_missing(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => null,
'school_year' => null,
'description' => null,
]);
$result = $this->service->getAssignmentsOverview();
$section = $result['classSections'][0];
$this->assertSame('Fall', $section['semester']);
$this->assertSame('2025-2026', $section['school_year']);
$this->assertSame('', $section['description']);
}
public function test_get_assignments_overview_excludes_inactive_students(): void
{
$inactiveStudent = Student::factory()->create([
'firstname' => 'Inactive',
'lastname' => 'Student',
'is_active' => 0,
]);
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
StudentClass::query()->create([
'student_id' => $inactiveStudent->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Should not appear',
'updated_by' => $this->updatedByUser->id,
]);
$result = $this->service->getAssignmentsOverview();
$section = $result['classSections'][0];
$this->assertSame([], $section['students']);
}
public function test_get_assignments_overview_sorts_sections_by_name(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionB->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Beta description',
]);
TeacherClass::query()->create([
'teacher_id' => $this->teacherAssistant->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
$result = $this->service->getAssignmentsOverview();
$this->assertCount(2, $result['classSections']);
$this->assertSame('Alpha Section', $result['classSections'][0]['class_section_name']);
$this->assertSame('Beta Section', $result['classSections'][1]['class_section_name']);
}
public function test_get_assignments_overview_collects_school_years_descending(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2024-2025',
'description' => 'Old year',
]);
TeacherClass::query()->create([
'teacher_id' => $this->teacherAssistant->id,
'class_section_id' => $this->sectionB->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'New year',
]);
$result = $this->service->getAssignmentsOverview();
$this->assertSame(['2025-2026', '2024-2025'], array_values($result['schoolYears']));
}
public function test_store_assignment_creates_new_row(): void
{
$assignment = $this->service->storeAssignment([
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Created by service',
], $this->updatedByUser->id);
$this->assertInstanceOf(StudentClass::class, $assignment);
$this->assertDatabaseHas('student_class', [
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Created by service',
'updated_by' => $this->updatedByUser->id,
]);
}
public function test_store_assignment_updates_existing_row(): void
{
StudentClass::query()->create([
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Old',
'updated_by' => $this->updatedByUser->id,
]);
$assignment = $this->service->storeAssignment([
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'New',
], $this->updatedByUser->id);
$this->assertSame('New', $assignment->description);
$this->assertSame(
1,
StudentClass::query()
->where('student_id', $this->studentOne->id)
->where('class_section_id', $this->sectionA->id)
->where('semester', 'Fall')
->where('school_year', '2025-2026')
->count()
);
$result = $service->saveStudentAssignment([
'student_id' => 10,
'class_section_id' => 7,
'description' => 'Auto-assigned',
// semester/school_year intentionally omitted to test fallback
], 55);
$this->assertDatabaseHas('student_class', [
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'New',
]);
}
$this->assertSame($expectedRecord, $result);
public function test_get_class_assignment_data_returns_all_sections(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
TeacherClass::query()->create([
'teacher_id' => $this->teacherAssistant->id,
'class_section_id' => $this->sectionB->id,
'position' => 'ta',
'semester' => 'Spring',
'school_year' => '2025-2026',
'description' => 'Beta description',
]);
StudentClass::query()->create([
'student_id' => $this->studentOne->id,
'class_section_id' => $this->sectionA->id,
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
'updated_by' => $this->updatedByUser->id,
]);
StudentClass::query()->create([
'student_id' => $this->studentTwo->id,
'class_section_id' => $this->sectionB->id,
'semester' => 'Spring',
'school_year' => '2025-2026',
'description' => 'Beta description',
'updated_by' => $this->updatedByUser->id,
]);
$result = $this->service->getClassAssignmentData();
$this->assertSame('Fall', $result['semester']);
$this->assertSame('2025-2026', $result['school_year']);
$this->assertCount(2, $result['classSections']);
$this->assertSame('Alpha Section', $result['classSections'][0]['class_section_name']);
$this->assertSame('Beta Section', $result['classSections'][1]['class_section_name']);
}
public function test_get_class_assignment_data_deduplicates_teacher_names(): void
{
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
TeacherClass::query()->create([
'teacher_id' => $this->teacherMain->id,
'class_section_id' => $this->sectionA->id,
'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
'description' => 'Alpha description',
]);
$result = $this->service->getClassAssignmentData();
$this->assertSame(
['John Doe'],
$result['classSections'][0]['main_teachers']
);
}
}