test(Router): cover default callback resolution through Synapsis
This commit is contained in:
@@ -8,7 +8,9 @@ use Libs\Request;
|
|||||||
use Libs\Router;
|
use Libs\Router;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
|
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
|
||||||
use PHPUnit\Framework\Attributes\Test;
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
|
use ReflectionClass;
|
||||||
use ReflectionProperty;
|
use ReflectionProperty;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
use TypeError;
|
use TypeError;
|
||||||
@@ -21,7 +23,10 @@ use TypeError;
|
|||||||
* negociacion por Accept entre representacion JSON y texto plano. Tambien la
|
* negociacion por Accept entre representacion JSON y texto plano. Tambien la
|
||||||
* frontera de Router::apply(): que toda excepcion de la cadena (middlewares,
|
* frontera de Router::apply(): que toda excepcion de la cadena (middlewares,
|
||||||
* callback final, notFound) llegue al $exceptionCallback deteniendo la
|
* callback final, notFound) llegue al $exceptionCallback deteniendo la
|
||||||
* ejecucion sin exit() y dejando intacto el flujo normal.
|
* ejecucion sin exit() y dejando intacto el flujo normal. Tambien que los
|
||||||
|
* valores por defecto declarados en las propiedades $notFoundCallback y
|
||||||
|
* $exceptionCallback (callables string) se resuelvan de punta a punta a
|
||||||
|
* traves de Synapsis::resolve() dentro de apply().
|
||||||
*/
|
*/
|
||||||
final class RouterTest extends TestCase
|
final class RouterTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -36,7 +41,7 @@ final class RouterTest extends TestCase
|
|||||||
$this->postBackup = $_POST;
|
$this->postBackup = $_POST;
|
||||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||||
unset($_SERVER['HTTP_ACCEPT']);
|
unset($_SERVER['HTTP_ACCEPT']);
|
||||||
http_response_code(200);
|
@http_response_code(200); // Ver tearDown: inofensivo mientras no haya un header('HTTP/...') activo.
|
||||||
$this->resetRouterState();
|
$this->resetRouterState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +50,11 @@ final class RouterTest extends TestCase
|
|||||||
$_SERVER = $this->serverBackup;
|
$_SERVER = $this->serverBackup;
|
||||||
$_GET = $this->getBackup;
|
$_GET = $this->getBackup;
|
||||||
$_POST = $this->postBackup;
|
$_POST = $this->postBackup;
|
||||||
http_response_code(200);
|
// El @ cubre el warning de PHP 8.5 ("...has no effect") que dispara
|
||||||
|
// cualquier http_response_code() posterior a un header('HTTP/...'),
|
||||||
|
// inevitable en el proceso aislado del test de notFound (el valor
|
||||||
|
// se aplica igualmente, como confirma el getter).
|
||||||
|
@http_response_code(200);
|
||||||
$this->resetRouterState();
|
$this->resetRouterState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +252,46 @@ final class RouterTest extends TestCase
|
|||||||
$this->assertSame(400, $caught[0]->getCode(), 'The status channel must survive custom exception types');
|
$this->assertSame(400, $caught[0]->getCode(), 'The status channel must survive custom exception types');
|
||||||
$this->assertFalse($finalRan, 'A Request that throws during DI resolution must stop the route');
|
$this->assertFalse($finalRan, 'A Request that throws during DI resolution must stop the route');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function declaredDefaultExceptionCallbackRendersThroughTheBoundary(): void
|
||||||
|
{
|
||||||
|
// Se fuerza el valor declarado en la clase, no el que reasigna
|
||||||
|
// resetRouterState(): es justo el camino property default ->
|
||||||
|
// Synapsis::resolve(string callable) que debe seguir funcionando.
|
||||||
|
Router::$exceptionCallback = (new ReflectionClass(Router::class))
|
||||||
|
->getDefaultProperties()['exceptionCallback'];
|
||||||
|
|
||||||
|
Router::get('/default-exception', function (): void {
|
||||||
|
throw new Exception('rendered by the default handler', 422);
|
||||||
|
});
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
Router::apply('/default-exception');
|
||||||
|
$output = ob_get_clean();
|
||||||
|
|
||||||
|
$this->assertSame(422, http_response_code(), 'The declared default handler must derive the status from the code');
|
||||||
|
$this->assertStringContainsString('rendered by the default handler', $output);
|
||||||
|
$this->assertStringContainsString('#0', $output, 'The declared default handler must render the plain text trace');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
#[RunInSeparateProcess]
|
||||||
|
public function declaredDefaultNotFoundCallbackRendersThe404Body(): void
|
||||||
|
{
|
||||||
|
Router::$notFoundCallback = (new ReflectionClass(Router::class))
|
||||||
|
->getDefaultProperties()['notFoundCallback'];
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
Router::apply('/no-such-route');
|
||||||
|
$output = ob_get_clean();
|
||||||
|
|
||||||
|
// Proceso aislado: defaultNotFound() emite header('HTTP/1.0 404 ...') y en
|
||||||
|
// PHP 8.5 eso hace que TODO http_response_code() posterior avise, sin forma
|
||||||
|
// de limpiar el estado en el mismo proceso. En CLI el header no toca
|
||||||
|
// http_response_code(), asi que la asercion util es el cuerpo renderizado.
|
||||||
|
$this->assertStringContainsString('Error 404 - Page Not Found', $output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||||
|
|||||||
Reference in New Issue
Block a user