diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 05e25dc1..f1ef128d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,7 +1,9 @@ name: Build on: - push: ~ + push: + branches-ignore: + - 'dependabot/**' pull_request: ~ release: types: [created] @@ -19,23 +21,18 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.0", "8.1"] - symfony: ["^5.4", "^6.0"] - sylius: ["~1.11.10", "~1.12.0"] - node: ["16.x"] - mysql: ["5.7", "8.0"] - - exclude: - - sylius: "~1.11.10" - symfony: "^6.0" - + php: ["8.1","8.2","8.3"] + symfony: ["^5.4", "^6.4"] + sylius: ["~1.12.0", "~1.13.0"] + node: ["20.x"] + mysql: ["8.0"] env: APP_ENV: test DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=${{ matrix.mysql }}" steps: - - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP @@ -43,12 +40,12 @@ jobs: with: php-version: "${{ matrix.php }}" extensions: intl, gd - tools: symfony + tools: flex, symfony coverage: none - name: Setup Node - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: node-version: "${{ matrix.node }}" @@ -70,11 +67,6 @@ jobs: - name: Install certificates run: symfony server:ca:install - - - - name: Run Chrome Headless - run: google-chrome-stable --enable-automation --disable-background-networking --no-default-browser-check --no-first-run --disable-popup-blocking --disable-default-apps --allow-insecure-localhost --disable-translate --disable-extensions --no-sandbox --enable-features=Metal --headless --remote-debugging-port=9222 --window-size=2880,1800 --proxy-server='direct://' --proxy-bypass-list='*' http://127.0.0.1 > /dev/null 2>&1 & - - name: Run webserver run: (cd tests/Application && symfony server:start --port=8080 --dir=public --daemon) @@ -82,25 +74,17 @@ jobs: - name: Get Composer cache directory id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache Composer - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json **/composer.lock') }} restore-keys: | ${{ runner.os }}-php-${{ matrix.php }}-composer- - - - name: Restrict Symfony version - if: matrix.symfony != '' - run: | - composer global config --no-plugins allow-plugins.symfony/flex true - composer global require --no-progress --no-scripts --no-plugins "symfony/flex:^1.10" - composer config extra.symfony.require "${{ matrix.symfony }}" - - name: Restrict Sylius version if: matrix.sylius != '' @@ -108,16 +92,22 @@ jobs: - name: Install PHP dependencies - run: composer update --no-interaction + run: composer install --no-interaction + env: + SYMFONY_REQUIRE: ${{ matrix.symfony }} + + - + name: Install Behat driver + run: vendor/bin/bdi browser:google-chrome drivers - name: Get Yarn cache directory id: yarn-cache - run: echo "::set-output name=dir::$(yarn cache dir)" + run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT - name: Cache Yarn - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ${{ steps.yarn-cache.outputs.dir }} key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/package.json **/yarn.lock') }} @@ -138,7 +128,7 @@ jobs: name: Prepare test application assets run: | (cd tests/Application && bin/console assets:install public -vvv) - (cd tests/Application && yarn build) + (cd tests/Application && yarn build:prod) - name: Prepare test application cache @@ -162,7 +152,7 @@ jobs: - name: Run PHPStan - run: vendor/bin/phpstan analyse -c phpstan.neon -l max src/ + run: vendor/bin/phpstan analyse - name: Run PHPSpec @@ -178,7 +168,7 @@ jobs: - name: Upload Behat logs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: Behat logs diff --git a/.gitignore b/.gitignore index 2fba55ec..3b4374bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /bin/* !/bin/.gitkeep +/drivers /vendor/ /node_modules/ /composer.lock @@ -13,3 +14,7 @@ /web/media /.phpunit.result.cache +/phpunit.xml +/phpspec.yml +/phpstan.neon +/behat.yml diff --git a/behat.yml.dist b/behat.yml.dist index bab155d7..3805e923 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -3,10 +3,17 @@ imports: - tests/Behat/Resources/suites.yml default: + formatters: + pretty: + verbose: true + paths: false + snippets: false + extensions: DMore\ChromeExtension\Behat\ServiceContainer\ChromeExtension: ~ + Robertfausk\Behat\PantherExtension: ~ - FriendsOfBehat\MinkDebugExtension\ServiceContainer\MinkDebugExtension: + FriendsOfBehat\MinkDebugExtension: directory: etc/build clean_start: false screenshot: true @@ -15,32 +22,32 @@ default: files_path: "%paths.base%/vendor/sylius/sylius/src/Sylius/Behat/Resources/fixtures/" base_url: "https://127.0.0.1:8080/" default_session: symfony - javascript_session: chrome_headless + javascript_session: panther sessions: symfony: symfony: ~ - chrome_headless: + chromedriver: chrome: api_url: http://127.0.0.1:9222 validate_certificate: false - chrome: - selenium2: - browser: chrome - capabilities: - browserName: chrome - browser: chrome - version: "" - marionette: null # https://github.com/Behat/MinkExtension/pull/311 - chrome: - switches: - - "start-fullscreen" - - "start-maximized" - - "no-sandbox" - extra_capabilities: + chrome_headless_second_session: + chrome: + api_url: http://127.0.0.1:9222 + validate_certificate: false + panther: + panther: + options: + webServerDir: "%paths.base%/tests/Application/public" + manager_options: + connection_timeout_in_ms: 5000 + request_timeout_in_ms: 120000 + chromedriver_arguments: + - --log-path=etc/build/chromedriver.log + - --verbose + capabilities: + acceptSslCerts: true + acceptInsecureCerts: true unexpectedAlertBehaviour: accept - firefox: - selenium2: - browser: firefox show_auto: false FriendsOfBehat\SymfonyExtension: @@ -53,3 +60,5 @@ default: FriendsOfBehat\SuiteSettingsExtension: paths: - "features" + + SyliusLabs\SuiteTagsExtension: ~ diff --git a/composer.json b/composer.json index e122cb7f..56e0bce3 100644 --- a/composer.json +++ b/composer.json @@ -19,34 +19,35 @@ } ], "require": { - "php": "^8.0", - "sylius/sylius": "~1.11.2 || ~1.12.0", + "sylius/sylius": "~1.12.0 || ~1.13.0", "friendsofsymfony/jsrouting-bundle": "^3.2" }, "require-dev": { "behat/behat": "^3.6", "behat/mink-selenium2-driver": "^1.4", + "dbrekelmans/bdi": "^1.1", "dmore/behat-chrome-extension": "^1.3", "dmore/chrome-mink-driver": "^2.7", "friends-of-behat/mink": "^1.8", - "friends-of-behat/mink-browserkit-driver": "^1.3", + "friends-of-behat/mink-browserkit-driver": "^1.4", + "friends-of-behat/mink-debug-extension": "^2.0", "friends-of-behat/mink-extension": "^2.5", "friends-of-behat/page-object-extension": "^0.3", "friends-of-behat/suite-settings-extension": "^1.0", "friends-of-behat/symfony-extension": "^2.1", "friends-of-behat/variadic-extension": "^1.3", - "friends-of-behat/mink-debug-extension": "^2.0", - "phpspec/phpspec": "^7.0", + "phpspec/phpspec": "^7.2", "phpstan/phpstan": "^1.8", "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^10.5", "polishsymfonycommunity/symfony-mocker-container": "^1.0", - "se/selenium-server-standalone": "^2.52", - "sylius-labs/coding-standard": "^4.0", - "symfony/debug-bundle": "^5.4 || ^6.0", - "symfony/dotenv": "^5.4 || ^6.0", - "symfony/web-profiler-bundle": "^5.4 || ^6.0", - "symfony/webpack-encore-bundle": "^1.15" + "robertfausk/behat-panther-extension": "^1.1", + "sylius-labs/coding-standard": "^4.2", + "sylius-labs/suite-tags-extension": "^0.2", + "symfony/debug-bundle": "^5.4 || ^6.4", + "symfony/dotenv": "^5.4 || ^6.4", + "symfony/runtime": "^5.4 || ^6.4", + "symfony/web-profiler-bundle": "^5.4 || ^6.4" }, "prefer-stable": true, "autoload": { @@ -55,6 +56,12 @@ "Tests\\Sylius\\AdminOrderCreationPlugin\\": "tests/" } }, + "autoload-dev": { + "psr-4": { + "spec\\Sylius\\AdminOrderCreationPlugin\\": "spec/" + }, + "classmap": ["tests/Application/Kernel.php"] + }, "scripts": { "analyse": [ "@composer validate --strict", @@ -68,12 +75,18 @@ "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": false, - "symfony/flex": true + "phpstan/extension-installer": false, + "symfony/flex": false, + "symfony/runtime": true } }, "extra": { "branch-alias": { "dev-master": "1.1-dev" + }, + "runtime": { + "project_dir": "tests/Application", + "dotenv_path": "tests/Application/.env" } } } diff --git a/easy-coding-standard.neon b/easy-coding-standard.neon deleted file mode 100644 index 004aef04..00000000 --- a/easy-coding-standard.neon +++ /dev/null @@ -1,2 +0,0 @@ -includes: - - vendor/sylius-labs/coding-standard/easy-coding-standard.neon diff --git a/easy-coding-standard.yml b/easy-coding-standard.yml deleted file mode 100644 index 24035995..00000000 --- a/easy-coding-standard.yml +++ /dev/null @@ -1,2 +0,0 @@ -imports: - - { resource: 'vendor/sylius-labs/coding-standard/easy-coding-standard.yml' } diff --git a/ecs.php b/ecs.php new file mode 100644 index 00000000..3f8fecc1 --- /dev/null +++ b/ecs.php @@ -0,0 +1,18 @@ +import('vendor/sylius-labs/coding-standard/ecs.php'); + + $config->paths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]); + $config->skip([ + '**/var/*', + '**/node_modules/*', + ]); +}; diff --git a/features/creating_order/being_unable_to_create_order_when_item_prices_are_not_defined_for_channel.feature b/features/creating_order/being_unable_to_create_order_when_item_prices_are_not_defined_for_channel.feature index 9c49b34b..4756acfc 100644 --- a/features/creating_order/being_unable_to_create_order_when_item_prices_are_not_defined_for_channel.feature +++ b/features/creating_order/being_unable_to_create_order_when_item_prices_are_not_defined_for_channel.feature @@ -8,7 +8,7 @@ Feature: Being unable to create order when item prices are not defined for chann Given the store operates on a channel named "Web-US" in "USD" currency And the store operates on a channel named "Web-EC" in "USD" currency And the store operates on a channel named "Web-PW" in "USD" currency - And the store has a product "Stark Coat" priced at "$100" available in channel "Web-US" and channel "Web-EC" + And the store has a product "Stark Coat" priced at "$100.00" available in channel "Web-US" and channel "Web-EC" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/creating_order_with_different_billing_address.feature b/features/creating_order/creating_order_with_different_billing_address.feature index 3954232e..bca69683 100644 --- a/features/creating_order/creating_order_with_different_billing_address.feature +++ b/features/creating_order/creating_order_with_different_billing_address.feature @@ -6,8 +6,8 @@ Feature: Creating order with different billing address Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$40" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$40.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/creating_order_with_multiple_items.feature b/features/creating_order/creating_order_with_multiple_items.feature index 3b8ebf94..1374655d 100644 --- a/features/creating_order/creating_order_with_multiple_items.feature +++ b/features/creating_order/creating_order_with_multiple_items.feature @@ -6,10 +6,10 @@ Feature: Creating order with multiple items Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$40" - And the store has a product "Greyjoy Boat" priced at "$1000" - And the store has a product "Targaryen Shield" priced at "$200" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$40.00" + And the store has a product "Greyjoy Boat" priced at "$1,000.00" + And the store has a product "Targaryen Shield" priced at "$200.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/creating_order_with_offline_payment.feature b/features/creating_order/creating_order_with_offline_payment.feature index 73d5e0f7..99c2f516 100644 --- a/features/creating_order/creating_order_with_offline_payment.feature +++ b/features/creating_order/creating_order_with_offline_payment.feature @@ -6,15 +6,15 @@ Feature: Creating order with offline payment Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$40" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$40.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" And I am logged in as an administrator @ui @javascript @email - Scenario: Creating an order with paypal payment for an existing customer + Scenario: Creating an order with offline payment for an existing customer When I create a new order for "jon.snow@the-wall.com" and channel "United States" And I add "Stark Coat" to this order And I specify this order shipping address as "Ankh Morpork", "Frost Alley", "90210", "United States" for "Jon Snow" diff --git a/features/creating_order/creating_order_with_online_payment.feature b/features/creating_order/creating_order_with_online_payment.feature index 8f802004..3baf1967 100644 --- a/features/creating_order/creating_order_with_online_payment.feature +++ b/features/creating_order/creating_order_with_online_payment.feature @@ -6,8 +6,8 @@ Feature: Creating order with online payment Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$40" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$40.00" And the store ships everywhere for free And the store has a payment method "Paypal" with a code "PAYPAL" and Paypal Express Checkout gateway And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/creating_order_without_payment.feature b/features/creating_order/creating_order_without_payment.feature index ce109431..52b18592 100644 --- a/features/creating_order/creating_order_without_payment.feature +++ b/features/creating_order/creating_order_without_payment.feature @@ -6,7 +6,7 @@ Feature: Creating order without payment if order is free Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$0" + And the store has a product "Stark Coat" priced at "$0.00" And the store ships everywhere for free And there is a customer account "jon.snow@the-wall.com" And I am logged in as an administrator diff --git a/features/creating_order/creating_simple_order.feature b/features/creating_order/creating_simple_order.feature index 02474458..4ad5973e 100644 --- a/features/creating_order/creating_simple_order.feature +++ b/features/creating_order/creating_simple_order.feature @@ -6,8 +6,8 @@ Feature: Creating simple order Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$40" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$40.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/modifying_item_price.feature b/features/creating_order/modifying_item_price.feature index db3e7201..70a3fc1b 100644 --- a/features/creating_order/modifying_item_price.feature +++ b/features/creating_order/modifying_item_price.feature @@ -6,8 +6,8 @@ Feature: Modifying unit price Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" - And the store has a product "Lannister Banner" priced at "$10" + And the store has a product "Stark Coat" priced at "$100.00" + And the store has a product "Lannister Banner" priced at "$10.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" @@ -22,7 +22,7 @@ Feature: Modifying unit price And I select "Free" shipping method And I select "Cash on Delivery" payment method And I place this order - And I lower item with "Stark Coat" price by "$100" + And I lower item with "Stark Coat" price by "$100.00" And I confirm this order And I check "Stark Coat" data Then I should be notified that order has been successfully created diff --git a/features/creating_order/modifying_order_total.feature b/features/creating_order/modifying_order_total.feature index b4852cd9..c8c915eb 100644 --- a/features/creating_order/modifying_order_total.feature +++ b/features/creating_order/modifying_order_total.feature @@ -6,7 +6,7 @@ Feature: Modifying order total Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" + And the store has a product "Stark Coat" priced at "$100.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/placing_order_after_going_back_from_order_preview.feature b/features/creating_order/placing_order_after_going_back_from_order_preview.feature index 68cdfe3a..f4a9e08f 100644 --- a/features/creating_order/placing_order_after_going_back_from_order_preview.feature +++ b/features/creating_order/placing_order_after_going_back_from_order_preview.feature @@ -6,7 +6,7 @@ Feature: Placing order after going back from the order preview Background: Given the store operates on a single channel in "United States" - And the store has a product "Stark Coat" priced at "$100" + And the store has a product "Stark Coat" priced at "$100.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/features/creating_order/previewing_order_before_creation.feature b/features/creating_order/previewing_order_before_creation.feature index ec8fc23e..f6459d41 100644 --- a/features/creating_order/previewing_order_before_creation.feature +++ b/features/creating_order/previewing_order_before_creation.feature @@ -8,7 +8,7 @@ Feature: Previewing order before creation Given the store operates on a single channel in "United States" And that channel allows to shop using "EUR" and "PLN" currencies And the store has locale "en_US" - And the store has a product "Stark Coat" priced at "$100" + And the store has a product "Stark Coat" priced at "$100.00" And the store ships everywhere for free And the store allows paying with "Cash on Delivery" And there is a customer account "jon.snow@the-wall.com" diff --git a/phpstan.neon b/phpstan.neon.dist similarity index 51% rename from phpstan.neon rename to phpstan.neon.dist index 642a2abb..fab0aef3 100644 --- a/phpstan.neon +++ b/phpstan.neon.dist @@ -1,14 +1,11 @@ parameters: - checkMissingIterableValueType: false - checkGenericClassInNonGenericObjectType: false + level: max + paths: + - src - excludes_analyse: - # Makes PHPStan crash - - 'src/DependencyInjection/Configuration.php' - - # Test dependencies - - 'tests/Application/app/**.php' - - 'tests/Application/src/**.php' + excludePaths: [] ignoreErrors: + - identifier: missingType.iterableValue + - identifier: missingType.generics - '/Parameter #1 \$configuration of method Symfony\\Component\\DependencyInjection\\Extension\\Extension::processConfiguration\(\) expects Symfony\\Component\\Config\\Definition\\ConfigurationInterface, Symfony\\Component\\Config\\Definition\\ConfigurationInterface\|null given\./' diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 81133862..ac2bfc2a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,10 @@ + bootstrap="tests/Application/config/bootstrap.php"> tests diff --git a/src/Controller/CustomerCreationAction.php b/src/Controller/CustomerCreationAction.php index 825a4c76..c4c647d3 100644 --- a/src/Controller/CustomerCreationAction.php +++ b/src/Controller/CustomerCreationAction.php @@ -20,7 +20,7 @@ final class CustomerCreationAction public function __construct( RouterInterface $router, - CustomerProviderInterface $customerProvider + CustomerProviderInterface $customerProvider, ) { $this->router = $router; $this->customerProvider = $customerProvider; @@ -38,8 +38,8 @@ public function __invoke(Request $request): Response [ 'customerId' => $customer->getId(), 'channelCode' => $request->attributes->get('channelCode'), - ] - ) + ], + ), ); } } diff --git a/src/Controller/OrderCreateAction.php b/src/Controller/OrderCreateAction.php index 869c3c4f..f710067b 100644 --- a/src/Controller/OrderCreateAction.php +++ b/src/Controller/OrderCreateAction.php @@ -25,7 +25,7 @@ final class OrderCreateAction public function __construct( OrderFactoryInterface $orderFactory, FormFactoryInterface $formFactory, - Environment $twig + Environment $twig, ) { $this->orderFactory = $orderFactory; $this->formFactory = $formFactory; diff --git a/src/Controller/OrderPreviewAction.php b/src/Controller/OrderPreviewAction.php index 830697b0..2bbe19bc 100644 --- a/src/Controller/OrderPreviewAction.php +++ b/src/Controller/OrderPreviewAction.php @@ -31,7 +31,7 @@ public function __construct( OrderFactoryInterface $orderFactory, FormFactoryInterface $formFactory, OrderProcessorInterface $orderProcessor, - Environment $twig + Environment $twig, ) { $this->orderFactory = $orderFactory; $this->formFactory = $formFactory; diff --git a/src/Controller/ProvideAvailableShippingMethodsAction.php b/src/Controller/ProvideAvailableShippingMethodsAction.php index 58bb2f30..8a7e9e70 100644 --- a/src/Controller/ProvideAvailableShippingMethodsAction.php +++ b/src/Controller/ProvideAvailableShippingMethodsAction.php @@ -20,7 +20,7 @@ final class ProvideAvailableShippingMethodsAction public function __construct( OrderPreparatorInterface $orderPreparator, - AvailableShippingMethodsListProvider $availableShippingMethodsListProvider + AvailableShippingMethodsListProvider $availableShippingMethodsListProvider, ) { $this->orderPreparator = $orderPreparator; $this->availableShippingMethodsListProvider = $availableShippingMethodsListProvider; diff --git a/src/DependencyInjection/Compiler/RegisterReorderProcessorsPass.php b/src/DependencyInjection/Compiler/RegisterReorderProcessorsPass.php index e506fc11..a8a1dd63 100644 --- a/src/DependencyInjection/Compiler/RegisterReorderProcessorsPass.php +++ b/src/DependencyInjection/Compiler/RegisterReorderProcessorsPass.php @@ -14,7 +14,7 @@ public function __construct() 'Sylius\AdminOrderCreationPlugin\ReorderProcessing\CompositeReorderProcessor', 'Sylius\AdminOrderCreationPlugin\ReorderProcessing\CompositeReorderProcessor', 'sylius_admin_order_creation.reorder_processor', - 'addProcessor' + 'addProcessor', ); } } diff --git a/src/EventListener/PaymentLinkCreationListener.php b/src/EventListener/PaymentLinkCreationListener.php index 91fc103c..a155456c 100644 --- a/src/EventListener/PaymentLinkCreationListener.php +++ b/src/EventListener/PaymentLinkCreationListener.php @@ -28,7 +28,7 @@ final class PaymentLinkCreationListener public function __construct( PaymentTokenProviderInterface $paymentTokenProvider, ObjectManager $orderManager, - OrderPaymentLinkSenderInterface $orderPaymentLinkSender + OrderPaymentLinkSenderInterface $orderPaymentLinkSender, ) { $this->paymentTokenProvider = $paymentTokenProvider; $this->orderManager = $orderManager; diff --git a/src/Factory/OrderFactory.php b/src/Factory/OrderFactory.php index db322eb3..d82ad2cb 100644 --- a/src/Factory/OrderFactory.php +++ b/src/Factory/OrderFactory.php @@ -33,7 +33,7 @@ public function __construct( FactoryInterface $baseOrderFactory, CustomerRepositoryInterface $customerRepository, ChannelRepositoryInterface $channelRepository, - ReorderProcessor $reorderProcessor + ReorderProcessor $reorderProcessor, ) { $this->baseOrderFactory = $baseOrderFactory; $this->customerRepository = $customerRepository; diff --git a/src/Form/Type/CurrencyCodeChoiceType.php b/src/Form/Type/CurrencyCodeChoiceType.php index 5a747dc5..687e8aa0 100644 --- a/src/Form/Type/CurrencyCodeChoiceType.php +++ b/src/Form/Type/CurrencyCodeChoiceType.php @@ -24,7 +24,7 @@ public function __construct(RepositoryInterface $currencyRepository) public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->addModelTransformer( - new ReversedTransformer(new ResourceToIdentifierTransformer($this->currencyRepository, 'code')) + new ReversedTransformer(new ResourceToIdentifierTransformer($this->currencyRepository, 'code')), ); } diff --git a/src/Form/Type/CustomerAutocompleteChoiceType.php b/src/Form/Type/CustomerAutocompleteChoiceType.php index 7069f954..0b9b0f31 100644 --- a/src/Form/Type/CustomerAutocompleteChoiceType.php +++ b/src/Form/Type/CustomerAutocompleteChoiceType.php @@ -23,7 +23,7 @@ public function configureOptions(OptionsResolver $resolver): void } /** - * {@inheritdoc} + * @inheritdoc */ public function buildView(FormView $view, FormInterface $form, array $options): void { @@ -32,7 +32,7 @@ public function buildView(FormView $view, FormInterface $form, array $options): } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockPrefix(): string { @@ -40,7 +40,7 @@ public function getBlockPrefix(): string } /** - * {@inheritdoc} + * @inheritdoc */ public function getParent(): string { diff --git a/src/Form/Type/LocaleCodeChoiceType.php b/src/Form/Type/LocaleCodeChoiceType.php index 92508246..53954ad3 100644 --- a/src/Form/Type/LocaleCodeChoiceType.php +++ b/src/Form/Type/LocaleCodeChoiceType.php @@ -22,7 +22,7 @@ public function __construct(RepositoryInterface $localeRepository) } /** - * {@inheritdoc} + * @inheritdoc */ public function buildForm(FormBuilderInterface $builder, array $options): void { @@ -30,7 +30,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void } /** - * {@inheritdoc} + * @inheritdoc */ public function getParent(): string { @@ -38,7 +38,7 @@ public function getParent(): string } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockPrefix(): string { diff --git a/src/Form/Type/OrderItemType.php b/src/Form/Type/OrderItemType.php index 04e74360..a582cb53 100644 --- a/src/Form/Type/OrderItemType.php +++ b/src/Form/Type/OrderItemType.php @@ -22,7 +22,7 @@ final class OrderItemType extends AbstractResourceType public function __construct( string $dataClass, DataMapperInterface $dataMapper, - array $validationGroups = [] + array $validationGroups = [], ) { parent::__construct($dataClass, $validationGroups); @@ -82,7 +82,7 @@ public function configureOptions(OptionsResolver $resolver): void } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockPrefix(): string { diff --git a/src/Form/Type/PaymentType.php b/src/Form/Type/PaymentType.php index 8402a63a..bb65069d 100644 --- a/src/Form/Type/PaymentType.php +++ b/src/Form/Type/PaymentType.php @@ -19,7 +19,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockPrefix(): string { diff --git a/src/Form/Type/ShipmentType.php b/src/Form/Type/ShipmentType.php index 60ffecc9..fa9118b1 100644 --- a/src/Form/Type/ShipmentType.php +++ b/src/Form/Type/ShipmentType.php @@ -19,7 +19,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void } /** - * {@inheritdoc} + * @inheritdoc */ public function getBlockPrefix(): string { diff --git a/src/Preparator/NewOrderPreparator.php b/src/Preparator/NewOrderPreparator.php index 07d1224a..2ed0db86 100644 --- a/src/Preparator/NewOrderPreparator.php +++ b/src/Preparator/NewOrderPreparator.php @@ -26,7 +26,7 @@ final class NewOrderPreparator implements OrderPreparatorInterface public function __construct( OrderFactoryInterface $orderFactory, FormFactoryInterface $formFactory, - OrderProcessorInterface $orderProcessor + OrderProcessorInterface $orderProcessor, ) { $this->orderFactory = $orderFactory; $this->formFactory = $formFactory; diff --git a/src/Provider/CustomerProvider.php b/src/Provider/CustomerProvider.php index 3f7fc93b..8887ab15 100644 --- a/src/Provider/CustomerProvider.php +++ b/src/Provider/CustomerProvider.php @@ -19,7 +19,7 @@ final class CustomerProvider implements CustomerProviderInterface public function __construct( CustomerRepositoryInterface $customerRepository, - FactoryInterface $customerFactory + FactoryInterface $customerFactory, ) { $this->customerRepository = $customerRepository; $this->customerFactory = $customerFactory; diff --git a/src/Provider/PaymentTokenProvider.php b/src/Provider/PaymentTokenProvider.php index 21d0fd4a..6857a070 100644 --- a/src/Provider/PaymentTokenProvider.php +++ b/src/Provider/PaymentTokenProvider.php @@ -40,14 +40,14 @@ public function getPaymentToken(PaymentInterface $payment): TokenInterface return $tokenFactory->createAuthorizeToken( $gatewayConfig->getGatewayName(), $payment, - $this->afterPayRoute + $this->afterPayRoute, ); } return $tokenFactory->createCaptureToken( $gatewayConfig->getGatewayName(), $payment, - $this->afterPayRoute + $this->afterPayRoute, ); } } diff --git a/src/ReorderProcessing/CompositeReorderProcessor.php b/src/ReorderProcessing/CompositeReorderProcessor.php index 2ebf7f8f..fba2239d 100644 --- a/src/ReorderProcessing/CompositeReorderProcessor.php +++ b/src/ReorderProcessing/CompositeReorderProcessor.php @@ -4,8 +4,8 @@ namespace Sylius\AdminOrderCreationPlugin\ReorderProcessing; -use Sylius\Component\Core\Model\OrderInterface; use Laminas\Stdlib\PriorityQueue; +use Sylius\Component\Core\Model\OrderInterface; final class CompositeReorderProcessor implements ReorderProcessor { diff --git a/src/ReorderProcessing/ReorderItemsProcessor.php b/src/ReorderProcessing/ReorderItemsProcessor.php index 3304745e..f89fe04d 100644 --- a/src/ReorderProcessing/ReorderItemsProcessor.php +++ b/src/ReorderProcessing/ReorderItemsProcessor.php @@ -25,7 +25,7 @@ final class ReorderItemsProcessor implements ReorderProcessor public function __construct( FactoryInterface $orderItemFactory, OrderItemQuantityModifierInterface $orderItemQuantityModifier, - OrderModifierInterface $orderModifier + OrderModifierInterface $orderModifier, ) { $this->orderItemFactory = $orderItemFactory; $this->orderItemQuantityModifier = $orderItemQuantityModifier; diff --git a/src/Sender/OrderPaymentLinkSender.php b/src/Sender/OrderPaymentLinkSender.php index 51d1c63b..b45c5213 100644 --- a/src/Sender/OrderPaymentLinkSender.php +++ b/src/Sender/OrderPaymentLinkSender.php @@ -39,7 +39,7 @@ public function sendPaymentLink(OrderInterface $order): void [ 'order' => $order, 'paymentLink' => $paymentDetails['payment-link'], - ] + ], ) ; } diff --git a/tests/Application/.env b/tests/Application/.env index 2de4b1f1..853f9d0b 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -31,8 +31,12 @@ JWT_PASSPHRASE=YOUR_SECRET_PASSPHRASE ###> symfony/messenger ### # Choose one of the transports below # MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages -MESSENGER_TRANSPORT_DSN=doctrine://default +# MESSENGER_TRANSPORT_DSN=doctrine://default # MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +SYLIUS_MESSENGER_TRANSPORT_MAIN_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_MAIN_FAILED_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_DSN=sync:// +SYLIUS_MESSENGER_TRANSPORT_CATALOG_PROMOTION_REMOVAL_FAILED_DSN=sync:// ###< symfony/messenger ### ###> symfony/mailer ### diff --git a/tests/Application/.env.test b/tests/Application/.env.test index e8e3a7ee..c74ebd71 100644 --- a/tests/Application/.env.test +++ b/tests/Application/.env.test @@ -7,12 +7,3 @@ JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private-test.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public-test.pem JWT_PASSPHRASE=ALL_THAT_IS_GOLD_DOES_NOT_GLITTER_NOT_ALL_THOSE_WHO_WANDER_ARE_LOST ###< lexik/jwt-authentication-bundle ### - -###> symfony/messenger ### -# Sync transport turned for testing env for the ease of testing -MESSENGER_TRANSPORT_DSN=sync:// -###< symfony/messenger ### - -###> symfony/mailer ### -MAILER_DSN=null://null -###< symfony/mailer ### diff --git a/tests/Application/.gitignore b/tests/Application/.gitignore index 8ad1225e..ea7406f6 100644 --- a/tests/Application/.gitignore +++ b/tests/Application/.gitignore @@ -1,10 +1,8 @@ /public/assets +/public/build /public/css /public/js /public/media/* -!/public/media/image/ -/public/media/image/* -!/public/media/image/.gitignore /node_modules diff --git a/tests/Application/Kernel.php b/tests/Application/Kernel.php index d42a1521..7c60a15c 100644 --- a/tests/Application/Kernel.php +++ b/tests/Application/Kernel.php @@ -5,7 +5,7 @@ namespace Tests\Sylius\AdminOrderCreationPlugin\Application; use PSS\SymfonyMockerContainer\DependencyInjection\MockerContainer; -use Sylius\Bundle\CoreBundle\Application\Kernel as SyliusKernel; +use Sylius\Bundle\CoreBundle\SyliusCoreBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\FileResource; @@ -13,7 +13,6 @@ use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Kernel as BaseKernel; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; -use Symfony\Component\Routing\RouteCollectionBuilder; final class Kernel extends BaseKernel { @@ -101,10 +100,17 @@ private function registerBundlesFromFile(string $bundlesFile): iterable { $contents = require $bundlesFile; - if (SyliusKernel::MINOR_VERSION > 10) { + if (SyliusCoreBundle::MINOR_VERSION > 10) { $contents = array_merge( ['Sylius\Calendar\SyliusCalendarBundle' => ['all' => true]], - $contents + $contents, + ); + } + + if (SyliusCoreBundle::MINOR_VERSION > 12) { + $contents = array_merge( + ['Sylius\Abstraction\StateMachine\SyliusStateMachineAbstractionBundle' => ['all' => true]], + $contents, ); } @@ -125,9 +131,9 @@ private function getBundleListFiles(): array static function (string $directory): string { return $directory . '/bundles.php'; }, - $this->getConfigurationDirectories() + $this->getConfigurationDirectories(), ), - 'file_exists' + 'file_exists', ); } @@ -138,7 +144,7 @@ private function getConfigurationDirectories(): array { $directories = [ $this->getProjectDir() . '/config', - $this->getProjectDir() . '/config/sylius/' . SyliusKernel::MAJOR_VERSION . '.' . SyliusKernel::MINOR_VERSION, + $this->getProjectDir() . '/config/sylius/' . SyliusCoreBundle::MAJOR_VERSION . '.' . SyliusCoreBundle::MINOR_VERSION, ]; return array_filter($directories, 'file_exists'); diff --git a/tests/Application/bin/console b/tests/Application/bin/console index 0554a196..d909c919 100755 --- a/tests/Application/bin/console +++ b/tests/Application/bin/console @@ -3,36 +3,13 @@ use Tests\Sylius\AdminOrderCreationPlugin\Application\Kernel; use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Component\Console\Input\ArgvInput; -use Symfony\Component\Debug\Debug; -set_time_limit(0); - -require __DIR__.'/../../../vendor/autoload.php'; - -if (!class_exists(Application::class)) { - throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.'); +if (!is_file(dirname(__DIR__).'/../../vendor/autoload_runtime.php')) { + throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".'); } -$input = new ArgvInput(); -if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) { - putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env); -} - -if ($input->hasParameterOption('--no-debug', true)) { - putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0'); -} - -require dirname(__DIR__).'/config/bootstrap.php'; - -if ($_SERVER['APP_DEBUG']) { - umask(0000); - - if (class_exists(Debug::class)) { - Debug::enable(); - } -} +require_once dirname(__DIR__).'/../../vendor/autoload_runtime.php'; -$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']); -$application = new Application($kernel); -$application->run($input); +return function (array $context) { + return new Application(new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG'])); +}; diff --git a/tests/Application/config/bootstrap.php b/tests/Application/config/bootstrap.php index 6bb0207a..2291ab42 100644 --- a/tests/Application/config/bootstrap.php +++ b/tests/Application/config/bootstrap.php @@ -1,21 +1,23 @@ =1.2) -if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) { +if (is_array($env = @include dirname(__DIR__) . '/.env.local.php')) { $_SERVER += $env; $_ENV += $env; } elseif (!class_exists(Dotenv::class)) { throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.'); } else { // load all the .env files - (new Dotenv())->loadEnv(dirname(__DIR__).'/.env'); + (new Dotenv())->loadEnv(dirname(__DIR__) . '/.env'); } $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev'; $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV']; -$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; +$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], \FILTER_VALIDATE_BOOLEAN) ? '1' : '0'; diff --git a/tests/Application/config/bundles.php b/tests/Application/config/bundles.php index fe6cbc48..815cd826 100644 --- a/tests/Application/config/bundles.php +++ b/tests/Application/config/bundles.php @@ -1,5 +1,7 @@ handle($request); -$response->send(); -$kernel->terminate($request, $response); +return static function (array $context) { + return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); +}; diff --git a/tests/Application/public/media/image/.gitignore b/tests/Application/public/media/image/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/Application/src/Migrations/.gitkeep b/tests/Application/src/Migrations/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/Behat/Context/Admin/ManagingOrdersContext.php b/tests/Behat/Context/Admin/ManagingOrdersContext.php index 5760ce67..ae00eb6a 100644 --- a/tests/Behat/Context/Admin/ManagingOrdersContext.php +++ b/tests/Behat/Context/Admin/ManagingOrdersContext.php @@ -6,15 +6,13 @@ use Behat\Behat\Context\Context; use Sylius\Behat\NotificationType; +use Sylius\Behat\Service\Checker\EmailCheckerInterface; use Sylius\Behat\Service\NotificationCheckerInterface; -use Sylius\Bundle\CoreBundle\Application\Kernel; -use Sylius\Component\Addressing\Comparator\AddressComparatorInterface; use Sylius\Component\Core\Model\AddressInterface; use Sylius\Component\Core\Model\CustomerInterface; use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\ProductInterface; -use Sylius\Behat\Service\Checker\EmailCheckerInterface as BehatEmailCheckerInterface; -use Sylius\Component\Core\Test\Services\EmailCheckerInterface as CoreEmailCheckerInterface; +use Sylius\Component\Core\Model\ProductVariantInterface; use Tests\Sylius\AdminOrderCreationPlugin\Behat\Element\Admin\OrderCreateFormElementInterface; use Tests\Sylius\AdminOrderCreationPlugin\Behat\Page\Admin\NewOrderCustomerPageInterface; use Tests\Sylius\AdminOrderCreationPlugin\Behat\Page\Admin\OrderIndexPageInterface; @@ -25,53 +23,16 @@ final class ManagingOrdersContext implements Context { - /** @var OrderIndexPageInterface */ - private $orderIndexPage; - - /** @var NewOrderCustomerPageInterface */ - private $newOrderCustomerPage; - - /** @var OrderPreviewPageInterface */ - private $orderPreviewPage; - - /** @var OrderShowPageInterface */ - private $orderShowPage; - - /** @var ReorderPageInterface */ - private $reorderPage; - - /** @var OrderCreateFormElementInterface */ - private $orderCreateFormElement; - - /** @var NotificationCheckerInterface */ - private $notificationChecker; - - /** @var BehatEmailCheckerInterface|CoreEmailCheckerInterface */ - private $emailChecker; - - /** @var AddressComparatorInterface */ - private $addressComparator; - public function __construct( - OrderIndexPageInterface $orderIndexPage, - NewOrderCustomerPageInterface $newOrderCustomerPage, - OrderPreviewPageInterface $orderPreviewPage, - OrderShowPageInterface $orderShowPage, - ReorderPageInterface $reorderPage, - OrderCreateFormElementInterface $orderCreateFormElement, - NotificationCheckerInterface $notificationChecker, - BehatEmailCheckerInterface|CoreEmailCheckerInterface $emailChecker, - AddressComparatorInterface $addressComparator + private OrderIndexPageInterface $orderIndexPage, + private NewOrderCustomerPageInterface $newOrderCustomerPage, + private OrderPreviewPageInterface $orderPreviewPage, + private OrderShowPageInterface $orderShowPage, + private ReorderPageInterface $reorderPage, + private OrderCreateFormElementInterface $orderCreateFormElement, + private NotificationCheckerInterface $notificationChecker, + private EmailCheckerInterface $emailChecker, ) { - $this->orderIndexPage = $orderIndexPage; - $this->newOrderCustomerPage = $newOrderCustomerPage; - $this->orderPreviewPage = $orderPreviewPage; - $this->orderShowPage = $orderShowPage; - $this->reorderPage = $reorderPage; - $this->orderCreateFormElement = $orderCreateFormElement; - $this->notificationChecker = $notificationChecker; - $this->emailChecker = $emailChecker; - $this->addressComparator = $addressComparator; } /** @@ -84,7 +45,9 @@ public function createNewOrderFor(CustomerInterface $customer, string $channelNa $this->newOrderCustomerPage->selectChannel($channelName); - $this->newOrderCustomerPage->selectCustomer($customer->getEmail()); + /** @var string $customerEmail */ + $customerEmail = $customer->getEmail(); + $this->newOrderCustomerPage->selectCustomer($customerEmail); $this->newOrderCustomerPage->next(); } @@ -124,18 +87,13 @@ public function tryToCreateNewOrderForNewCustomerWithoutEmail(): void /** * @When I add :product to this order - */ - public function addProductToThisOrder(ProductInterface $product): void - { - $this->orderCreateFormElement->addProduct($product->getVariants()->first()->getDescriptor()); - } - - /** * @When I add :quantity of :product to this order */ - public function addMultipleProductsToThisOrder(int $quantity, ProductInterface $product): void + public function addProductToThisOrder(ProductInterface $product, int $quantity = 1): void { - $this->orderCreateFormElement->addMultipleProducts($product->getVariants()->first()->getDescriptor(), $quantity); + /** @var ProductVariantInterface $productVariant */ + $productVariant = $product->getVariants()->first(); + $this->orderCreateFormElement->addProductWithQuantity($productVariant->getDescriptor(), $quantity); } /** @@ -143,11 +101,14 @@ public function addMultipleProductsToThisOrder(int $quantity, ProductInterface $ */ public function removeProductFromThisOrder(ProductInterface $product): void { + /** @var ProductVariantInterface $productVariant */ + $productVariant = $product->getVariants()->first(); + try { - $this->orderCreateFormElement->removeProduct($product->getVariants()->first()->getDescriptor()); + $this->orderCreateFormElement->removeProduct($productVariant->getDescriptor()); } catch (\InvalidArgumentException $exception) { // TODO: Currently the autocomplete include product variant code instead of its descriptor when rendering a form with existing items - $this->orderCreateFormElement->removeProduct($product->getVariants()->first()->getCode()); + $this->orderCreateFormElement->removeProduct($productVariant->getCode()); } } @@ -237,9 +198,11 @@ public function lowerOrderPriceBy(string $discount): void */ public function lowerItemWithProductPriceBy(ProductInterface $product, string $discount): void { + /** @var string $productCode */ + $productCode = $product->getCode(); $this->orderPreviewPage->lowerItemWithProductPriceBy( - $product->getCode(), - str_replace(['$', '€', '£'], '', $discount) + $productCode, + str_replace(['$', '€', '£'], '', $discount), ); } @@ -248,11 +211,14 @@ public function lowerItemWithProductPriceBy(ProductInterface $product, string $d */ public function iChangeQuantityOfItemTo(ProductInterface $product, int $quantity): void { + /** @var ProductVariantInterface $productVariant */ + $productVariant = $product->getVariants()->first(); + try { - $this->orderCreateFormElement->specifyQuantity($product->getVariants()->first()->getDescriptor(), $quantity); + $this->orderCreateFormElement->specifyQuantity($productVariant->getDescriptor(), $quantity); } catch (\InvalidArgumentException $exception) { // TODO: Currently the autocomplete include product variant code instead of its descriptor when rendering a form with existing items - $this->orderCreateFormElement->specifyQuantity($product->getVariants()->first()->getCode(), $quantity); + $this->orderCreateFormElement->specifyQuantity($productVariant->getCode(), $quantity); } } @@ -323,8 +289,8 @@ public function shouldNotHaveShippingMethodAvailableToSelect(string $shippingMet public function shouldBeNotifiedAboutShippingMethodsSelectionRequirements(): void { Assert::same( + $this->orderCreateFormElement->getShippingMethodsValidationMessage(), 'You need to add some items and shipping address to select from eligible shipping method', - $this->orderCreateFormElement->getShippingMethodsValidationMessage() ); } @@ -335,7 +301,7 @@ public function shouldBeNotifiedThatOrderHasBeenSuccessfullyCreated(): void { $this->notificationChecker->checkNotification( 'Order has been successfully created', - NotificationType::success() + NotificationType::success(), ); } @@ -352,8 +318,10 @@ public function shouldBeNotifiedThatOrderDiscountCannotBeBelow0(): void */ public function shouldBeNotifiedThatItemWithProductDiscountCannotBeBelow0(ProductInterface $product): void { + /** @var string $productCode */ + $productCode = $product->getCode(); Assert::true( - $this->orderPreviewPage->hasItemDiscountValidationMessage($product->getCode(), 'Discount cannot be below 0') + $this->orderPreviewPage->hasItemDiscountValidationMessage($productCode, 'Discount cannot be below 0'), ); } @@ -388,7 +356,7 @@ public function thereShouldBePaymentLinkSentTo(string $email): void { Assert::true($this->emailChecker->hasMessageTo( 'New order has been created for you in Admin panel. Check it out in your orders history. To pay for this order, click', - $email + $email, )); } @@ -397,19 +365,7 @@ public function thereShouldBePaymentLinkSentTo(string $email): void */ public function thereShouldBeNoPaymentLinkSentTo(string $email): void { - if (Kernel::VERSION_ID < 11200) { - try { - $this->emailChecker->countMessagesTo($email); - } catch (\InvalidArgumentException $exception) { - return; - } - - throw new \Exception('There should be no messages exception thrown'); - } - - if (11200 <= Kernel::VERSION_ID) { - Assert::same($this->emailChecker->countMessagesTo($email), 0); - } + Assert::same($this->emailChecker->countMessagesTo($email), 0); } /** @@ -424,7 +380,7 @@ public function thereShouldBeOneOrderForInTheRegistry(string $channelName, Custo 'state' => 'New', 'paymentState' => 'Awaiting payment', 'shippingState' => 'Ready', - 'channel' => $channelName + 'channel' => $channelName, ])); } @@ -442,7 +398,7 @@ public function thereShouldBeOneOrdersForInTheRegistry(int $amountOfOrders, Cust 'state' => 'New', 'paymentState' => 'Awaiting payment', 'shippingState' => 'Ready', - ]) + ]), ); } @@ -454,7 +410,7 @@ public function thisOrderShippingAddressShouldBe( string $street, string $postcode, string $city, - string $countryName + string $countryName, ): void { Assert::true($this->orderShowPage->hasShippingAddress($customerName, $street, $postcode, $city, $countryName)); } @@ -467,7 +423,7 @@ public function thisOrderBillingAddressShouldBe( string $street, string $postcode, string $city, - string $countryName + string $countryName, ): void { Assert::true($this->orderShowPage->hasBillingAddress($customerName, $street, $postcode, $city, $countryName)); } diff --git a/tests/Behat/Context/Transform/LexicalContext.php b/tests/Behat/Context/Transform/LexicalContext.php new file mode 100644 index 00000000..6c15bd22 --- /dev/null +++ b/tests/Behat/Context/Transform/LexicalContext.php @@ -0,0 +1,49 @@ +validatePriceString($price); + + $price = str_replace(',', '', $price); + $price = (int) round((float) $price * 100, 2); + + if ('-' === $sign) { + $price *= -1; + } + + return $price; + } + + /** + * @Transform /^"((?:\d+\.)?\d+)%"$/ + */ + public function getPercentageFromString(string $percentage): float + { + return (float) $percentage / 100; + } + + /** + * @throws \InvalidArgumentException + */ + private function validatePriceString(string $price): void + { + if (!preg_match('/^.*\.\d{2}$/', $price)) { + throw new \InvalidArgumentException('The price string should have exactly 2 decimal digits.'); + } + + if (!preg_match('/^\d{1,3}(,\d{3})*\.\d{2}$/', $price)) { + throw new \InvalidArgumentException('Thousands and larger numbers should be separated by commas.'); + } + } +} diff --git a/tests/Behat/Element/Admin/OrderCreateFormElement.php b/tests/Behat/Element/Admin/OrderCreateFormElement.php index a9444fa2..9c96e8b2 100644 --- a/tests/Behat/Element/Admin/OrderCreateFormElement.php +++ b/tests/Behat/Element/Admin/OrderCreateFormElement.php @@ -4,11 +4,11 @@ namespace Tests\Sylius\AdminOrderCreationPlugin\Behat\Element\Admin; -use Behat\Mink\Driver\Selenium2Driver; +use ArrayAccess; use Behat\Mink\Element\NodeElement; use Behat\Mink\Exception\Exception; use Behat\Mink\Session; -use DMore\ChromeDriver\ChromeDriver; +use Sylius\Behat\Service\JQueryHelper; use Sylius\Component\Core\Model\AddressInterface; use Tests\Sylius\AdminOrderCreationPlugin\Behat\Element\Element; use Tests\Sylius\AdminOrderCreationPlugin\Behat\Service\AutoCompleteSelector; @@ -16,36 +16,25 @@ class OrderCreateFormElement extends Element implements OrderCreateFormElementInterface { public const TYPE_BILLING = 'billing'; + public const TYPE_SHIPPING = 'shipping'; - /** @var AutoCompleteSelector */ - private $autoCompleteSelector; public function __construct( Session $session, - $parameters, - AutoCompleteSelector $autoCompleteSelector + ArrayAccess $parameters, + private AutoCompleteSelector $autoCompleteSelector, ) { parent::__construct($session, $parameters); - - $this->autoCompleteSelector = $autoCompleteSelector; - } - - public function addProduct(string $productVariantDescriptor): void - { - $this->clickOnTabAndWait('Items'); - $item = $this->addItemAndWaitForIt(); - - $this->autoCompleteSelector->selectOption($item, $productVariantDescriptor); } - public function addMultipleProducts(string $productVariantDescriptor, int $quantity): void + public function addProductWithQuantity(string $productVariantDescriptor, int $quantity): void { $this->clickOnTabAndWait('Items'); - $item = $this->addItemAndWaitForIt(); + $item = $this->addItemAndReturnIt(); - $this->autoCompleteSelector->selectOption($item, $productVariantDescriptor); - $item->fillField('Quantity', $quantity); + $this->autoCompleteSelector->selectOption($this->getSession(), $item, $productVariantDescriptor); + $item->fillField('Quantity', (string) $quantity); } public function removeProduct(string $productVariantDescriptor): void @@ -60,26 +49,30 @@ public function areProductsVisible(): bool { $this->clickOnTabAndWait('Items'); - $item = $this->addItemAndWaitForIt(); + $item = $this->addItemAndReturnIt(); - return $this->autoCompleteSelector->areItemsVisible($item); + return $this->autoCompleteSelector->areItemsVisible($this->getSession(), $item); } public function specifyShippingAddress(AddressInterface $address): void { $this->clickOnTabAndWait('Shipping address & Billing address'); + /** @var NodeElement $addressForm */ + $addressForm = $this->getDocument()->find('css', 'div[id*="shippingAddress"]'); $this->fillAddressData( - $this->getDocument()->find('css', 'div[id*="shippingAddress"]'), - $address + $addressForm, + $address, ); } public function specifyBillingAddress(AddressInterface $address): void { + /** @var NodeElement $addressForm */ + $addressForm = $this->getDocument()->find('css', 'div[id*="billingAddress"]'); $this->fillAddressData( - $this->getDocument()->find('css', 'div[id*="billingAddress"]'), - $address + $addressForm, + $address, ); } @@ -87,6 +80,7 @@ public function getAvailableShippingMethods(): array { $this->clickOnTabAndWait('Shipments & Payments'); + /** @var NodeElement $shipmentsCollection */ $shipmentsCollection = $this->getDocument()->find('css', '#sylius_admin_order_creation_new_order_shipments'); if (count($shipmentsCollection->findAll('css', '[data-form-collection="item"]')) === 0) { @@ -96,14 +90,13 @@ public function getAvailableShippingMethods(): array $this->waitForFormToLoad(); $shippingMethods = $this->getDocument()->findAll( - 'css', '#sylius_admin_order_creation_new_order_shipments [data-form-collection="item"]:last-child select option' + 'css', + '#sylius_admin_order_creation_new_order_shipments [data-form-collection="item"]:last-child select option', ); - $shippingMethods = array_map(function(NodeElement $option) : string { + return array_map(static function (NodeElement $option): string { return $option->getText(); }, $shippingMethods); - - return $shippingMethods; } public function moveToShippingAndPaymentsSection(): void @@ -135,12 +128,12 @@ public function specifyQuantity(string $productVariantDescriptor, int $quantity) { $item = $this->getItemWithProductSelected($productVariantDescriptor); - $item->fillField('Quantity', $quantity); + $item->fillField('Quantity', (string) $quantity); } public function placeOrder(): void { - $this->getDocument()->waitFor(10, function() { + $this->getDocument()->waitFor(10, function () { try { $this->getDocument()->pressButton('Create'); @@ -149,7 +142,6 @@ public function placeOrder(): void return false; } }); - } public function selectLocale(string $localeName): void @@ -168,11 +160,10 @@ public function selectCurrency(string $currencyName): void public function getShippingMethodsValidationMessage(): string { - return $this - ->getDocument() - ->find('css', '#shipmentsAndPayments .invalid-data-message') - ->getText() - ; + /** @var NodeElement $invalidMessage */ + $invalidMessage = $this->getDocument()->find('css', '#shipmentsAndPayments .invalid-data-message'); + + return $invalidMessage->getText(); } protected function getDefinedElements(): array @@ -234,38 +225,24 @@ private function selectMethod(string $type, string $field, string $name, bool $a $collection->selectFieldOption($field, $name); } - private function addItemAndWaitForIt(): NodeElement + private function addItemAndReturnIt(): NodeElement { - $itemsCount = $this->countItems(); - $this->getDocument()->waitFor(10, function() { - try { - $this->getDocument()->clickLink('Add'); + $this->getDocument()->clickLink('Add'); - return true; - } catch (Exception $exception) { - return false; - } - }); - - $this->getDocument()->waitFor(1, function () use ($itemsCount) { - return $this->countItems() > $itemsCount; - }); + /** @var NodeElement $lastItem */ + $lastItem = $this->getDocument()->find('css', '#items [data-form-collection="item"]:last-child'); - return $this->getDocument()->find('css', '#items [data-form-collection="item"]:last-child'); - } - - private function countItems(): int - { - return count($this->getDocument()->findAll('css', '#items [data-form-collection="item"]')); + return $lastItem; } private function getItemWithProductSelected(string $productVariantDescriptor): NodeElement { - /** @var NodeElement $item */ foreach ($this->getDocument()->findAll('css', '#items [data-form-collection="item"]') as $item) { - $selectedProduct = $item->find('css', '.sylius-autocomplete .text')->getText(); + /** @var NodeElement $autocompleteText */ + $autocompleteText = $item->find('css', '.sylius-autocomplete .text'); + $selectedProduct = $autocompleteText->getText(); - if (strpos($selectedProduct, $productVariantDescriptor) !== false) { + if (str_contains($selectedProduct, $productVariantDescriptor)) { return $item; } } @@ -275,39 +252,30 @@ private function getItemWithProductSelected(string $productVariantDescriptor): N private function clickOnTabAndWait(string $tabName): void { - if (!$this->getDriver() instanceof Selenium2Driver && !$this->getDriver() instanceof ChromeDriver) { - return; - } - + /** @var NodeElement $tab */ $tab = $this->getDocument()->find('css', sprintf('.title:contains("%s")', $tabName)); - if ($tab->hasClass('active')) { return; } $tab->click(); - $this->getDocument()->waitFor(5, function () use ($tabName) { - return $this - ->getDocument() - ->find('css', sprintf('.title:contains("%s") + .content', $tabName)) - ->hasClass('active') - ; - }); + /** @var NodeElement $tabContent */ + $tabContent = $this->getDocument()->find('css', sprintf('.title:contains("%s") + .content', $tabName)); + + $this->getDocument()->waitFor(5, fn () => $tabContent->hasClass('active')); } private function waitForFormToLoad(): void { - $form = $this->getDocument()->find('css', '[name="sylius_admin_order_creation_new_order"]'); - $this->getDocument()->waitFor(1000, function () use ($form) { - return !$form->hasClass('loading'); - }); + JQueryHelper::waitForAsynchronousActionsToFinish($this->getSession()); } public function isAddPaymentButtonVisible(): bool { - return - $this->getElement('payments')->find('css', '[data-form-collection="add"]')->isVisible() - ; + /** @var NodeElement $paymentButton */ + $paymentButton = $this->getElement('payments')->find('css', '[data-form-collection="add"]'); + + return $paymentButton->isVisible(); } } diff --git a/tests/Behat/Element/Admin/OrderCreateFormElementInterface.php b/tests/Behat/Element/Admin/OrderCreateFormElementInterface.php index 43de22cc..6771e788 100644 --- a/tests/Behat/Element/Admin/OrderCreateFormElementInterface.php +++ b/tests/Behat/Element/Admin/OrderCreateFormElementInterface.php @@ -8,9 +8,7 @@ interface OrderCreateFormElementInterface { - public function addProduct(string $productVariantDescriptor): void; - - public function addMultipleProducts(string $productVariantDescriptor, int $quantity): void; + public function addProductWithQuantity(string $productVariantDescriptor, int $quantity): void; public function removeProduct(string $productVariantDescriptor): void; diff --git a/tests/Behat/Element/Element.php b/tests/Behat/Element/Element.php index 693e8516..bb5f394e 100644 --- a/tests/Behat/Element/Element.php +++ b/tests/Behat/Element/Element.php @@ -4,6 +4,7 @@ namespace Tests\Sylius\AdminOrderCreationPlugin\Behat\Element; +use ArrayAccess; use Behat\Mink\Driver\DriverInterface; use Behat\Mink\Element\DocumentElement; use Behat\Mink\Element\NodeElement; @@ -13,18 +14,12 @@ abstract class Element { - /** @var Session */ - private $session; - - private $parameters; + private ?DocumentElement $document = null; - /** @var DocumentElement|null */ - private $document; - - public function __construct(Session $session, $parameters = []) - { - $this->session = $session; - $this->parameters = $parameters; + public function __construct( + private Session $session, + private ArrayAccess $parameters, + ) { } protected function getParameter(string $name): NodeElement @@ -49,7 +44,7 @@ protected function getElement(string $name, array $parameters = []): NodeElement $this->getSession(), sprintf('Element named "%s" with parameters %s', $name, implode(', ', $parameters)), 'xpath', - $element->getXpath() + $element->getXpath(), ); } @@ -88,7 +83,7 @@ private function createElement(string $name, array $parameters = []): NodeElemen throw new \InvalidArgumentException(sprintf( 'Could not find a defined element with name "%s". The defined ones are: %s.', $name, - implode(', ', array_keys($definedElements)) + implode(', ', array_keys($definedElements)), )); } @@ -96,7 +91,7 @@ private function createElement(string $name, array $parameters = []): NodeElemen return new NodeElement( $this->getSelectorAsXpath($elementSelector, $this->session->getSelectorsHandler()), - $this->session + $this->session, ); } @@ -115,9 +110,10 @@ private function resolveParameters(string $name, array $parameters, array $defin } array_map( - function ($definedElement) use ($parameters): string { + static function ($definedElement) use ($parameters): string { return strtr($definedElement, $parameters); - }, $definedElements[$name] + }, + $definedElements[$name], ); return $definedElements[$name]; diff --git a/tests/Behat/Page/Admin/NewOrderCustomerPage.php b/tests/Behat/Page/Admin/NewOrderCustomerPage.php index 613b13b3..c101835c 100644 --- a/tests/Behat/Page/Admin/NewOrderCustomerPage.php +++ b/tests/Behat/Page/Admin/NewOrderCustomerPage.php @@ -11,18 +11,13 @@ final class NewOrderCustomerPage extends SymfonyPage implements NewOrderCustomerPageInterface { - /** @var AutoCompleteSelector */ - private $autoCompleteSelector; - public function __construct( Session $session, $parameters, RouterInterface $router, - AutoCompleteSelector $autoCompleteSelector + private AutoCompleteSelector $autoCompleteSelector, ) { parent::__construct($session, $parameters, $router); - - $this->autoCompleteSelector = $autoCompleteSelector; } public function getRouteName(): string @@ -32,7 +27,7 @@ public function getRouteName(): string public function selectCustomer(string $customerEmail): void { - $this->autoCompleteSelector->selectOption($this->getDocument(), $customerEmail); + $this->autoCompleteSelector->selectOption($this->getSession(), $this->getDocument(), $customerEmail); } public function next(): void @@ -50,7 +45,7 @@ public function selectChannel(string $channelName): void { $this->getDocument()->selectFieldOption( 'sylius_admin_order_creation_new_order_customer_create_channel', - $channelName + $channelName, ); } diff --git a/tests/Behat/Page/Admin/OrderIndexPage.php b/tests/Behat/Page/Admin/OrderIndexPage.php index 7598be65..c8d5d947 100644 --- a/tests/Behat/Page/Admin/OrderIndexPage.php +++ b/tests/Behat/Page/Admin/OrderIndexPage.php @@ -19,7 +19,7 @@ public function __construct( $parameters, RouterInterface $router, TableAccessorInterface $tableAccessor, - $routeName + $routeName, ) { parent::__construct($session, $parameters, $router, $tableAccessor, $routeName); diff --git a/tests/Behat/Page/Admin/OrderPreviewPage.php b/tests/Behat/Page/Admin/OrderPreviewPage.php index 6f2eacd1..2d0c3585 100644 --- a/tests/Behat/Page/Admin/OrderPreviewPage.php +++ b/tests/Behat/Page/Admin/OrderPreviewPage.php @@ -4,9 +4,7 @@ namespace Tests\Sylius\AdminOrderCreationPlugin\Behat\Page\Admin; -use Behat\Mink\Driver\Selenium2Driver; use Behat\Mink\Element\NodeElement; -use DMore\ChromeDriver\ChromeDriver; use FriendsOfBehat\PageObjectExtension\Page\SymfonyPage; final class OrderPreviewPage extends SymfonyPage implements OrderPreviewPageInterface @@ -18,12 +16,18 @@ public function getRouteName(): string public function getTotal(): string { - return str_replace('Order total: ', '', $this->getDocument()->find('css', 'td#total')->getText()); + /** @var NodeElement $totalCell */ + $totalCell = $this->getDocument()->find('css', 'td#total'); + + return str_replace('Order total: ', '', $totalCell->getText()); } public function getShippingTotal(): string { - return str_replace('Shipping total: ', '', $this->getDocument()->find('css', 'td#shipping-total')->getText()); + /** @var NodeElement $shippingTotalCell */ + $shippingTotalCell = $this->getDocument()->find('css', 'td#shipping-total'); + + return str_replace('Shipping total: ', '', $shippingTotalCell->getText()); } public function hasProduct(string $productName): bool @@ -56,6 +60,7 @@ public function hasOrderDiscountValidationMessage(string $message): bool public function hasItemDiscountValidationMessage(string $productCode, string $message): bool { + /** @var NodeElement $item */ $item = $this->getDocument()->find('css', sprintf('table tr:contains("%s") + tr', $productCode)); return null !== $item->find('css', sprintf('.sylius-validation-error:contains("%s")', $message)); @@ -66,7 +71,7 @@ public function hasLocale(string $localeName): bool /** @var NodeElement $localeElement */ $localeElement = $this->getDocument()->find('css', '#sylius-order-locale-code'); - return strpos($localeElement->getText(), $localeName) !== false; + return str_contains($localeElement->getText(), $localeName); } public function hasCurrency(string $currencyName): bool @@ -74,54 +79,41 @@ public function hasCurrency(string $currencyName): bool /** @var NodeElement $localeElement */ $localeElement = $this->getDocument()->find('css', '#sylius-order-currency'); - return strpos($localeElement->getText(), $currencyName) !== false; + return str_contains($localeElement->getText(), $currencyName); } public function lowerOrderPriceBy(string $discount): void { + /** @var NodeElement $discountCollection */ $discountCollection = $this->getDocument()->find('css', '#sylius_admin_order_creation_new_order_adjustments'); $discountCollection->clickLink('Add discount'); - $this->getDocument()->waitFor(1, function () use ($discountCollection) { - return $discountCollection->has('css', '[data-form-collection="item"]'); - }); + $this->getDocument()->waitFor(1, fn () => $discountCollection->has('css', '[data-form-collection="item"]')); $discountCollection->fillField('Order discount', $discount); } public function lowerItemWithProductPriceBy(string $productCode, string $discount): void { + /** @var NodeElement $item */ $item = $this->getDocument()->find('css', sprintf('table tr:contains("%s") + tr', $productCode)); $item->clickLink('Add discount'); + /** @var NodeElement $discountCollection */ $discountCollection = $item->find('css', '[data-form-type="collection"]'); - $this->getDocument()->waitFor(1, function () use ($discountCollection) { - return $discountCollection->has('css', '[data-form-collection="item"]'); - }); + $this->getDocument()->waitFor(1, fn () => $discountCollection->has('css', '[data-form-collection="item"]')); $discountCollection->fillField('Item discount', $discount); } public function confirm(): void { - $confirmButton = $this->getDocument()->findButton('Confirm'); - - if ($this->getDriver() instanceof Selenium2Driver || $this->getDriver() instanceof ChromeDriver) { - $confirmButton->focus(); - } - - $confirmButton->press(); + $this->getDocument()->pressButton('Confirm'); } public function goBack(): void { - $backButton = $this->getDocument()->findButton('Back'); - - if ($this->getDriver() instanceof Selenium2Driver || $this->getDriver() instanceof ChromeDriver) { - $backButton->focus(); - } - - $backButton->press(); + $this->getDocument()->pressButton('Back'); } } diff --git a/tests/Behat/Resources/services.xml b/tests/Behat/Resources/services.xml index 6af58e09..69ec3b9b 100644 --- a/tests/Behat/Resources/services.xml +++ b/tests/Behat/Resources/services.xml @@ -24,7 +24,6 @@ - diff --git a/tests/Behat/Resources/suites/admin_reordering.yml b/tests/Behat/Resources/suites/admin_reordering.yml index cc209beb..409812f1 100644 --- a/tests/Behat/Resources/suites/admin_reordering.yml +++ b/tests/Behat/Resources/suites/admin_reordering.yml @@ -38,4 +38,4 @@ default: - Tests\Sylius\AdminOrderCreationPlugin\Behat\Context\Admin\ManagingOrdersContext filters: - tags: "@admin_order_creation_admin_reordering && @ui" + tags: "@admin_order_creation_admin_reordering&&@ui" diff --git a/tests/Behat/Resources/suites/managing_orders.yml b/tests/Behat/Resources/suites/managing_orders.yml index e5d728bd..b53019d4 100644 --- a/tests/Behat/Resources/suites/managing_orders.yml +++ b/tests/Behat/Resources/suites/managing_orders.yml @@ -56,4 +56,4 @@ default: - Tests\Sylius\AdminOrderCreationPlugin\Behat\Context\Admin\ManagingOrdersContext filters: - tags: "@admin_order_creation_managing_orders && @ui" + tags: "@admin_order_creation_managing_orders&&@ui" diff --git a/tests/Behat/Service/AutoCompleteSelector.php b/tests/Behat/Service/AutoCompleteSelector.php index 8b9b0fd6..3fb674e7 100644 --- a/tests/Behat/Service/AutoCompleteSelector.php +++ b/tests/Behat/Service/AutoCompleteSelector.php @@ -5,41 +5,27 @@ namespace Tests\Sylius\AdminOrderCreationPlugin\Behat\Service; use Behat\Mink\Element\ElementInterface; -use Behat\Testwork\Call\Exception\FatalThrowableError; +use Behat\Mink\Element\NodeElement; +use Behat\Mink\Session; +use Sylius\Behat\Service\AutocompleteHelper; +use Sylius\Behat\Service\JQueryHelper; final class AutoCompleteSelector { - public function selectOption(ElementInterface $scope, string $optionName): void + public function selectOption(Session $session, ElementInterface $scope, string $optionName): void { - $this->waitForItemsToLoad($scope); - - $scope->waitFor(10, function () use ($scope, $optionName) { - try { - $scope->find('css', sprintf('.sylius-autocomplete .menu .item:contains("%s")', $optionName))->click(); - - return true; - } catch (FatalThrowableError $exception) { - return false; - } - }); + /** @var NodeElement $autocomplete */ + $autocomplete = $scope->find('css', '.sylius-autocomplete'); + AutocompleteHelper::chooseValue($session, $autocomplete, $optionName); } - public function areItemsVisible(ElementInterface $scope): bool + public function areItemsVisible(Session $session, ElementInterface $scope): bool { - $this->waitForItemsToLoad($scope); + JQueryHelper::waitForAsynchronousActionsToFinish($session); - return strpos($scope->find('css', '.sylius-autocomplete .menu')->getText(), 'No results found') !== false; - } - - private function waitForItemsToLoad(ElementInterface $scope): void - { - $scope->find('css', '.sylius-autocomplete .icon')->click(); + /** @var NodeElement $menu */ + $menu = $scope->find('css', '.sylius-autocomplete .menu'); - $scope->waitFor(10, function() use ($scope) { - return $scope - ->find('css', '.sylius-autocomplete .menu') - ->hasClass('visible') - ; - }); + return str_contains($menu->getText(), 'No results found'); } }