From 76f72eb1e54d5e32d9acadfe7e8350156397addd Mon Sep 17 00:00:00 2001 From: Mateusz Zalewski Date: Wed, 4 Jul 2018 10:57:17 +0200 Subject: [PATCH 1/3] Add Symfony page class for Symfony support --- composer.json | 3 +- src/Page/SymfonyPage.php | 115 ++++++++++++++++++++++++++++++ src/Page/SymfonyPageInterface.php | 15 ++++ 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/Page/SymfonyPage.php create mode 100644 src/Page/SymfonyPageInterface.php diff --git a/composer.json b/composer.json index 739f237..475be2b 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "require": { "php": "^7.1", - "behat/mink": "^1.7" + "behat/mink": "^1.7", + "symfony/routing": "^3.4" }, "autoload": { "psr-4": { "FriendsOfBehat\\PageObjectExtension\\": "src/" } diff --git a/src/Page/SymfonyPage.php b/src/Page/SymfonyPage.php new file mode 100644 index 0000000..ba8fa65 --- /dev/null +++ b/src/Page/SymfonyPage.php @@ -0,0 +1,115 @@ + 'en_US']; + + public function __construct(Session $session, array $parameters, RouterInterface $router) + { + parent::__construct($session, $parameters); + + $this->router = $router; + } + + abstract public function getRouteName(): string; + + /** + * @throws UnexpectedPageException + */ + public function verifyRoute(array $requiredUrlParameters = []): void + { + $url = $this->getDriver()->getCurrentUrl(); + $path = parse_url($url)['path']; + + $path = preg_replace('#^/app(_dev|_test|_test_cached)?\.php/#', '/', $path); + $matchedRoute = $this->router->match($path); + + $this->verifyRouteName($matchedRoute, $url); + $this->verifyRouteParameters($requiredUrlParameters, $matchedRoute); + } + + final protected function makePathAbsolute(string $path): string + { + $baseUrl = rtrim($this->getParameter('base_url'), '/') . '/'; + + return 0 !== strpos($path, 'http') ? $baseUrl . ltrim($path, '/') : $path; + } + + protected function getUrl(array $urlParameters = []): string + { + $path = $this->router->generate($this->getRouteName(), $urlParameters + static::$additionalParameters); + + $replace = []; + foreach (static::$additionalParameters as $key => $value) { + $replace[sprintf('&%s=%s', $key, $value)] = ''; + $replace[sprintf('?%s=%s&', $key, $value)] = '?'; + $replace[sprintf('?%s=%s', $key, $value)] = ''; + } + + $path = str_replace(array_keys($replace), array_values($replace), $path); + + return $this->makePathAbsolute($path); + } + + protected function verifyUrl(array $urlParameters = []): void + { + $url = $this->getDriver()->getCurrentUrl(); + $path = parse_url($url)['path']; + + $path = preg_replace('#^/app(_dev|_test|_test_cached)?\.php/#', '/', $path); + $matchedRoute = $this->router->match($path); + + if (isset($matchedRoute['_locale'])) { + $urlParameters += ['_locale' => $matchedRoute['_locale']]; + } + + parent::verifyUrl($urlParameters); + } + + /** + * @throws UnexpectedPageException + */ + private function verifyRouteName(array $matchedRoute, string $url): void + { + if ($matchedRoute['_route'] !== $this->getRouteName()) { + throw new UnexpectedPageException( + sprintf( + "Matched route '%s' does not match the expected route '%s' for URL '%s'", + $matchedRoute['_route'], + $this->getRouteName(), + $url + ) + ); + } + } + + /** + * @throws UnexpectedPageException + */ + private function verifyRouteParameters(array $requiredUrlParameters, array $matchedRoute): void + { + foreach ($requiredUrlParameters as $key => $value) { + if (!isset($matchedRoute[$key]) || $matchedRoute[$key] !== $value) { + throw new UnexpectedPageException( + sprintf( + "Matched route does not match the expected parameter '%s'='%s' (%s found)", + $key, + $value, + $matchedRoute[$key] ?? 'null' + ) + ); + } + } + } +} diff --git a/src/Page/SymfonyPageInterface.php b/src/Page/SymfonyPageInterface.php new file mode 100644 index 0000000..b7ae8d3 --- /dev/null +++ b/src/Page/SymfonyPageInterface.php @@ -0,0 +1,15 @@ + Date: Wed, 4 Jul 2018 10:59:11 +0200 Subject: [PATCH 2/3] Document SymfonyPage --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index fd2edf8..ac985e6 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,11 @@ inspired by [sensiolabs/BehatPageObjectExtension](https://github.com/sensiolabs/ `Element` represents part of the page. This concept is extracted from [SyliusAdminOrderCreation](https://github.com/Sylius/AdminOrderCreationPlugin/blob/master/tests/Behat/Element/Element.php). +### SymfonyPage + +`SymfonyPage` is an extension of `Page` class for better and more straightforward Symfony application support. +This concept is also extracted from [Sylius Behat system](https://github.com/Sylius/Sylius/tree/master/src/Sylius/Behat/Page) + ## Installation ```bash From 4523feb7c08f2bcab92be0515979e9d50cd00c62 Mon Sep 17 00:00:00 2001 From: Mateusz Zalewski Date: Wed, 4 Jul 2018 11:37:17 +0200 Subject: [PATCH 3/3] Suggest symfony/routing and explain packages conflict --- composer.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 475be2b..ad48a1b 100644 --- a/composer.json +++ b/composer.json @@ -22,9 +22,17 @@ "require": { "php": "^7.1", - "behat/mink": "^1.7", + "behat/mink": "^1.7" + }, + "require-dev": { "symfony/routing": "^3.4" }, + "suggest": { + "symfony/routing": "Allow better support for PageObject pattern in Symfony applications" + }, + "conflict": { + "symfony/routing": "<3.4" + }, "autoload": { "psr-4": { "FriendsOfBehat\\PageObjectExtension\\": "src/" } }