42, 'device_id' => 'pi-01', 'camera_id' => 'cam-01', 'event_type' => 'fall', 'severity' => 'high', 'occurred_at' => 1_700_000_000, 'duration_s' => 3.0, 'metrics' => [], ]; } public function testMultiDownBodyCarriesTheDoNotEnterWarning(): void { $body = $this->channels()->body($this->event([ 'event_type' => 'multi_down', 'severity' => 'critical', 'metrics' => ['people' => 3], ])); self::assertStringContainsString('공기호흡기 없이 진입하지 마십시오', $body); self::assertStringContainsString('가스 누출', $body); self::assertStringContainsString('3명', $body, '몇 명이 쓰러졌는지가 본문에 있어야 한다'); self::assertStringContainsString('구조하러 들어간 사람', $body); } public function testFallFromHeightBodyWarnsAgainstMovingTheCasualty(): void { $body = $this->channels()->body($this->event([ 'event_type' => 'fall_from_height', 'severity' => 'critical', ])); self::assertStringContainsString('척추', $body); self::assertStringContainsString('옮기지 마십시오', $body); } public function testOrdinaryFallGetsNoExtraGuidance(): void { // 모든 알림에 경고가 붙으면 경고가 의미를 잃는다. $body = $this->channels()->body($this->event()); self::assertStringNotContainsString('공기호흡기', $body); self::assertStringNotContainsString('척추', $body); } public function testSubjectsUseKoreanLabelsForTheNewTypes(): void { self::assertStringContainsString('추락', $this->channels()->subject($this->event(['event_type' => 'fall_from_height']))); self::assertStringContainsString('동시 다발 쓰러짐', $this->channels()->subject($this->event(['event_type' => 'multi_down']))); } }