'pi-1', 'camera_id' => 'cam-1', 'event_type' => 'fall', 'severity' => 'high', 'occurred_at' => 1000.0, 'snapshots' => ['aGk=']]; } public function testAcceptsValid(): void { $r = EventValidator::validate($this->valid()); $this->assertTrue($r['ok'], implode(',', $r['errors'])); $this->assertSame('fall', $r['clean']['event_type']); } public function testRejectsOverlongIds(): void { // An overlong id must be a 400 (invalid), not a MySQL 'Data too long' 500 that the edge // then retries forever. Columns: device_id/camera_id VARCHAR(64), zone_id CHAR(32). $long = $this->valid(); $long['device_id'] = str_repeat('x', 65); $this->assertFalse(EventValidator::validate($long)['ok']); $cam = $this->valid(); $cam['camera_id'] = str_repeat('y', 65); $this->assertFalse(EventValidator::validate($cam)['ok']); $zone = $this->valid(); $zone['zone_id'] = str_repeat('z', 33); $this->assertFalse(EventValidator::validate($zone)['ok']); // a normal-length id still passes $ok = $this->valid(); $ok['device_id'] = str_repeat('x', 64); $this->assertTrue(EventValidator::validate($ok)['ok']); } public function testRejectsUnknownEventType(): void { $p = $this->valid(); $p['event_type'] = 'explode'; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsUnknownSeverity(): void { $p = $this->valid(); $p['severity'] = 'ULTRA'; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsMissingRequired(): void { $p = $this->valid(); unset($p['device_id']); $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsTooManySnapshots(): void { $p = $this->valid(); $p['snapshots'] = ['a', 'b', 'c', 'd']; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsNonNumericOccurredAt(): void { $p = $this->valid(); $p['occurred_at'] = ['bad']; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsNonStringDeviceId(): void { $p = $this->valid(); $p['device_id'] = ['x']; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsNonArraySnapshots(): void { $p = $this->valid(); $p['snapshots'] = 'notarray'; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsNonStringSnapshotItem(): void { $p = $this->valid(); $p['snapshots'] = [123]; $this->assertFalse(EventValidator::validate($p)['ok']); } public function testRejectsNonStringZoneId(): void { $p = $this->valid(); $p['zone_id'] = ['z']; $this->assertFalse(EventValidator::validate($p)['ok']); } }