reconstruction of the project
This commit is contained in:
@@ -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']
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user