Nach dem Anlegen/Bearbeiten eines Projekts im Konfig-Dialog prueft ein neuer Endpunkt
(POST /api/v1/repo-configs/{id}/check), ob fds2610-bot dort Schreibrechte hat und ein
aktiver Webhook auf diese monitor-Instanz zeigt. Das Ergebnis erscheint als gruener Haken
bzw. rotes Kreuz rechts neben den Bearbeiten-/Loeschen-Symbolen, mit Tooltip zum geprueften
Service bzw. zur Fehlerursache.
151 lines
5.6 KiB
PHP
151 lines
5.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Monitor\Api\Tests\Controller;
|
|
|
|
use Monitor\Api\Controller\RepoConfigController;
|
|
use Monitor\Api\Db\Database;
|
|
use Monitor\Api\Http\NotFoundException;
|
|
use Monitor\Api\Http\Request;
|
|
use Monitor\Api\Repository\RepoConfigRepository;
|
|
use Monitor\Api\Repository\TicketRepository;
|
|
use Monitor\Api\Sync\CodebergClient;
|
|
use Monitor\Api\Sync\RepoHealthChecker;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
final class RepoConfigControllerTest extends TestCase
|
|
{
|
|
private RepoConfigController $controller;
|
|
private TicketRepository $tickets;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$db = Database::inMemory();
|
|
$db->pdo()->exec('DELETE FROM repo_configs');
|
|
$db->pdo()->exec('DELETE FROM tickets');
|
|
$this->tickets = new TicketRepository($db);
|
|
$healthChecker = new RepoHealthChecker(new class implements CodebergClient {
|
|
public function listIssues(string $owner, string $repo, string $state): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
public function repoPermissions(string $owner, string $repo): array
|
|
{
|
|
return ['push' => true];
|
|
}
|
|
|
|
public function listWebhooks(string $owner, string $repo): array
|
|
{
|
|
return [['active' => true, 'url' => 'https://monitor.example.org/api/v1/webhooks/codeberg', 'content_type' => 'json']];
|
|
}
|
|
});
|
|
$this->controller = new RepoConfigController(new RepoConfigRepository($db), $this->tickets, $healthChecker);
|
|
}
|
|
|
|
public function testIndexReturnsEmptyListInitially(): void
|
|
{
|
|
$response = $this->controller->index(Request::create('GET', '/api/v1/repo-configs'));
|
|
|
|
self::assertSame(200, $response->status);
|
|
self::assertSame([], $response->body()['repos']);
|
|
}
|
|
|
|
public function testCreateReturns201WithNewRepo(): void
|
|
{
|
|
$response = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#fbca04',
|
|
]));
|
|
|
|
self::assertSame(201, $response->status);
|
|
self::assertSame('fds2610', $response->body()['repo']['owner']);
|
|
}
|
|
|
|
public function testCreateRejectsInvalidColorWith422(): void
|
|
{
|
|
$response = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => 'nope',
|
|
]));
|
|
|
|
self::assertSame(422, $response->status);
|
|
}
|
|
|
|
public function testUpdateReturnsUpdatedRepo(): void
|
|
{
|
|
$created = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#fbca04',
|
|
]))->body()['repo'];
|
|
|
|
$response = $this->controller->update(
|
|
Request::create('PATCH', '/api/v1/repo-configs/' . $created['id'], body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#000000',
|
|
]),
|
|
['id' => (string) $created['id']]
|
|
);
|
|
|
|
self::assertSame(200, $response->status);
|
|
self::assertSame('#000000', $response->body()['repo']['color']);
|
|
}
|
|
|
|
public function testDeleteReturnsDeletedTrue(): void
|
|
{
|
|
$created = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#fbca04',
|
|
]))->body()['repo'];
|
|
|
|
$response = $this->controller->delete(
|
|
Request::create('DELETE', '/api/v1/repo-configs/' . $created['id']),
|
|
['id' => (string) $created['id']]
|
|
);
|
|
|
|
self::assertSame(200, $response->status);
|
|
self::assertTrue($response->body()['deleted']);
|
|
}
|
|
|
|
public function testDeleteRemovesTicketsOfTheProjectFromTheKanban(): void
|
|
{
|
|
$created = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#fbca04',
|
|
]))->body()['repo'];
|
|
|
|
$orphaned = $this->tickets->create(['title' => 'A', 'repo' => 'fds2610/monitor']);
|
|
$unrelated = $this->tickets->create(['title' => 'B', 'repo' => 'fds2610/anderes-projekt']);
|
|
$manual = $this->tickets->create(['title' => 'C']);
|
|
|
|
$this->controller->delete(
|
|
Request::create('DELETE', '/api/v1/repo-configs/' . $created['id']),
|
|
['id' => (string) $created['id']]
|
|
);
|
|
|
|
self::assertNull($this->tickets->find((int) $orphaned['id']));
|
|
self::assertNotNull($this->tickets->find((int) $unrelated['id']));
|
|
self::assertNotNull($this->tickets->find((int) $manual['id']));
|
|
}
|
|
|
|
public function testCheckReturnsWriteAccessAndWebhookResults(): void
|
|
{
|
|
$created = $this->controller->create(Request::create('POST', '/api/v1/repo-configs', body: [
|
|
'owner' => 'fds2610', 'repo' => 'monitor', 'color' => '#fbca04',
|
|
]))->body()['repo'];
|
|
|
|
$response = $this->controller->check(
|
|
Request::create('POST', '/api/v1/repo-configs/' . $created['id'] . '/check'),
|
|
['id' => (string) $created['id']]
|
|
);
|
|
|
|
self::assertSame(200, $response->status);
|
|
self::assertTrue($response->body()['checks']['write_access']['ok']);
|
|
self::assertTrue($response->body()['checks']['webhook']['ok']);
|
|
}
|
|
|
|
public function testCheckThrowsNotFoundForUnknownRepo(): void
|
|
{
|
|
$this->expectException(NotFoundException::class);
|
|
|
|
$this->controller->check(
|
|
Request::create('POST', '/api/v1/repo-configs/999/check'),
|
|
['id' => '999']
|
|
);
|
|
}
|
|
}
|