Add tests for ApiAuthController (JWT) and ApiDocController (doc/spec/insomnia)
ApiAuthControllerTest (7 unit tests): - verifyJwt valid token, expired token, invalid signature, wrong email - Malformed token, too few parts, empty payload ApiDocControllerTest (5 WebTestCase tests): - /api/doc returns success with env-switcher - /api/doc/spec.json returns 5 sections array - /api/doc/insomnia.json downloads with correct format and resources - Insomnia export contains workspace/environment/request_group/request - Login request has afterResponseScript for jwt_token auto-store Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
90
tests/Controller/Api/ApiAuthControllerTest.php
Normal file
90
tests/Controller/Api/ApiAuthControllerTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller\Api;
|
||||
|
||||
use App\Controller\Api\ApiAuthController;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ApiAuthControllerTest extends TestCase
|
||||
{
|
||||
private const SECRET = 'test_secret_key_for_jwt';
|
||||
|
||||
private function generateToken(array $payloadOverrides = []): string
|
||||
{
|
||||
$header = $this->base64UrlEncode(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
|
||||
$payload = array_merge([
|
||||
'userId' => 42,
|
||||
'email' => 'orga@test.com',
|
||||
'roles' => ['ROLE_ORGANIZER'],
|
||||
'iat' => time(),
|
||||
'exp' => time() + 86400,
|
||||
], $payloadOverrides);
|
||||
$payloadB64 = $this->base64UrlEncode(json_encode($payload));
|
||||
$signature = $this->base64UrlEncode(hash_hmac('sha256', $header.'.'.$payloadB64, self::SECRET, true));
|
||||
|
||||
return $header.'.'.$payloadB64.'.'.$signature;
|
||||
}
|
||||
|
||||
private function base64UrlEncode(string $data): string
|
||||
{
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
public function testVerifyJwtValid(): void
|
||||
{
|
||||
$token = $this->generateToken();
|
||||
$result = ApiAuthController::verifyJwt($token, 'orga@test.com', self::SECRET);
|
||||
|
||||
self::assertSame(42, $result['userId']);
|
||||
self::assertFalse($result['expired']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtExpired(): void
|
||||
{
|
||||
$token = $this->generateToken(['exp' => time() - 100]);
|
||||
$result = ApiAuthController::verifyJwt($token, 'orga@test.com', self::SECRET);
|
||||
|
||||
self::assertSame(42, $result['userId']);
|
||||
self::assertTrue($result['expired']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtInvalidSignature(): void
|
||||
{
|
||||
$token = $this->generateToken();
|
||||
$result = ApiAuthController::verifyJwt($token, 'orga@test.com', 'wrong_secret');
|
||||
|
||||
self::assertNull($result['userId']);
|
||||
self::assertFalse($result['expired']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtWrongEmail(): void
|
||||
{
|
||||
$token = $this->generateToken();
|
||||
$result = ApiAuthController::verifyJwt($token, 'other@test.com', self::SECRET);
|
||||
|
||||
self::assertNull($result['userId']);
|
||||
self::assertFalse($result['expired']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtMalformedToken(): void
|
||||
{
|
||||
$result = ApiAuthController::verifyJwt('not.a.valid.token.at.all', 'orga@test.com', self::SECRET);
|
||||
self::assertNull($result['userId']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtTooFewParts(): void
|
||||
{
|
||||
$result = ApiAuthController::verifyJwt('only.two', 'orga@test.com', self::SECRET);
|
||||
self::assertNull($result['userId']);
|
||||
}
|
||||
|
||||
public function testVerifyJwtEmptyPayload(): void
|
||||
{
|
||||
$header = $this->base64UrlEncode(json_encode(['alg' => 'HS256']));
|
||||
$payloadB64 = $this->base64UrlEncode('');
|
||||
$signature = $this->base64UrlEncode(hash_hmac('sha256', $header.'.'.$payloadB64, self::SECRET, true));
|
||||
|
||||
$result = ApiAuthController::verifyJwt($header.'.'.$payloadB64.'.'.$signature, 'orga@test.com', self::SECRET);
|
||||
self::assertNull($result['userId']);
|
||||
}
|
||||
}
|
||||
78
tests/Controller/ApiDocControllerTest.php
Normal file
78
tests/Controller/ApiDocControllerTest.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class ApiDocControllerTest extends WebTestCase
|
||||
{
|
||||
public function testDocPageReturnsSuccess(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/api/doc');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertSelectorExists('#env-switcher');
|
||||
}
|
||||
|
||||
public function testSpecJsonReturnsJson(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/api/doc/spec.json');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
$data = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertIsArray($data);
|
||||
self::assertCount(5, $data);
|
||||
self::assertSame('Authentification', $data[0]['name']);
|
||||
}
|
||||
|
||||
public function testInsomniaExportDownloads(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/api/doc/insomnia.json');
|
||||
|
||||
self::assertResponseIsSuccessful();
|
||||
self::assertStringContainsString('attachment', $client->getResponse()->headers->get('Content-Disposition'));
|
||||
|
||||
$data = json_decode($client->getResponse()->getContent(), true);
|
||||
self::assertSame('export', $data['_type']);
|
||||
self::assertSame(4, $data['__export_format']);
|
||||
self::assertNotEmpty($data['resources']);
|
||||
}
|
||||
|
||||
public function testInsomniaContainsWorkspaceAndEnv(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/api/doc/insomnia.json');
|
||||
|
||||
$data = json_decode($client->getResponse()->getContent(), true);
|
||||
$types = array_column($data['resources'], '_type');
|
||||
|
||||
self::assertContains('workspace', $types);
|
||||
self::assertContains('environment', $types);
|
||||
self::assertContains('request_group', $types);
|
||||
self::assertContains('request', $types);
|
||||
}
|
||||
|
||||
public function testInsomniaLoginHasAfterResponseScript(): void
|
||||
{
|
||||
$client = static::createClient();
|
||||
$client->request('GET', '/api/doc/insomnia.json');
|
||||
|
||||
$data = json_decode($client->getResponse()->getContent(), true);
|
||||
$requests = array_filter($data['resources'], fn ($r) => 'request' === ($r['_type'] ?? ''));
|
||||
|
||||
$loginReq = null;
|
||||
foreach ($requests as $req) {
|
||||
if (str_contains($req['url'] ?? '', '/api/auth/login') && !str_contains($req['url'] ?? '', 'sso')) {
|
||||
$loginReq = $req;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self::assertNotNull($loginReq);
|
||||
self::assertArrayHasKey('afterResponseScript', $loginReq);
|
||||
self::assertStringContainsString('jwt_token', $loginReq['afterResponseScript']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user