set('user_id', 1); if ($site !== null) $s->set('site_scope', $site); return $s; } private function repo(): InMemoryEventRepository { $r = new InMemoryEventRepository(); $now = (float)time(); // cam-1 zone_warning: 3 events, 2 FP-tagged $a = $r->insert(['camera_id' => 'cam-1', 'event_type' => 'zone_warning', 'severity' => 'warning', 'site' => 'a', 'occurred_at' => $now]); $b = $r->insert(['camera_id' => 'cam-1', 'event_type' => 'zone_warning', 'severity' => 'warning', 'site' => 'a', 'occurred_at' => $now]); $r->insert(['camera_id' => 'cam-1', 'event_type' => 'zone_warning', 'severity' => 'warning', 'site' => 'a', 'occurred_at' => $now]); $r->markFalsePositive($a, 'u'); $r->markFalsePositive($b, 'u'); // cam-2 fall on another site: 1 event, 1 FP $c = $r->insert(['camera_id' => 'cam-2', 'event_type' => 'fall', 'severity' => 'high', 'site' => 'b', 'occurred_at' => $now]); $r->markFalsePositive($c, 'u'); // cam-3: events but no FP tags -> not in the report $r->insert(['camera_id' => 'cam-3', 'event_type' => 'fall', 'severity' => 'high', 'site' => 'a', 'occurred_at' => $now]); return $r; } public function testRequiresLogin(): void { $c = new FpStatsController($this->repo(), new ArraySessionStore()); $this->assertSame(401, $c->json(new Request('GET', '/api/fp-stats', [], '', [], []))->status()); } public function testAggregatesPerCameraAndType(): void { $c = new FpStatsController($this->repo(), $this->sess()); $data = json_decode($c->json(new Request('GET', '/api/fp-stats', [], '', [], []))->body(), true); $this->assertSame(30, $data['days']); $this->assertCount(2, $data['stats']); // cam-3 (no FP) excluded $this->assertSame(['camera_id' => 'cam-1', 'event_type' => 'zone_warning', 'total' => 3, 'fp' => 2], $data['stats'][0]); // sorted by fp desc } public function testSiteScopeFiltersStats(): void { $c = new FpStatsController($this->repo(), $this->sess('a')); $data = json_decode($c->json(new Request('GET', '/api/fp-stats', [], '', [], []))->body(), true); $this->assertCount(1, $data['stats']); $this->assertSame('cam-1', $data['stats'][0]['camera_id']); } }