5, 'processed' => '3', 'failed' => 0, 'bogus_key' => 99, ]); expect($result)->toBe([ 'total' => 5, 'processed' => 3, 'failed' => 0, ]); }); it('strips empty string keys and non-numeric values', function () { $result = SummaryCountsNormalizer::normalize([ '' => 1, 'total' => 'not-a-number', 'succeeded' => 10, ]); expect($result)->toBe(['succeeded' => 10]); }); it('renders summary line with only non-zero values', function () { $line = SummaryCountsNormalizer::renderSummaryLine([ 'report_created' => 0, 'report_deduped' => 1, 'findings_created' => 0, 'findings_unchanged' => 10, 'alert_events_produced' => 0, ]); expect($line)->toBe('Report deduped: 1 · Findings unchanged: 10'); }); it('returns null when all values are zero', function () { $line = SummaryCountsNormalizer::renderSummaryLine([ 'report_created' => 0, 'findings_created' => 0, ]); expect($line)->toBeNull(); }); it('returns null for empty array', function () { expect(SummaryCountsNormalizer::renderSummaryLine([]))->toBeNull(); }); it('humanizes snake_case keys to Title case', function () { $line = SummaryCountsNormalizer::renderSummaryLine([ 'high' => 3, 'alert_events_produced' => 2, ]); expect($line)->toBe('High: 3 · Alert events produced: 2'); });