fix all issues before deploy
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace Tests\App\Services;
|
||||
|
||||
use App\Services\EnrollmentTransitionService;
|
||||
use App\Support\Enrollment\DeliberationDecision;
|
||||
use CodeIgniter\Database\BaseBuilder;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -27,6 +28,71 @@ final class EnrollmentTransitionServiceTest extends TestCase
|
||||
$this->assertSame(10, (int) $result['id']);
|
||||
}
|
||||
|
||||
public function testKgMissingDecisionUsesAgePlacementDecision(): void
|
||||
{
|
||||
$service = new EnrollmentTransitionService($this->createMock(BaseConnection::class));
|
||||
|
||||
$this->assertSame(
|
||||
DeliberationDecision::PASSED,
|
||||
$this->invoke($service, 'decisionForKgWithoutFinalDecision', [['class_name' => 'KG'], 6, ''])
|
||||
);
|
||||
$this->assertSame(
|
||||
DeliberationDecision::REPEAT_CLASS,
|
||||
$this->invoke($service, 'decisionForKgWithoutFinalDecision', [['class_name' => 'Kindergarten'], 5, ''])
|
||||
);
|
||||
$this->assertNull($this->invoke($service, 'decisionForKgWithoutFinalDecision', [['class_name' => 'KG'], 6, 'Needs review']));
|
||||
$this->assertNull($this->invoke($service, 'decisionForKgWithoutFinalDecision', [['class_name' => '1'], 6, '']));
|
||||
}
|
||||
|
||||
public function testExplicitNewStudentStatusMarksFirstEnrollmentCandidate(): void
|
||||
{
|
||||
$statusBuilder = $this->builderReturning(['is_new' => 1]);
|
||||
$statusBuilder->method('where')->willReturnSelf();
|
||||
|
||||
$db = $this->createMock(BaseConnection::class);
|
||||
$db->method('tableExists')->with('student_year_status')->willReturn(true);
|
||||
$db->method('table')->with('student_year_status')->willReturn($statusBuilder);
|
||||
|
||||
$service = new EnrollmentTransitionService($db);
|
||||
|
||||
$this->assertTrue($this->invoke($service, 'isFirstEnrollmentStudent', [
|
||||
42,
|
||||
['school_year' => '2026-2027'],
|
||||
'2026-2027',
|
||||
]));
|
||||
}
|
||||
|
||||
public function testFirstEnrollmentPlacementUsesRegistrationGradeBaseSection(): void
|
||||
{
|
||||
$classBuilder = $this->builderReturning(['id' => 3, 'class_name' => '3']);
|
||||
$classBuilder->method('where')->willReturnSelf();
|
||||
|
||||
$sectionBuilder = $this->builderReturning([
|
||||
'class_section_id' => 30,
|
||||
'class_id' => 3,
|
||||
'class_section_name' => '3',
|
||||
]);
|
||||
$sectionBuilder->method('where')->willReturnSelf();
|
||||
|
||||
$db = $this->createMock(BaseConnection::class);
|
||||
$db->method('tableExists')->willReturnCallback(static fn (string $table): bool => $table === 'classSection');
|
||||
$db->method('fieldExists')->willReturn(false);
|
||||
$db->method('table')->willReturnCallback(static function (string $table) use ($classBuilder, $sectionBuilder) {
|
||||
return $table === 'classes' ? $classBuilder : $sectionBuilder;
|
||||
});
|
||||
|
||||
$service = new EnrollmentTransitionService($db);
|
||||
|
||||
$placement = $this->invoke($service, 'firstEnrollmentPlacement', [
|
||||
['registration_grade' => 'Grade 3'],
|
||||
'2026-2027',
|
||||
]);
|
||||
|
||||
$this->assertSame(3, (int) $placement['assigned_grade_id']);
|
||||
$this->assertSame(30, (int) $placement['assigned_class_section_id']);
|
||||
$this->assertSame('same_class_assigned', $placement['placement_status']);
|
||||
}
|
||||
|
||||
public function testClassLookupFallsBackToGlobalRowsWhenSchoolYearSpecificRowIsMissing(): void
|
||||
{
|
||||
$firstBuilder = $this->builderReturning(null);
|
||||
@@ -145,6 +211,66 @@ final class EnrollmentTransitionServiceTest extends TestCase
|
||||
$this->assertContains('SIBLING_LAST_NAME_MISMATCH', $evaluation['blocking_rule_codes']);
|
||||
}
|
||||
|
||||
public function testNewStudentDoesNotMakeReturningSiblingsFailLastNameRule(): void
|
||||
{
|
||||
$studentBuilder = $this->createMock(BaseBuilder::class);
|
||||
$studentBuilder->method('select')->willReturnSelf();
|
||||
$studentBuilder->method('where')->willReturnSelf();
|
||||
$studentBuilder->method('orderBy')->willReturnSelf();
|
||||
$studentBuilder->method('get')->willReturn(new class {
|
||||
public function getResultArray(): array
|
||||
{
|
||||
return [
|
||||
['id' => 1, 'firstname' => 'Ibrahim', 'lastname' => 'Khalid', 'parent_id' => 9],
|
||||
['id' => 2, 'firstname' => 'Eesa', 'lastname' => 'Khalid', 'parent_id' => 9],
|
||||
['id' => 3, 'firstname' => 'Lamia', 'lastname' => 'Khalid', 'parent_id' => 9],
|
||||
['id' => 4, 'firstname' => 'New', 'lastname' => 'Khalid', 'parent_id' => 9],
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
$assignmentBuilder = $this->createMock(BaseBuilder::class);
|
||||
$assignmentBuilder->method('select')->willReturnSelf();
|
||||
$assignmentBuilder->method('join')->willReturnSelf();
|
||||
$assignmentBuilder->method('where')->willReturnSelf();
|
||||
$assignmentBuilder->method('orderBy')->willReturnSelf();
|
||||
$assignmentBuilder->method('limit')->willReturnSelf();
|
||||
$assignmentBuilder->method('get')->willReturnCallback(new class {
|
||||
private int $calls = 0;
|
||||
|
||||
public function __invoke(): object
|
||||
{
|
||||
$this->calls++;
|
||||
$hasSourceAssignment = $this->calls <= 3;
|
||||
|
||||
return new class($hasSourceAssignment) {
|
||||
public function __construct(private readonly bool $hasSourceAssignment)
|
||||
{
|
||||
}
|
||||
|
||||
public function getRowArray(): ?array
|
||||
{
|
||||
return $this->hasSourceAssignment ? ['class_section_id' => 10] : null;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
$db = $this->createMock(BaseConnection::class);
|
||||
$db->method('tableExists')->willReturnCallback(static fn (string $table): bool => in_array($table, ['students', 'student_class'], true));
|
||||
$db->method('table')->willReturnCallback(static function (string $table) use ($studentBuilder, $assignmentBuilder) {
|
||||
return $table === 'students' ? $studentBuilder : $assignmentBuilder;
|
||||
});
|
||||
|
||||
$service = new EnrollmentTransitionService($db);
|
||||
$evaluation = [];
|
||||
|
||||
$this->invoke($service, 'applyHouseholdLastNameRule', [&$evaluation, 9, '2025-2026']);
|
||||
|
||||
$this->assertTrue($evaluation['family_name_check_ok']);
|
||||
$this->assertArrayNotHasKey('blocking_rule_codes', $evaluation);
|
||||
}
|
||||
|
||||
public function testPreviousYearBalanceBlocksEnrollment(): void
|
||||
{
|
||||
$service = $this->serviceWithFinance(125.50, 'submission_blocked_until_payment');
|
||||
@@ -343,6 +469,29 @@ final class EnrollmentTransitionServiceTest extends TestCase
|
||||
$this->assertArrayNotHasKey('parent_enrollment_allowed', $evaluation);
|
||||
}
|
||||
|
||||
public function testClassReassignmentFlagIsIgnored(): void
|
||||
{
|
||||
$db = $this->createMock(BaseConnection::class);
|
||||
$db->method('tableExists')->with('enrollment_flags')->willReturn(true);
|
||||
$db->expects($this->never())->method('table');
|
||||
|
||||
$service = new EnrollmentTransitionService($db);
|
||||
|
||||
$written = $this->invoke($service, 'upsertOpenFlag', [
|
||||
123,
|
||||
'2026-2027',
|
||||
'2025-2026',
|
||||
[
|
||||
'flag_type' => 'CLASS_REASSIGNMENT_REQUIRED',
|
||||
'priority' => 'normal',
|
||||
'details' => ['reason' => 'repeat class'],
|
||||
],
|
||||
null,
|
||||
]);
|
||||
|
||||
$this->assertFalse($written);
|
||||
}
|
||||
|
||||
public function testPreviousLastNameExceptionDoesNotCarryForwardWhenNewStudentIsAdded(): void
|
||||
{
|
||||
$service = $this->serviceWithLastNameCarryForward(
|
||||
|
||||
Reference in New Issue
Block a user