path = sys_get_temp_dir() . '/monitor-webhook-' . uniqid() . '/sync-requested'; $this->hooksPath = sys_get_temp_dir() . '/monitor-webhook-hooks-' . uniqid() . '/hooks-count'; $this->trigger = new SyncTrigger($this->path); $this->hooks = new HookCounter($this->hooksPath); } protected function tearDown(): void { if (file_exists($this->path)) { unlink($this->path); } if (is_dir(dirname($this->path))) { rmdir(dirname($this->path)); } if (file_exists($this->hooksPath)) { unlink($this->hooksPath); } if (is_dir(dirname($this->hooksPath))) { rmdir(dirname($this->hooksPath)); } } public function testIssueEventRequestsASync(): void { $controller = new WebhookController($this->trigger, $this->hooks); $response = $controller->codeberg($this->request('issues')); self::assertSame(202, $response->status); self::assertTrue($this->trigger->consume()); } /** * Codeberg schickt beim Anlegen des Webhooks ein "ping" zum Testen der Zustellung - das * ist keine Issue-Aenderung und soll keinen Codeberg-Request ausloesen. */ public function testPingIsAnsweredWithoutRequestingASync(): void { $controller = new WebhookController($this->trigger, $this->hooks); $response = $controller->codeberg($this->request('ping')); self::assertSame(200, $response->status); self::assertFalse($this->trigger->consume()); } /** Unbekannte Events loesen einen Sync aus - lieber einmal zu viel als einen verpassten. */ public function testUnknownEventStillRequestsASync(): void { $controller = new WebhookController($this->trigger, $this->hooks); $response = $controller->codeberg($this->request('issue_label')); self::assertSame(202, $response->status); self::assertTrue($this->trigger->consume()); } /** * Hooks-KPI (Issue #38): jede angenommene Zustellung zaehlt, auch "ping" - der Endpunkt * meldet nur, dass etwas empfangen wurde, nicht ob es fachlich relevant war. */ public function testCodebergIncrementsHookCounterRegardlessOfEventType(): void { $controller = new WebhookController($this->trigger, $this->hooks); $controller->codeberg($this->request('issues')); $controller->codeberg($this->request('ping')); $controller->codeberg($this->request('issue_label')); self::assertSame(3, $this->hooks->count()); } public function testStatsReturnsCurrentHookCount(): void { $controller = new WebhookController($this->trigger, $this->hooks); $controller->codeberg($this->request('issues')); $controller->codeberg($this->request('issues')); $response = $controller->stats(Request::create('GET', '/api/v1/webhooks/stats')); self::assertSame(200, $response->status); self::assertSame(2, $response->body()['count']); } public function testStatsReturnsZeroWithoutAnyReceivedWebhook(): void { $controller = new WebhookController($this->trigger, $this->hooks); $response = $controller->stats(Request::create('GET', '/api/v1/webhooks/stats')); self::assertSame(0, $response->body()['count']); } private function request(string $event): Request { return Request::create( 'POST', '/api/v1/webhooks/codeberg', [], [], ['X-Gitea-Event' => $event], '{}' ); } }