diff --git a/src/Test/Controller/AdminControllerWebTestCase.php b/src/Test/Controller/AdminControllerWebTestCase.php index 32a6a19..ca22798 100644 --- a/src/Test/Controller/AdminControllerWebTestCase.php +++ b/src/Test/Controller/AdminControllerWebTestCase.php @@ -7,6 +7,9 @@ use DOMElement; use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA; use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface; +use Override; use Psl\Dict; use Psl\Iter; use Psl\Str; @@ -19,12 +22,11 @@ use Symfony\Component\HttpFoundation\Response; use function array_merge; -use function http_build_query; use function is_array; use function iterator_to_array; /** - * @template TCrudController + * @template TCrudController of CrudControllerInterface */ abstract class AdminControllerWebTestCase extends AdminWebTestCase { @@ -33,6 +35,9 @@ abstract class AdminControllerWebTestCase extends AdminWebTestCase */ abstract protected function controllerUnderTest(): string; + /** + * @return non-empty-string + */ abstract protected function actionName(): string; protected static function easyAdminRoutePath(): string @@ -64,22 +69,55 @@ protected function assertRequestGet( * @param array $queryParameters */ protected function prepareAdminUrl(array $queryParameters, string|null $fragment = null): string + { + if (! static::usePrettyUrls()) { + return $this->prepareLegacyAdminUrl($queryParameters, $fragment); + } + + return $this->generateAdminPrettyUrl( + dashboardFqcn: $this->dashboardControllerFqcn(), + crudControllerFqcn: $this->controllerUnderTest(), + actionName: $this->actionName(), + routeParameters: $this->prepareAdminUrlRouteParameters(), + queryParameters: $queryParameters, + fragment: $fragment, + ); + } + + /** + * @param array $queryParameters + */ + protected function prepareLegacyAdminUrl(array $queryParameters, string|null $fragment = null): string { return static::easyAdminRoutePath() . '?' . $this->prepareAdminUrlQueryParameters($queryParameters) . ($fragment ?? ''); } + /** + * @return array $routeParameters + */ + protected function prepareAdminUrlRouteParameters(): array + { + return []; + } + + /** @return class-string|null */ + protected function dashboardControllerFqcn(): string|null + { + return null; + } + /** * @param array $queryParameters */ + #[Override] protected function prepareAdminUrlQueryParameters(array $queryParameters): string { - $queryParameters[EA::CRUD_CONTROLLER_FQCN] ??= $this->controllerUnderTest(); - $queryParameters[EA::CRUD_ACTION] ??= $this->actionName(); - - // we need to prepare the URL having some query parameters in a specific order - $queryParameters = Dict\sort_by_key($queryParameters); + if (! static::usePrettyUrls()) { + $queryParameters[EA::CRUD_CONTROLLER_FQCN] ??= $this->controllerUnderTest(); + $queryParameters[EA::CRUD_ACTION] ??= $this->actionName(); + } - return http_build_query($queryParameters); + return parent::prepareAdminUrlQueryParameters($queryParameters); } /** @@ -202,6 +240,46 @@ protected function assertPageTitle(string $expectedPageTitle): void self::assertSame($expectedPageTitle, $title->text(normalizeWhitespace: true)); } + /** + * @param class-string $crudControllerFqcn + * @param non-empty-string $actionName + * @param array $redirectQueryParameters + */ + protected function assertResponseRedirectsToCrudController( + string $crudControllerFqcn, + string $actionName, + string|int|null $entityId = null, + array $redirectQueryParameters = [], + string|null $fragment = null, + ): void { + if (static::usePrettyUrls()) { + $redirectRouteParameters = []; + if ($entityId !== null) { + $redirectRouteParameters[EA::ENTITY_ID] = $entityId; + } + + $expectedRedirectUrl = 'http://' . static::serverHost() . $this->generateAdminPrettyUrl( + $this->dashboardControllerFqcn(), + $crudControllerFqcn, + $actionName, + $redirectRouteParameters, + $redirectQueryParameters, + $fragment, + ); + + self::assertResponseRedirectsToUrl($this->getClient()->getResponse(), $expectedRedirectUrl); + } else { + $redirectQueryParameters[EA::CRUD_CONTROLLER_FQCN] ??= $crudControllerFqcn; + $redirectQueryParameters[EA::CRUD_ACTION] ??= $actionName; + + if ($entityId !== null) { + $redirectQueryParameters[EA::ENTITY_ID] = $entityId; + } + + $this->assertResponseIsRedirect($redirectQueryParameters, $fragment); + } + } + /** * @param array $redirectQueryParameters */ diff --git a/src/Test/Controller/AdminWebTestCase.php b/src/Test/Controller/AdminWebTestCase.php index 497ca8f..49e2cde 100644 --- a/src/Test/Controller/AdminWebTestCase.php +++ b/src/Test/Controller/AdminWebTestCase.php @@ -4,7 +4,11 @@ namespace Protung\EasyAdminPlusBundle\Test\Controller; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface; +use EasyCorp\Bundle\EasyAdminBundle\Router\AdminRouteGenerator; use Override; +use Psl\Dict; use Psl\Iter; use Psl\Str; use Psl\Type; @@ -15,11 +19,13 @@ use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionFactoryInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\User\InMemoryUser; use Symfony\Component\Security\Core\User\UserInterface; use function array_merge; +use function http_build_query; use function serialize; abstract class AdminWebTestCase extends WebTestCase @@ -51,6 +57,11 @@ protected static function authenticationFirewallContext(): string return 'easyadmin'; } + protected static function usePrettyUrls(): bool + { + return false; + } + /** @param array $server */ #[Override] protected static function createClient(array $server = []): KernelBrowser @@ -139,6 +150,51 @@ protected static function loginAsAdmin(): UserInterface return $user; } + /** + * @param class-string|null $dashboardFqcn + * @param class-string $crudControllerFqcn + * @param non-empty-string $actionName + * @param array $routeParameters + * @param array $queryParameters + */ + protected function generateAdminPrettyUrl( + string|null $dashboardFqcn, + string $crudControllerFqcn, + string $actionName, + array $routeParameters = [], + array $queryParameters = [], + string|null $fragment = null, + ): string { + $route = $this->getContainerService(AdminRouteGenerator::class)->findRouteName( + dashboardFqcn: $dashboardFqcn, + crudControllerFqcn: $crudControllerFqcn, + actionName: $actionName, + ); + + $path = $this->getContainerService(UrlGeneratorInterface::class)->generate( + Type\non_empty_string()->assert($route), + $routeParameters, + ); + + $queryAndFragment = $this->prepareAdminUrlQueryParameters($queryParameters) . ($fragment ?? ''); + if ($queryAndFragment !== '') { + return $path . '?' . $queryAndFragment; + } + + return $path; + } + + /** + * @param array $queryParameters + */ + protected function prepareAdminUrlQueryParameters(array $queryParameters): string + { + // we need to prepare the URL having some query parameters in a specific order + $queryParameters = Dict\sort_by_key($queryParameters); + + return http_build_query($queryParameters); + } + /** * @param non-empty-string $expectedMessage * @param non-empty-string ...$expectedMessages diff --git a/src/Test/Controller/AutocompleteActionTestCase.php b/src/Test/Controller/AutocompleteActionTestCase.php index 3d71bf9..956f664 100644 --- a/src/Test/Controller/AutocompleteActionTestCase.php +++ b/src/Test/Controller/AutocompleteActionTestCase.php @@ -13,7 +13,7 @@ use function array_merge; /** - * @template TController + * @template TController of CrudControllerInterface * @template-extends CustomActionTestCase */ abstract class AutocompleteActionTestCase extends CustomActionTestCase diff --git a/src/Test/Controller/CustomActionTestCase.php b/src/Test/Controller/CustomActionTestCase.php index cb18da5..a21fd38 100644 --- a/src/Test/Controller/CustomActionTestCase.php +++ b/src/Test/Controller/CustomActionTestCase.php @@ -6,6 +6,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; use Override; use Psl\Type; use Symfony\Component\DomCrawler\Crawler; @@ -15,7 +16,7 @@ use Symfony\Component\HttpFoundation\Response; /** - * @template TCrudController + * @template TCrudController of CrudControllerInterface * @template-extends AdminControllerWebTestCase */ abstract class CustomActionTestCase extends AdminControllerWebTestCase diff --git a/src/Test/Controller/DashboardControllerTestCase.php b/src/Test/Controller/DashboardControllerTestCase.php index 7d1d256..c5736e9 100644 --- a/src/Test/Controller/DashboardControllerTestCase.php +++ b/src/Test/Controller/DashboardControllerTestCase.php @@ -4,6 +4,7 @@ namespace Protung\EasyAdminPlusBundle\Test\Controller; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface; use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator; use Psl\Dict; use Psl\Str; @@ -14,7 +15,7 @@ use function array_key_exists; /** - * @template TDashboardController + * @template TDashboardController of DashboardControllerInterface */ abstract class DashboardControllerTestCase extends AdminWebTestCase { @@ -100,7 +101,7 @@ protected function prepareDashboardUrl(array $routeParameters): string { return $this->getContainerService(AdminUrlGenerator::class) ->setAll(Dict\sort_by_key($routeParameters)) - ->setDashboard($this->getDashboardControllerFqcn()) + ->setDashboard($this->dashboardControllerFqcn()) ->generateUrl(); } @@ -118,5 +119,5 @@ private function makeGetRequestAndFollowRedirects(string $url): Crawler /** * @return class-string */ - abstract protected function getDashboardControllerFqcn(): string; + abstract protected function dashboardControllerFqcn(): string; } diff --git a/src/Test/Controller/DeleteActionTestCase.php b/src/Test/Controller/DeleteActionTestCase.php index a95487a..ec3d0d1 100644 --- a/src/Test/Controller/DeleteActionTestCase.php +++ b/src/Test/Controller/DeleteActionTestCase.php @@ -87,7 +87,7 @@ protected function assertRemovingEntityFromDetailPageAndRedirectingToIndexAction */ protected function assertDeleteEntityRespondsWithStatusCodeForbidden(array $queryParameters = []): void { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } @@ -129,6 +129,19 @@ protected function entityIdUnderTest(): string|int return static::$expectedEntityIdUnderTest; } + /** + * @return array $routeParameters + */ + #[Override] + protected function prepareAdminUrlRouteParameters(): array + { + $routeParameters = parent::prepareAdminUrlRouteParameters(); + + $routeParameters[EA::ENTITY_ID] ??= $this->entityIdUnderTest(); + + return $routeParameters; + } + /** * @return TEntity|null */ diff --git a/src/Test/Controller/DetailActionTestCase.php b/src/Test/Controller/DetailActionTestCase.php index fe05443..686428b 100644 --- a/src/Test/Controller/DetailActionTestCase.php +++ b/src/Test/Controller/DetailActionTestCase.php @@ -6,6 +6,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; use LogicException; use Override; use Psl\Str; @@ -17,7 +18,7 @@ use function array_key_exists; /** - * @template TCrudController + * @template TCrudController of CrudControllerInterface * @template-extends AdminControllerWebTestCase */ abstract class DetailActionTestCase extends AdminControllerWebTestCase @@ -48,12 +49,25 @@ protected function entityIdUnderTest(): string|int return static::$expectedEntityIdUnderTest; } + /** + * @return array $routeParameters + */ + #[Override] + protected function prepareAdminUrlRouteParameters(): array + { + $routeParameters = parent::prepareAdminUrlRouteParameters(); + + $routeParameters[EA::ENTITY_ID] ??= $this->entityIdUnderTest(); + + return $routeParameters; + } + /** * @param array $queryParameters */ public function assertRespondsWithStatusCodeForbidden(array $queryParameters = []): void { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } @@ -65,7 +79,7 @@ public function assertRespondsWithStatusCodeForbidden(array $queryParameters = [ */ protected function assertPage(array $queryParameters = []): void { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } diff --git a/src/Test/Controller/EditActionTestCase.php b/src/Test/Controller/EditActionTestCase.php index a89abc5..bf5c9b0 100644 --- a/src/Test/Controller/EditActionTestCase.php +++ b/src/Test/Controller/EditActionTestCase.php @@ -53,12 +53,25 @@ protected function entityIdUnderTest(): string|int return static::$expectedEntityIdUnderTest; } + /** + * @return array $routeParameters + */ + #[Override] + protected function prepareAdminUrlRouteParameters(): array + { + $routeParameters = parent::prepareAdminUrlRouteParameters(); + + $routeParameters[EA::ENTITY_ID] ??= $this->entityIdUnderTest(); + + return $routeParameters; + } + /** * @param array $queryParameters */ public function assertShowingEntityToEditRespondsWithStatusCodeForbidden(array $queryParameters = []): void { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } @@ -70,7 +83,7 @@ public function assertShowingEntityToEditRespondsWithStatusCodeForbidden(array $ */ protected function assertShowingEntityToEdit(array $queryParameters = []): void { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } @@ -99,9 +112,18 @@ protected function assertSavingEntityAndRedirectingToIndexAction( ): void { $this->submitFormRequest($data, $files, $queryParameters); - $redirectQueryParameters[EA::CRUD_ACTION] = Action::INDEX; + if (static::usePrettyUrls()) { + $this->assertResponseRedirectsToCrudController( + $this->controllerUnderTest(), + Action::INDEX, + null, + $redirectQueryParameters, + ); + } else { + $redirectQueryParameters[EA::CRUD_ACTION] = Action::INDEX; - $this->assertResponseIsRedirect($redirectQueryParameters); + $this->assertResponseIsRedirect($redirectQueryParameters); + } } /** @@ -118,10 +140,19 @@ protected function assertSavingEntityAndRedirectingToDetailAction( ): void { $this->submitFormRequest($data, $files, $queryParameters); - $redirectQueryParameters[EA::CRUD_ACTION] = Action::DETAIL; - $redirectQueryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); + if (static::usePrettyUrls()) { + $this->assertResponseRedirectsToCrudController( + $this->controllerUnderTest(), + Action::DETAIL, + $this->entityIdUnderTest(), + $redirectQueryParameters, + ); + } else { + $redirectQueryParameters[EA::CRUD_ACTION] = Action::DETAIL; + $redirectQueryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); - $this->assertResponseIsRedirect($redirectQueryParameters); + $this->assertResponseIsRedirect($redirectQueryParameters); + } } /** @@ -180,7 +211,7 @@ protected function submitFormRequest( array $queryParameters = [], string $submitButton = Action::SAVE_AND_RETURN, ): Crawler { - if (! array_key_exists(EA::ENTITY_ID, $queryParameters)) { + if (! static::usePrettyUrls() && ! array_key_exists(EA::ENTITY_ID, $queryParameters)) { $queryParameters[EA::ENTITY_ID] = $this->entityIdUnderTest(); } diff --git a/src/Test/Controller/IndexActionTestCase.php b/src/Test/Controller/IndexActionTestCase.php index b7c65eb..b25e8e2 100644 --- a/src/Test/Controller/IndexActionTestCase.php +++ b/src/Test/Controller/IndexActionTestCase.php @@ -6,6 +6,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA; +use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface; use Override; use Psl\Dict; use Psl\Type; @@ -13,7 +14,7 @@ use Symfony\Component\DomCrawler\Crawler; /** - * @template TCrudController + * @template TCrudController of CrudControllerInterface * @template-extends AdminControllerWebTestCase */ abstract class IndexActionTestCase extends AdminControllerWebTestCase diff --git a/src/Test/Controller/NewActionTestCase.php b/src/Test/Controller/NewActionTestCase.php index 9e4e186..8ab5fa6 100644 --- a/src/Test/Controller/NewActionTestCase.php +++ b/src/Test/Controller/NewActionTestCase.php @@ -60,9 +60,18 @@ protected function assertSavingEntityAndRedirectingToIndexAction( ): void { $this->submitFormRequest($data, $files, $queryParameters); - $redirectQueryParameters[EA::CRUD_ACTION] = Action::INDEX; - - $this->assertResponseIsRedirect($redirectQueryParameters); + if (static::usePrettyUrls()) { + $this->assertResponseRedirectsToCrudController( + $this->controllerUnderTest(), + Action::INDEX, + null, + $redirectQueryParameters, + ); + } else { + $redirectQueryParameters[EA::CRUD_ACTION] = Action::INDEX; + + $this->assertResponseIsRedirect($redirectQueryParameters); + } } /** @@ -79,10 +88,19 @@ protected function assertSavingEntityAndRedirectingToDetailAction( ): void { $this->submitFormRequest($data, $files, $queryParameters); - $redirectQueryParameters[EA::CRUD_ACTION] = Action::DETAIL; - $redirectQueryParameters[EA::ENTITY_ID] = $this->getAdminContextFromLastRequest()->getEntity()->getPrimaryKeyValueAsString(); - - $this->assertResponseIsRedirect($redirectQueryParameters); + if (static::usePrettyUrls()) { + $this->assertResponseRedirectsToCrudController( + $this->controllerUnderTest(), + Action::DETAIL, + $this->getAdminContextFromLastRequest()->getEntity()->getPrimaryKeyValueAsString(), + $redirectQueryParameters, + ); + } else { + $redirectQueryParameters[EA::CRUD_ACTION] = Action::DETAIL; + $redirectQueryParameters[EA::ENTITY_ID] = $this->getAdminContextFromLastRequest()->getEntity()->getPrimaryKeyValueAsString(); + + $this->assertResponseIsRedirect($redirectQueryParameters); + } } /**