shouldReceive('getConfig')->with('semester')->andReturn('Fall'); $config->shouldReceive('getConfig')->with('school_year')->andReturn('2025-2026'); return new AttendanceNotificationWorkflowService( $student, $studentClass, $attendanceData, $tracking, $config, $mailer, $rules, $parents, $composer, $log ); } public function test_send_auto_emails_returns_empty_summary_when_no_auto_email_violations(): void { $service = $this->makeService(); $result = $service->sendAutoEmails([ ['action' => 'team_notify'], ]); $this->assertTrue($result['success']); $this->assertSame(0, $result['sent']); $this->assertSame(0, $result['skipped']); $this->assertSame(0, $result['errors']); } public function test_send_email_manual_returns_failure_when_all_sends_fail(): void { $mailer = Mockery::mock(AttendanceMailerService::class); $mailer->shouldReceive('send')->andReturn(false); $parents = Mockery::mock(AttendanceParentLookupService::class); $parents->shouldReceive('getSecondaryParentForStudent')->andReturn(null); $composer = Mockery::mock(AttendanceEmailComposerService::class); $composer->shouldReceive('normalizeBodyToHtml')->andReturn('
Hello
'); $composer->shouldReceive('renderWithEmailLayout')->andReturn('Hello'); $log = Mockery::mock(AttendanceNotificationLogService::class); $log->shouldReceive('logNotification')->atLeast()->once(); $service = $this->makeService( mailer: $mailer, parents: $parents, composer: $composer, log: $log ); $result = $service->sendEmailManual([ 'student_id' => 10, 'to' => 'parent@example.com', 'subject' => 'Test', 'body_html' => 'Hello', 'code' => 'ABS_1', 'incident_date' => '2026-03-01', ], ['2026-03-01']); $this->assertFalse($result['success']); $this->assertSame(500, $result['status']); } }