Keep configured auth transports when faking an actor (#91)

Assisted-By: Claude Fable 5.1
Co-authored-by: roxblnfk <roxblnfk@ya.ru>
This commit is contained in:
dualfrozandroxblnfk committed 2026-09-21 18:30:28 +04:00
1 parent fdcc6b7728
commit 0171b86dd8
4 files changed
+176 -3

No files matched your search

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Spiral\Testing\Tests\App\Bootloader;
use Spiral\Auth\Transport\HeaderTransport;
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Bootloader\Auth\HttpAuthBootloader;
/**
* Registers an auth transport under a name that does not exist in the default auth config.
*/
final class CustomAuthTransportBootloader extends Bootloader
{
public const TRANSPORT = 'custom';
public function defineDependencies(): array
{
return [HttpAuthBootloader::class];
}
public function init(HttpAuthBootloader $auth): void
{
$auth->addTransport(self::TRANSPORT, new HeaderTransport(header: 'X-Custom-Token'));
}
}
@@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace Spiral\Testing\Tests\Http;
use Spiral\Auth\Middleware\AuthMiddleware;
use Spiral\Auth\Middleware\AuthTransportMiddleware;
use Spiral\Auth\TransportRegistry;
use Spiral\Core\Container\Autowire;
use Spiral\Testing\Tests\App\Bootloader\CustomAuthTransportBootloader;
use Spiral\Testing\Tests\Http\Stub\ActorReportingMiddleware;
use Spiral\Testing\Tests\TestCase;
final class FakeHttpAuthTransportTest extends TestCase
{
private const HEADER_AUTH = 'auth.header';
private const CUSTOM_AUTH = 'auth.custom';
public function defineBootloaders(): array
{
return [...parent::defineBootloaders(), CustomAuthTransportBootloader::class];
}
public function testCustomTransportIsConfigured(): void
{
$transports = $this->getContainer()->get(TransportRegistry::class)->getTransports();
$this->assertArrayHasKey(CustomAuthTransportBootloader::TRANSPORT, $transports);
}
public function testActorIsAuthenticatedThroughNamedTransport(): void
{
$actor = new \stdClass();
$response = $this->fakeHttp()
->withActor($actor)
->withMiddleware(ActorReportingMiddleware::class, self::HEADER_AUTH)
->get('/get/query-params');
$response->assertOk();
$response->assertBodySame($actor::class);
}
public function testActorIsAuthenticatedThroughCustomTransport(): void
{
$actor = new \stdClass();
$response = $this->fakeHttp()
->withActor($actor)
->withMiddleware(ActorReportingMiddleware::class, self::CUSTOM_AUTH)
->get('/get/query-params');
$response->assertOk();
$response->assertBodySame($actor::class);
}
public function testActorIsAuthenticatedThroughEveryTransport(): void
{
$actor = new \stdClass();
$response = $this->fakeHttp()
->withActor($actor)
->withMiddleware(ActorReportingMiddleware::class, AuthMiddleware::class)
->get('/get/query-params');
$response->assertOk();
$response->assertBodySame($actor::class);
}
public function testRequestWithoutActorStaysUnauthenticated(): void
{
$response = $this->fakeHttp()
->withMiddleware(ActorReportingMiddleware::class, self::CUSTOM_AUTH)
->get('/get/query-params');
$response->assertOk();
$response->assertBodySame(ActorReportingMiddleware::NO_ACTOR);
}
protected function setUp(): void
{
parent::setUp();
$binder = $this->getContainer()->getBinder('http');
$binder->bind(
self::HEADER_AUTH,
new Autowire(AuthTransportMiddleware::class, ['transportName' => 'header']),
);
$binder->bind(
self::CUSTOM_AUTH,
new Autowire(AuthTransportMiddleware::class, ['transportName' => CustomAuthTransportBootloader::TRANSPORT]),
);
}
}
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Spiral\Testing\Tests\Http\Stub;
use Nyholm\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Spiral\Auth\AuthContextInterface;
use Spiral\Auth\Middleware\AuthMiddleware;
final class ActorReportingMiddleware implements MiddlewareInterface
{
public const NO_ACTOR = 'guest';
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$context = $request->getAttribute(AuthMiddleware::ATTRIBUTE);
$actor = $context instanceof AuthContextInterface ? $context->getActor() : null;
return new Response(200, body: $actor === null ? self::NO_ACTOR : $actor::class);
}
}