diff --git a/behat.dist.yaml b/behat.dist.yaml index 5041adeb..86f38838 100644 --- a/behat.dist.yaml +++ b/behat.dist.yaml @@ -3,6 +3,14 @@ imports: default: extensions: + Behat\MinkExtension: + base_url: "https://127.0.0.1:8080/" + default_session: symfony + sessions: + symfony: + symfony: ~ + show_auto: false + FriendsOfBehat\SymfonyExtension: bootstrap: tests/bootstrap.php diff --git a/composer.json b/composer.json index f306b89b..4fa53544 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,10 @@ "require-dev": { "behat/behat": "^3.16", "doctrine/doctrine-fixtures-bundle": "^3.6", + "friends-of-behat/mink": "^1.11", + "friends-of-behat/mink-browserkit-driver": "^1.6", + "friends-of-behat/mink-extension": "^2.7", + "friends-of-behat/page-object-extension": "^0.3.2", "friends-of-behat/symfony-extension": "^2.6", "matthiasnoback/symfony-config-test": "^5.1", "matthiasnoback/symfony-dependency-injection-test": "^5.1", diff --git a/config/behat/suites/ui/book/managing_books.yaml b/config/behat/suites/ui/book/managing_books.yaml index 0bcd6f7a..1bb55eac 100644 --- a/config/behat/suites/ui/book/managing_books.yaml +++ b/config/behat/suites/ui/book/managing_books.yaml @@ -2,11 +2,10 @@ default: suites: ui_managing_books: contexts: + - Sylius\BehatBridge\Behat\Context\Hook\DoctrineORMContext - Sylius\BehatBridge\Behat\Context\Transform\SharedStorageContext - - MainTests\Sylius\Behat\Context\Setup\BookContext - - MainTests\Sylius\Behat\Context\Ui\ManagingBooksContext - + - MainTests\Sylius\Behat\Context\Domain\BookContext filters: tags: "@managing_books&&@ui" diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 455e23d8..b595e56d 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -37,6 +37,7 @@ security: access_control: - { path: ^/admin/login, roles: PUBLIC_ACCESS } - { path: ^/admin/logout, roles: PUBLIC_ACCESS } + - { path: ^/admin/books, roles: PUBLIC_ACCESS } # TODO: to remove, just to simplify for now - { path: ^/admin, roles: ROLE_ADMIN } - { path: ^/, roles: PUBLIC_ACCESS } # - { path: ^/profile, roles: ROLE_USER } diff --git a/config/services_test.yaml b/config/services_test.yaml index 4af151cd..f4cb6c62 100644 --- a/config/services_test.yaml +++ b/config/services_test.yaml @@ -3,6 +3,11 @@ services: autowire: true autoconfigure: true + # TODO should be autoconfigured on friends-of-behat/page-object-extension + _instanceof: + FriendsOfBehat\PageObjectExtension\Page\SymfonyPage: + bind: + $minkParameters: '@behat.mink.parameters' MainTests\Sylius\Behat\: resource: '../tests/Behat/*' diff --git a/ecs.php b/ecs.php index f05b3cb3..b4bc16d2 100644 --- a/ecs.php +++ b/ecs.php @@ -9,6 +9,7 @@ $ecsConfig->paths([ __DIR__ . '/app', __DIR__ . '/src', + __DIR__ . '/tests', ]); $ecsConfig->import('vendor/sylius-labs/coding-standard/ecs.php'); diff --git a/features/admin/book/managing_books/adding_books.feature b/features/admin/book/managing_books/adding_books.feature new file mode 100644 index 00000000..c76a38ee --- /dev/null +++ b/features/admin/book/managing_books/adding_books.feature @@ -0,0 +1,14 @@ +@managing_books +Feature: Adding a new book + In order to manage the library + As an Administrator + I want to add a new book + + @ui + Scenario: Adding a new book + When I want to create a new book + And I name it "Carrie" + And I specify its author as "Stephen King" + And I add it + Then the book "Carrie" should be added + And the book "Carrie" should appear in the list diff --git a/features/admin/book/managing_books/editing_books.feature b/features/admin/book/managing_books/editing_books.feature index 22c06272..8a186202 100644 --- a/features/admin/book/managing_books/editing_books.feature +++ b/features/admin/book/managing_books/editing_books.feature @@ -5,8 +5,11 @@ Feature: Editing books I want to be able to edit the book Background: - Given there is a book "Shinning" + Given there is a book "The Shining" @ui Scenario: Renaming a book When I want to edit this book + And I rename it to "Carrie" + And I save my changes + Then this book title should be "Carrie" diff --git a/src/BehatBridge/config/services/behat/context.php b/src/BehatBridge/config/services/behat/context.php index e17c9abc..be2c3632 100644 --- a/src/BehatBridge/config/services/behat/context.php +++ b/src/BehatBridge/config/services/behat/context.php @@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; +use Sylius\BehatBridge\Behat\Context\Hook\DoctrineORMContext; use Sylius\BehatBridge\Behat\Context\Transform\SharedStorageContext; return function (ContainerConfigurator $configurator): void { @@ -29,4 +30,12 @@ ]) ; $services->alias(SharedStorageContext::class, 'sylius_behat_bridge.behat.context.transform.shared_storage'); + + $services + ->set('sylius_behat_bridge.behat.context.hook.doctrine.orm', DoctrineORMContext::class) + ->args([ + service('doctrine.orm.entity_manager'), + ]) + ; + $services->alias(DoctrineORMContext::class, 'sylius_behat_bridge.behat.context.hook.doctrine.orm'); }; diff --git a/src/BehatBridge/config/services/behat/element/admin.php b/src/BehatBridge/config/services/behat/element/admin.php new file mode 100644 index 00000000..19fdec7d --- /dev/null +++ b/src/BehatBridge/config/services/behat/element/admin.php @@ -0,0 +1,52 @@ +services(); + + $services + ->set('sylius_behat_bridge.behat.element.admin.action.cancel', CancelActionElement::class) + ->args([ + service('behat.mink.default_session'), + service('behat.mink.parameters'), + ]) + ; + $services->alias(CancelActionElementInterface::class, 'sylius_behat_bridge.behat.element.admin.action.cancel'); + + $services + ->set('sylius_behat_bridge.behat.element.admin.action.create', CreateActionElement::class) + ->args([ + service('behat.mink.default_session'), + service('behat.mink.parameters'), + ]) + ; + $services->alias(CreateActionElementInterface::class, 'sylius_behat_bridge.behat.element.admin.action.create'); + + $services + ->set('sylius_behat_bridge.behat.element.admin.action.update', UpdateActionElement::class) + ->args([ + service('behat.mink.default_session'), + service('behat.mink.parameters'), + ]) + ; + $services->alias(UpdateActionElementInterface::class, 'sylius_behat_bridge.behat.element.admin.action.update'); +}; diff --git a/src/BehatBridge/src/Behat/Context/Hook/DoctrineORMContext.php b/src/BehatBridge/src/Behat/Context/Hook/DoctrineORMContext.php new file mode 100644 index 00000000..ca14d5ac --- /dev/null +++ b/src/BehatBridge/src/Behat/Context/Hook/DoctrineORMContext.php @@ -0,0 +1,35 @@ +entityManager); + $purger->purge(); + $this->entityManager->clear(); + } +} diff --git a/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElement.php b/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElement.php new file mode 100644 index 00000000..00574c02 --- /dev/null +++ b/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElement.php @@ -0,0 +1,31 @@ +getElement('cancel_button')->click(); + } + + protected function getDefinedElements(): array + { + return [ + 'cancel_button' => '[data-test-cancel-changes-button]', + ]; + } +} diff --git a/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElementInterface.php b/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElementInterface.php new file mode 100644 index 00000000..12e52131 --- /dev/null +++ b/src/BehatBridge/src/Behat/Element/Admin/Action/CancelActionElementInterface.php @@ -0,0 +1,19 @@ +getElement('create_button')->click(); + } + + protected function getDefinedElements(): array + { + return [ + 'create_button' => '[type=submit]:contains("Create")', + ]; + } +} diff --git a/src/BehatBridge/src/Behat/Element/Admin/Action/CreateActionElementInterface.php b/src/BehatBridge/src/Behat/Element/Admin/Action/CreateActionElementInterface.php new file mode 100644 index 00000000..07e085ce --- /dev/null +++ b/src/BehatBridge/src/Behat/Element/Admin/Action/CreateActionElementInterface.php @@ -0,0 +1,19 @@ +getElement('update_button')->click(); + } + + protected function getDefinedElements(): array + { + return [ + 'update_button' => '[data-test-update-changes-button]', + ]; + } +} diff --git a/src/BehatBridge/src/Behat/Element/Admin/Action/UpdateActionElementInterface.php b/src/BehatBridge/src/Behat/Element/Admin/Action/UpdateActionElementInterface.php new file mode 100644 index 00000000..03eebb59 --- /dev/null +++ b/src/BehatBridge/src/Behat/Element/Admin/Action/UpdateActionElementInterface.php @@ -0,0 +1,19 @@ +cancelActionElement->cancel(); + } + + public function create(): void + { + $this->createActionElement->create(); + } +} diff --git a/src/BehatBridge/src/Behat/Page/Admin/Crud/AbstractUpdatePage.php b/src/BehatBridge/src/Behat/Page/Admin/Crud/AbstractUpdatePage.php new file mode 100644 index 00000000..8d16e206 --- /dev/null +++ b/src/BehatBridge/src/Behat/Page/Admin/Crud/AbstractUpdatePage.php @@ -0,0 +1,43 @@ +cancelActionElement->cancel(); + } + + public function update(): void + { + $this->updateActionElement->update(); + } +} diff --git a/tests/Behat/Context/Domain/BookContext.php b/tests/Behat/Context/Domain/BookContext.php new file mode 100644 index 00000000..68ab878d --- /dev/null +++ b/tests/Behat/Context/Domain/BookContext.php @@ -0,0 +1,47 @@ + $title]); + $exist = true; + } catch (\RuntimeException) { + } + + Assert::true($exist); + } + + /** + * @param Proxy $book + */ + #[Then('/^(this book) title should be "([^"]+)"$/')] + public function thisBookTitleShouldBe(Proxy $book, string $title): void + { + Assert::eq($book->getTitle(), $title); + } +} diff --git a/tests/Behat/Context/Setup/BookContext.php b/tests/Behat/Context/Setup/BookContext.php index 22c930f7..5d682764 100644 --- a/tests/Behat/Context/Setup/BookContext.php +++ b/tests/Behat/Context/Setup/BookContext.php @@ -1,5 +1,16 @@ createPage->open(); + } + /** * @param Proxy $book */ #[When('/^I want to edit (this book)$/')] public function iWantToEditThisBook(Proxy $book): void { - // For now, we are just testing the shared context transform + $this->updatePage->open(['id' => $book->getId()]); + } + + #[When('I name it :title')] + public function iNameIt(string $title): void + { + $this->createPage->specifyTitle($title); + } + + #[When('I specify its author as :author')] + public function iSpecifyItsAuthorAs(string $author): void + { + $this->createPage->specifyAuthor($author); + } + + #[When('I rename it to :title')] + public function iRenameItTo(string $title): void + { + $this->updatePage->changeTitle($title); + } + + #[When('I add it')] + public function iAddIt(): void + { + $this->createPage->create(); + } + + #[When('I save my changes')] + public function iSaveMyChanges(): void + { + $this->updatePage->update(); + } + + #[Then('the book :title should appear in the list')] + public function theBookShouldAppearInTheList(string $title): void + { + // TODO We need an index page } } diff --git a/tests/Behat/Page/Admin/Book/CreatePage.php b/tests/Behat/Page/Admin/Book/CreatePage.php new file mode 100644 index 00000000..0f53a86c --- /dev/null +++ b/tests/Behat/Page/Admin/Book/CreatePage.php @@ -0,0 +1,42 @@ +getElement('title')->setValue($title); + } + + public function specifyAuthor(string $author): void + { + $this->getElement('author')->setValue($author); + } + + protected function getDefinedElements(): array + { + return [ + 'author' => '#sylius_resource_authorName', + 'title' => '#sylius_resource_title', + ]; + } +} diff --git a/tests/Behat/Page/Admin/Book/UpdatePage.php b/tests/Behat/Page/Admin/Book/UpdatePage.php new file mode 100644 index 00000000..5d1f1587 --- /dev/null +++ b/tests/Behat/Page/Admin/Book/UpdatePage.php @@ -0,0 +1,36 @@ +getElement('title')->setValue($title); + } + + protected function getDefinedElements(): array + { + return [ + 'title' => '#sylius_resource_title', + ]; + } +} diff --git a/tests/Functional/BookTest.php b/tests/Functional/BookTest.php index e76e60da..699953ba 100644 --- a/tests/Functional/BookTest.php +++ b/tests/Functional/BookTest.php @@ -1,5 +1,14 @@ assertCount(0, BookFactory::all()); + $this->assertCount(0, BookFactory::all()); } } diff --git a/tests/Functional/ConferenceTest.php b/tests/Functional/ConferenceTest.php index 56b4de2d..514e04c2 100644 --- a/tests/Functional/ConferenceTest.php +++ b/tests/Functional/ConferenceTest.php @@ -1,5 +1,14 @@ bootEnv(dirname(__DIR__).'/.env'); + (new Dotenv())->bootEnv(dirname(__DIR__) . '/.env'); }