This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\App\Services;
|
||||
|
||||
use App\Services\EmailService;
|
||||
use App\Services\EnrollmentRegistrationEmailService;
|
||||
use App\Services\EnrollmentTransitionService;
|
||||
use App\Support\Enrollment\DeliberationDecision;
|
||||
use CodeIgniter\Database\BaseBuilder;
|
||||
use CodeIgniter\Database\BaseConnection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class EnrollmentRegistrationEmailServiceTest extends TestCase
|
||||
{
|
||||
public function testPassedStudentUsesReEnrollmentOpeningLanguage(): void
|
||||
{
|
||||
$service = $this->service();
|
||||
|
||||
$evaluation = [
|
||||
'deliberation_decision' => DeliberationDecision::PASSED,
|
||||
'placement_status' => 'exit_required',
|
||||
'source_grade_name' => '8',
|
||||
'adult_student' => false,
|
||||
'blockers' => [
|
||||
'The student has passed the highest available grade and must follow the school completion or exit process.',
|
||||
'Registration for the new school year has not opened yet.',
|
||||
],
|
||||
];
|
||||
|
||||
$status = $this->invoke($service, 'registrationStatus', [$evaluation]);
|
||||
$message = $this->invoke($service, 'decisionMessage', ['Student Name', $evaluation, 'August 1, 2026', 'August 31, 2026']);
|
||||
$action = $this->invoke($service, 'requiredAction', [$evaluation, 'August 31, 2026']);
|
||||
|
||||
$this->assertSame('Eligible', $status);
|
||||
$this->assertStringContainsString('We are pleased to inform you that Student Name has successfully passed Grade 8.', $message);
|
||||
$this->assertStringContainsString('Re-enrollment for the new school year will open on August 1, 2026.', $message);
|
||||
$this->assertStringContainsString('Please make sure to re-enroll your child before August 31, 2026', $message);
|
||||
$this->assertStringContainsString('sign in to the parent portal', $message);
|
||||
$this->assertStringContainsString('Complete re-enrollment before August 31, 2026.', $action);
|
||||
$this->assertStringNotContainsString('Not Eligible', $status);
|
||||
$this->assertStringNotContainsString('Registration for the new school year has not opened yet', $message);
|
||||
$this->assertStringNotContainsString('Contact the school administration.', $action);
|
||||
}
|
||||
|
||||
public function testFinancialSectionIsHiddenWhenNothingIsDue(): void
|
||||
{
|
||||
$service = $this->service();
|
||||
|
||||
$html = $this->invoke($service, 'financialSection', [10, [
|
||||
'registration_fee' => 0,
|
||||
'tuition_due_at_registration' => 0,
|
||||
'mandatory_fees' => 0,
|
||||
], null]);
|
||||
|
||||
$this->assertSame('', $html);
|
||||
}
|
||||
|
||||
public function testFinancialSectionShowsWhenAnyAmountIsDue(): void
|
||||
{
|
||||
$service = $this->service();
|
||||
|
||||
$html = $this->invoke($service, 'financialSection', [10, [
|
||||
'registration_fee' => 25,
|
||||
'tuition_due_at_registration' => 0,
|
||||
'mandatory_fees' => 0,
|
||||
], null]);
|
||||
|
||||
$this->assertStringContainsString('Family Account Information', $html);
|
||||
$this->assertStringContainsString('Total currently due:</strong> $25.00', $html);
|
||||
}
|
||||
|
||||
public function testAutomaticDistributionPlacementShowsOnlyGrade(): void
|
||||
{
|
||||
$service = $this->service();
|
||||
|
||||
$placement = $this->invoke($service, 'placementText', [[
|
||||
'placement_status' => 'automatic_distribution_pending',
|
||||
'assigned_grade_name' => '9',
|
||||
]]);
|
||||
|
||||
$this->assertSame('Grade 9', $placement);
|
||||
}
|
||||
|
||||
public function testForceCannotSendWithoutAdminLaunchApproval(): void
|
||||
{
|
||||
$emailService = $this->createMock(EmailService::class);
|
||||
$emailService->expects($this->never())->method('send');
|
||||
$service = $this->service($this->dbWithNoRecipientFamilies(), $emailService);
|
||||
|
||||
$summary = $service->sendForSchoolYear([
|
||||
'name' => '2026-2027',
|
||||
'registration_launch_approved_at' => null,
|
||||
], null, false, true);
|
||||
|
||||
$this->assertSame(0, $summary['sent']);
|
||||
$this->assertSame(1, $summary['skipped']);
|
||||
$this->assertStringContainsString('not approved', implode(' ', $summary['messages']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<mixed> $args
|
||||
*/
|
||||
private function invoke(EnrollmentRegistrationEmailService $service, string $method, array $args): mixed
|
||||
{
|
||||
$reflection = new \ReflectionMethod($service, $method);
|
||||
$reflection->setAccessible(true);
|
||||
|
||||
return $reflection->invokeArgs($service, $args);
|
||||
}
|
||||
|
||||
private function service(?BaseConnection $db = null, ?EmailService $emailService = null): EnrollmentRegistrationEmailService
|
||||
{
|
||||
$db ??= $this->createMock(BaseConnection::class);
|
||||
|
||||
return new EnrollmentRegistrationEmailService(
|
||||
$db,
|
||||
new EnrollmentTransitionService($db),
|
||||
$emailService ?? $this->createMock(EmailService::class),
|
||||
);
|
||||
}
|
||||
|
||||
private function dbWithNoRecipientFamilies(): BaseConnection
|
||||
{
|
||||
$query = new class {
|
||||
public function getResultArray(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
$builder = $this->createMock(BaseBuilder::class);
|
||||
$builder->method('select')->willReturnSelf();
|
||||
$builder->method('where')->willReturnSelf();
|
||||
$builder->method('get')->willReturn($query);
|
||||
|
||||
$db = $this->createMock(BaseConnection::class);
|
||||
$db->method('table')->willReturn($builder);
|
||||
$db->method('fieldExists')->with('user_type', 'users')->willReturn(false);
|
||||
|
||||
return $db;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user