105 lines
3.4 KiB
PHP
105 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\App\Services;
|
|
|
|
use App\Services\EnrollmentTransitionService;
|
|
use CodeIgniter\Database\BaseBuilder;
|
|
use CodeIgniter\Database\BaseConnection;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class EnrollmentTransitionServiceTest extends TestCase
|
|
{
|
|
public function testPassedClassNameWithPrefixFindsNextNumericGrade(): void
|
|
{
|
|
$service = $this->serviceExpectingClassLookup('9', ['id' => 9, 'class_name' => '9']);
|
|
|
|
$result = $this->invoke($service, 'nextClass', ['Class 8', '2026-2027']);
|
|
|
|
$this->assertSame(9, (int) $result['id']);
|
|
}
|
|
|
|
public function testPassedClassNinePromotesToTenWhenGradeTenExists(): void
|
|
{
|
|
$service = $this->serviceExpectingClassLookup('10', ['id' => 10, 'class_name' => '10']);
|
|
|
|
$result = $this->invoke($service, 'nextClass', ['Class 9', '2026-2027']);
|
|
|
|
$this->assertSame(10, (int) $result['id']);
|
|
}
|
|
|
|
public function testClassLookupFallsBackToGlobalRowsWhenSchoolYearSpecificRowIsMissing(): void
|
|
{
|
|
$firstBuilder = $this->builderReturning(null);
|
|
$firstBuilder->expects($this->exactly(2))
|
|
->method('where')
|
|
->willReturnSelf();
|
|
|
|
$fallbackBuilder = $this->builderReturning(['id' => 10, 'class_name' => '10']);
|
|
$fallbackBuilder->expects($this->once())
|
|
->method('where')
|
|
->with('UPPER(class_name)', '10')
|
|
->willReturnSelf();
|
|
|
|
$db = $this->createMock(BaseConnection::class);
|
|
$db->expects($this->exactly(2))
|
|
->method('table')
|
|
->with('classes')
|
|
->willReturnOnConsecutiveCalls($firstBuilder, $fallbackBuilder);
|
|
$db->method('fieldExists')->with('school_year', 'classes')->willReturn(true);
|
|
|
|
$service = new EnrollmentTransitionService($db);
|
|
|
|
$result = $this->invoke($service, 'nextClass', ['Class 9', '2026-2027']);
|
|
|
|
$this->assertSame(10, (int) $result['id']);
|
|
}
|
|
|
|
private function serviceExpectingClassLookup(string $expectedClassName, array $row): EnrollmentTransitionService
|
|
{
|
|
$builder = $this->builderReturning($row);
|
|
$builder->expects($this->once())
|
|
->method('where')
|
|
->with('UPPER(class_name)', $expectedClassName)
|
|
->willReturnSelf();
|
|
|
|
$db = $this->createMock(BaseConnection::class);
|
|
$db->expects($this->once())
|
|
->method('table')
|
|
->with('classes')
|
|
->willReturn($builder);
|
|
$db->method('fieldExists')->with('school_year', 'classes')->willReturn(false);
|
|
|
|
return new EnrollmentTransitionService($db);
|
|
}
|
|
|
|
private function builderReturning(?array $row): BaseBuilder
|
|
{
|
|
$builder = $this->createMock(BaseBuilder::class);
|
|
$builder->method('orderBy')->willReturnSelf();
|
|
$builder->method('limit')->willReturnSelf();
|
|
$builder->method('get')->willReturn(new class($row) {
|
|
public function __construct(private readonly ?array $row)
|
|
{
|
|
}
|
|
|
|
public function getRowArray(): ?array
|
|
{
|
|
return $this->row;
|
|
}
|
|
});
|
|
|
|
return $builder;
|
|
}
|
|
|
|
/**
|
|
* @param list<mixed> $args
|
|
*/
|
|
private function invoke(EnrollmentTransitionService $service, string $method, array $args): mixed
|
|
{
|
|
$reflection = new \ReflectionMethod($service, $method);
|
|
$reflection->setAccessible(true);
|
|
|
|
return $reflection->invokeArgs($service, $args);
|
|
}
|
|
}
|