<?php
declare(strict_types=1);
namespace GNexus\GAuth\Tests\Unit\Client;
use GNexus\GAuth\Client\GAuthClient;
use GNexus\GAuth\Config\GAuthConfig;
use GNexus\GAuth\Contract\RuntimeUserProviderInterface;
use GNexus\GAuth\Contract\TokenEndpointInterface;
use GNexus\GAuth\Contract\WebhookParserInterface;
use GNexus\GAuth\Contract\WebhookVerifierInterface;
use GNexus\GAuth\DTO\AuthenticatedUser;
use GNexus\GAuth\DTO\TokenSet;
use GNexus\GAuth\DTO\VerifiedWebhook;
use GNexus\GAuth\DTO\WebhookEvent;
use GNexus\GAuth\Support\InMemoryPkceStore;
use GNexus\GAuth\Support\InMemoryStateStore;
use PHPUnit\Framework\TestCase;
final class GAuthClientTest extends TestCase
{
public function testBuildAuthorizationRequestPersistsStateAndPkce(): void
{
$stateStore = new InMemoryStateStore();
$pkceStore = new InMemoryPkceStore();
$client = new GAuthClient(
config: new GAuthConfig(
baseUrl: 'https://auth.example.test',
clientId: 'billing',
clientSecret: 'secret',
redirectUri: 'https://billing.example.test/callback',
),
tokenEndpoint: new class implements TokenEndpointInterface
{
public function exchangeAuthorizationCode(string $code, string $pkceVerifier): TokenSet
{
return new TokenSet('a', 'b', 'Bearer', 900);
}
public function refreshToken(string $refreshToken): TokenSet
{
return new TokenSet('a', 'b', 'Bearer', 900);
}
public function revokeToken(string $token, ?string $tokenTypeHint = null): void
{
}
},
runtimeUserProvider: new class implements RuntimeUserProviderInterface
{
public function fetchUser(string $accessToken): AuthenticatedUser
{
return new AuthenticatedUser('1', 'user@example.test', true);
}
},
webhookVerifier: new class implements WebhookVerifierInterface
{
public function verify(string $rawBody, array $headers, string $secret): VerifiedWebhook
{
return new VerifiedWebhook($rawBody, []);
}
},
webhookParser: new class implements WebhookParserInterface
{
public function parse(string $rawBody): WebhookEvent
{
return new WebhookEvent('evt_1', 'webhook.test');
}
},
stateStore: $stateStore,
pkceStore: $pkceStore,
);
$request = $client->buildAuthorizationRequest('/dashboard', ['openid', 'profile']);
self::assertNotSame('', $request->state);
self::assertNotSame('', $request->pkceVerifier);
self::assertNotSame('', $request->pkceChallenge);
self::assertTrue($stateStore->has($request->state));
self::assertSame($request->pkceVerifier, $pkceStore->get($request->state));
self::assertStringContainsString('response_type=code', $request->authorizationUrl);
self::assertStringContainsString('client_id=billing', $request->authorizationUrl);
self::assertStringContainsString('scope=openid%20profile', $request->authorizationUrl);
self::assertStringContainsString('return_to=%2Fdashboard', $request->authorizationUrl);
}
}