index/tests/RouterTest.php

167 lines
6.7 KiB
PHP
Raw Normal View History

2022-09-13 15:13:11 +02:00
<?php
// RouterTest.php
// Created: 2022-01-20
// Updated: 2025-03-02
2022-09-13 15:13:11 +02:00
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use Index\Http\{HttpHeaders,HttpRequest,HttpUri,NullStream};
use Index\Http\Routing\{Filter,Route,Router,RouteHandler,RouteHandlerCommon};
2022-09-13 15:13:11 +02:00
/**
2024-03-30 16:24:34 +00:00
* This test isn't super representative of the current functionality
* it mostly just does the same tests that were done against the previous implementation
2022-09-13 15:13:11 +02:00
*/
#[CoversClass(Filter::class)]
#[CoversClass(Route::class)]
#[CoversClass(Router::class)]
#[CoversClass(RouteHandler::class)]
#[CoversClass(RouteHandlerCommon::class)]
2022-09-13 15:13:11 +02:00
final class RouterTest extends TestCase {
public function testRouter(): void {
$router1 = new Router;
2024-03-30 16:24:34 +00:00
$router1->route('GET', '/', fn() => 'get');
$router1->route('POST', '/', fn() => 'post');
$router1->route('DELETE', '/', fn() => 'delete');
$router1->route('PATCH', '/', fn() => 'patch');
$router1->route('PUT', '/', fn() => 'put');
$router1->route('CUSTOM', '/', fn() => 'wacky');
2024-03-30 16:24:34 +00:00
$this->assertEquals('get', $router1->resolve('GET', '/')->dispatch([]));
$this->assertEquals('wacky', $router1->resolve('CUSTOM', '/')->dispatch([]));
$router1->filter('/', function() { /* this one intentionally does nothing */ });
2024-03-30 16:24:34 +00:00
// registration order should matter
$router1->filter('/deep', fn() => 'deep');
2024-03-30 16:24:34 +00:00
$postRoot = $router1->resolve('POST', '/');
$this->assertNull($postRoot->runFilters([]));
2024-03-30 16:24:34 +00:00
$this->assertEquals('post', $postRoot->dispatch([]));
$this->assertEquals('deep', $router1->resolve('GET', '/deep/nothing')->runFilters([]));
2024-03-30 16:24:34 +00:00
$router1->filter('/user/([A-Za-z0-9]+)/below', fn(string $user) => 'warioware below ' . $user);
2024-03-30 16:24:34 +00:00
$router1->route('GET', '/user/static', fn() => 'the static one');
$router1->route('GET', '/user/static/below', fn() => 'below the static one');
$router1->route('GET', '/user/([A-Za-z0-9]+)', fn(string $user) => $user);
$router1->route('GET', '/user/([A-Za-z0-9]+)/below', fn(string $user) => 'below ' . $user);
2024-03-30 16:24:34 +00:00
$this->assertEquals('below the static one', $router1->resolve('GET', '/user/static/below')->dispatch([]));
$getWariowareBelowFlashwave = $router1->resolve('GET', '/user/flashwave/below');
$this->assertEquals('warioware below flashwave', $getWariowareBelowFlashwave->runFilters([]));
2024-03-30 16:24:34 +00:00
$this->assertEquals('below flashwave', $getWariowareBelowFlashwave->dispatch([]));
$router2 = new Router;
$router2->filter('/', fn() => 'meow');
$router2->route('GET', '/rules', fn() => 'rules page');
$router2->route('GET', '/contact', fn() => 'contact page');
$router2->route('GET', '/25252', fn() => 'numeric test');
2024-03-30 16:24:34 +00:00
$getRules = $router2->resolve('GET', '/rules');
$this->assertEquals('meow', $getRules->runFilters([]));
2024-03-30 16:24:34 +00:00
$this->assertEquals('rules page', $getRules->dispatch([]));
$get25252 = $router2->resolve('GET', '/25252');
$this->assertEquals('meow', $get25252->runFilters([]));
2024-03-30 16:24:34 +00:00
$this->assertEquals('numeric test', $get25252->dispatch([]));
2022-09-13 15:13:11 +02:00
}
2023-09-07 22:08:31 +00:00
public function testAttribute(): void {
$router = new Router;
2024-10-02 02:09:21 +00:00
$handler = new class implements RouteHandler {
use RouteHandlerCommon;
2024-10-02 02:09:21 +00:00
#[Route('GET', '/')]
public function getIndex(): string {
2023-09-07 22:08:31 +00:00
return 'index';
}
#[Route('POST', '/avatar')]
public function postAvatar(): string {
2023-09-07 22:08:31 +00:00
return 'avatar';
}
#[Route('PUT', '/static')]
public static function putStatic(): string {
2023-09-07 22:08:31 +00:00
return 'static';
}
#[Route('GET', '/meow')]
#[Route('POST', '/meow')]
public function multiple(): string {
2023-09-07 22:08:31 +00:00
return 'meow';
}
2023-09-07 22:37:04 +00:00
#[Filter('/filter')]
public function useFilter(): string {
return 'this intercepts';
}
#[Route('GET', '/filter')]
public function getFilter(): string {
return 'this is intercepted';
}
public function hasNoAttr(): string {
2023-09-07 22:37:04 +00:00
return 'not a route';
}
2023-09-07 22:08:31 +00:00
};
$router->register($handler);
2024-03-30 16:24:34 +00:00
$this->assertFalse($router->resolve('GET', '/soap')->hasHandler());
$patchAvatar = $router->resolve('PATCH', '/avatar');
$this->assertFalse($patchAvatar->hasHandler());
$this->assertTrue(!empty($patchAvatar->supportedMethods));
$this->assertEquals(['POST'], $patchAvatar->supportedMethods);
2024-03-30 16:24:34 +00:00
$this->assertEquals('index', $router->resolve('GET', '/')->dispatch([]));
$this->assertEquals('avatar', $router->resolve('POST', '/avatar')->dispatch([]));
$this->assertEquals('static', $router->resolve('PUT', '/static')->dispatch([]));
$this->assertEquals('meow', $router->resolve('GET', '/meow')->dispatch([]));
$this->assertEquals('meow', $router->resolve('POST', '/meow')->dispatch([]));
// stopping on filter is the dispatcher's job
$getFilter = $router->resolve('GET', '/filter');
$this->assertEquals('this intercepts', $getFilter->runFilters([]));
$this->assertEquals('this is intercepted', $getFilter->dispatch([]));
2023-09-07 22:08:31 +00:00
}
public function testEEPROMSituation(): void {
$router = new Router;
$router->route('OPTIONS', '/uploads/([A-Za-z0-9\-_]+)(?:\.(t|json))?', function() {});
$router->route('GET', '/uploads/([A-Za-z0-9\-_]+)(?:\.(t|json))?', function() {});
$router->route('DELETE', '/uploads/([A-Za-z0-9\-_]+)', function() {});
$resolved = $router->resolve('DELETE', '/uploads/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
$this->assertEquals(['OPTIONS', 'GET', 'DELETE'], $resolved->supportedMethods);
}
2024-08-18 16:41:02 +00:00
public function testFilterInterceptionOnRoot(): void {
$router = new Router;
$router->filter('/', fn() => 'expected');
$router->route('GET', '/', fn() => 'unexpected');
$router->route('GET', '/test', fn() => 'also unexpected');
2024-08-18 16:41:02 +00:00
ob_start();
$router->dispatch(new HttpRequest('1.1', [], NullStream::instance(), [], 'GET', HttpUri::createUri('/'), [], []));
2024-08-18 16:41:02 +00:00
$this->assertEquals('expected', ob_get_clean());
ob_start();
$router->dispatch(new HttpRequest('1.1', [], NullStream::instance(), [], 'GET', HttpUri::createUri('/test'), [], []));
2024-08-18 16:41:02 +00:00
$this->assertEquals('expected', ob_get_clean());
ob_start();
$router->dispatch(new HttpRequest('1.1', [], NullStream::instance(), [], 'GET', HttpUri::createUri('/error'), [], []));
2024-08-18 16:41:02 +00:00
$this->assertEquals('expected', ob_get_clean());
}
2022-09-13 15:13:11 +02:00
}