buildTemplateContext( [ 'name' => 'John Doe', 'last_date' => '2026-03-01', ], [ 'parent_name' => 'Jane Doe', 'phone' => '555-1212', ] ); $this->assertSame('Jane Doe', $context['{{parent_name}}']); $this->assertSame('John Doe', $context['{{student_name}}']); $this->assertSame('2026-03-01', $context['{{incident_date}}']); $this->assertSame('555-1212', $context['{{voicemail_phone}}']); } public function test_render_template_uses_model_get_template(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $model->shouldReceive('getTemplate') ->once() ->with('ABS_1', 'default') ->andReturn([ 'subject' => 'Notice for {{student_name}}', 'body_html' => '
Date: {{incident_date}}
', ]); $service = new AttendanceEmailComposerService($model); $rendered = $service->renderTemplate('ABS_1', 'default', [ '{{student_name}}' => 'John Doe', '{{incident_date}}' => '2026-03-01', ]); $this->assertSame( ['Notice for John Doe', 'Date: 2026-03-01
'], $rendered ); } public function test_pick_variant_returns_override_when_present(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $service = new AttendanceEmailComposerService($model); $this->assertSame('custom_variant', $service->pickVariant('ABS_2', 'custom_variant')); } public function test_pick_variant_returns_no_answer_for_abs_2(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $service = new AttendanceEmailComposerService($model); $this->assertSame('no_answer', $service->pickVariant('ABS_2')); } public function test_pick_variant_returns_default_for_other_codes(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $service = new AttendanceEmailComposerService($model); $this->assertSame('default', $service->pickVariant('ABS_1')); } public function test_normalize_body_to_html_keeps_html_when_tags_present(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $service = new AttendanceEmailComposerService($model); $body = 'Hello
'; $this->assertSame($body, $service->normalizeBodyToHtml($body)); } public function test_normalize_body_to_html_converts_plain_text_to_br_html(): void { $model = Mockery::mock(AttendanceEmailTemplate::class); $service = new AttendanceEmailComposerService($model); $result = $service->normalizeBodyToHtml("Hello\nWorld"); $this->assertStringContainsString('Hello', $result); $this->assertStringContainsString('