Files
nat-as-server/tests/Support/ApiTestCase.php
tom.hempel 06fc134299
Some checks failed
Tests / test (push) Has been cancelled
just testing the environment
2026-05-20 07:10:08 +02:00

126 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Support;
use PHPUnit\Framework\TestCase;
use QdbHttpResponse;
/**
* In-process API tests via qdb_dispatch_api_request().
*
* Error envelopes:
* - Handlers: { ok: false, error: { code, message } } — use assertError()
* - Auth middleware (require_valid_token, require_role): { error: "message" } — use assertLegacyAuthError()
*/
abstract class ApiTestCase extends TestCase
{
protected ?string $bearerToken = null;
protected function setUp(): void
{
parent::setUp();
DatabaseFixture::forTests()->reset();
$this->bearerToken = null;
unset($GLOBALS['__TEST_JSON_BODY']);
$_GET = [];
$_POST = [];
}
/**
* @return array{status: int, body: array<string, mixed>, raw: string}
*/
protected function api(
string $method,
string $route,
?array $jsonBody = null,
?string $token = null,
array $query = [],
): array {
$_GET = $query;
$_POST = [];
$_SERVER['REQUEST_METHOD'] = strtoupper($method);
$_SERVER['REQUEST_URI'] = '/api/' . ltrim($route, '/');
$_SERVER['SCRIPT_NAME'] = '/api/index.php';
$_SERVER['HTTP_AUTHORIZATION'] = ($token ?? $this->bearerToken)
? 'Bearer ' . ($token ?? $this->bearerToken)
: '';
if ($jsonBody !== null) {
$GLOBALS['__TEST_JSON_BODY'] = json_encode($jsonBody, JSON_THROW_ON_ERROR);
} else {
unset($GLOBALS['__TEST_JSON_BODY']);
}
ob_start();
$status = 200;
$body = [];
try {
require_once dirname(__DIR__, 2) . '/api/dispatch.php';
qdb_dispatch_api_request();
} catch (QdbHttpResponse $e) {
$status = $e->status;
$body = $e->body;
}
$raw = (string) ob_get_clean();
if ($raw !== '' && $body === []) {
$decoded = json_decode($raw, true);
if (is_array($decoded)) {
$body = $decoded;
}
}
if ($body === [] && $raw !== '') {
$body = ['_raw' => $raw];
}
if (!isset($body['ok']) && isset($body['error'])) {
// legacy auth envelope — body kept as-is
} elseif ($status === 200 && !isset($body['ok']) && $raw === '') {
$status = http_response_code() ?: 200;
}
return ['status' => $status, 'body' => $body, 'raw' => $raw];
}
/**
* @return array{status: int, body: array<string, mixed>, raw: string}
*/
protected function loginAs(string $username, string $password = DatabaseFixture::PASSWORD): array
{
$res = $this->api('POST', 'auth/login', [
'username' => $username,
'password' => $password,
]);
if (($res['body']['ok'] ?? false) === true) {
$this->bearerToken = $res['body']['data']['token'] ?? null;
}
return $res;
}
protected function assertOk(array $response): void
{
$this->assertTrue($response['body']['ok'] ?? false, $response['raw'] ?: json_encode($response['body']));
}
protected function assertError(array $response, ?string $code = null): void
{
$this->assertFalse($response['body']['ok'] ?? true);
if ($code !== null) {
$this->assertSame($code, $response['body']['error']['code'] ?? null);
}
}
protected function assertLegacyAuthError(array $response, int $status, string $message): void
{
$this->assertSame($status, $response['status']);
$this->assertSame($message, $response['body']['error'] ?? null);
}
}