From c7e71a952f76022219678fd84b741a80f95bccc8 Mon Sep 17 00:00:00 2001 From: Michael Telgmann Date: Fri, 6 Dec 2024 16:16:05 +0100 Subject: [PATCH] chore: Update cs-fixer and fix PHPStan issues --- tests/.php-cs-fixer.php | 29 +- tests/Component/Api/ApiClient.php | 514 ++++++-------- tests/Component/SpinTrait/SpinTrait.php | 8 +- .../XpathBuilder/BackendXpathBuilder.php | 9 +- .../XpathBuilder/BaseXpathBuilder.php | 33 +- .../XpathBuilder/FrontendXpathBuilder.php | 19 +- tests/Context/ApiContext.php | 34 +- tests/Context/BackendArticleContext.php | 85 +-- tests/Context/BackendCustomerContext.php | 3 +- tests/Context/BackendOrderContext.php | 22 +- tests/Context/BackendQuestionMarkContext.php | 5 +- tests/Context/BackendVoucherContext.php | 7 +- tests/Context/DebugContext.php | 35 +- .../Exception/PageNotDefinedException.php | 6 +- tests/Context/FileCheckContext.php | 8 +- tests/Context/FrontendCheckoutContext.php | 5 +- tests/Context/FrontendContext.php | 7 +- tests/Context/FrontendDetailContext.php | 57 +- tests/Context/GeneralContext.php | 4 +- tests/Context/InstallerContext.php | 2 +- tests/Context/ProductExportContext.php | 5 +- tests/Context/SubContext.php | 8 +- tests/Context/SubshopContext.php | 20 +- tests/Context/UpdaterContext.php | 26 +- tests/Element/Backend/ExtJsElement.php | 5 +- tests/Element/Backend/Form/Checkbox.php | 7 +- tests/Element/Backend/Form/Combobox.php | 24 +- tests/Element/Backend/Form/Selecttree.php | 35 +- tests/Element/Backend/GridView/GridView.php | 5 +- .../Element/Backend/GridView/GridViewRow.php | 4 +- tests/Element/Backend/Window.php | 39 +- .../Frontend/Checkout/CartPosition.php | 47 +- tests/Page/Backend/BackendModule.php | 45 +- tests/Page/Backend/CustomerModule.php | 33 +- tests/Page/Backend/ExistingArticleModule.php | 68 +- tests/Page/Backend/NewArticleModule.php | 153 ++--- tests/Page/Backend/PaymentModule.php | 3 +- tests/Page/Backend/ProductExportModule.php | 44 +- tests/Page/Backend/QuestionMarkModule.php | 2 +- tests/Page/Backend/SettingsModule.php | 6 +- tests/Page/Backend/ShippingModule.php | 58 +- tests/Page/Backend/SystemInfoModule.php | 18 +- tests/Page/Backend/VoucherModule.php | 12 +- tests/Page/ContextAwarePage.php | 75 +- tests/Page/Frontend/Account.php | 9 +- tests/Page/Frontend/CheckoutCart.php | 143 ++-- tests/Page/Frontend/CheckoutConfirm.php | 10 +- .../Page/Frontend/CheckoutShippingPayment.php | 18 +- tests/Page/Frontend/Detail.php | 33 +- tests/Page/Frontend/Index.php | 26 +- tests/Page/Installer/InstallerIndex.php | 37 +- tests/Page/Updater/UpdaterIndex.php | 6 - tests/behat | 2 +- tests/phpstan-baseline.neon | 638 +----------------- tests/phpstan.neon | 5 + 55 files changed, 840 insertions(+), 1721 deletions(-) diff --git a/tests/.php-cs-fixer.php b/tests/.php-cs-fixer.php index 237002d..092c344 100644 --- a/tests/.php-cs-fixer.php +++ b/tests/.php-cs-fixer.php @@ -1,13 +1,17 @@ registerCustomFixers(new Fixers()) ->setRiskyAllowed(true) + ->setParallelConfig(ParallelConfigFactory::detect()) ->setRules([ '@PSR12' => true, '@Symfony' => true, @@ -28,27 +33,41 @@ 'doctrine_annotation_indentation' => true, 'doctrine_annotation_spaces' => true, 'general_phpdoc_annotation_remove' => [ - 'annotations' => ['copyright', 'category'], + 'annotations' => ['copyright', 'category'], ], + 'global_namespace_import' => true, + 'modernize_types_casting' => true, + 'native_function_invocation' => ['exclude' => ['ini_get'], 'strict' => false], + 'no_alias_functions' => true, 'no_useless_else' => true, 'no_useless_return' => true, 'no_superfluous_phpdoc_tags' => true, + 'nullable_type_declaration_for_default_null_value' => true, + 'operator_linebreak' => ['only_booleans' => true], + 'ordered_class_elements' => true, 'phpdoc_line_span' => true, 'phpdoc_order' => true, + 'phpdoc_separation' => ['groups' => [['ORM\*', 'Assert\*', 'ShopwareAssert\*'], ['deprecated', 'link', 'see', 'since'], ['author', 'copyright', 'license'], ['category', 'package', 'subpackage'], ['property', 'property-read', 'property-write']]], 'phpdoc_summary' => false, 'phpdoc_var_annotation_correct_order' => true, + 'php_unit_dedicate_assert' => true, + 'php_unit_dedicate_assert_internal_type' => true, + 'php_unit_construct' => true, + 'php_unit_mock' => true, + 'php_unit_mock_short_will_return' => true, 'php_unit_test_case_static_method_calls' => true, 'single_line_throw' => false, 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], - 'operator_linebreak' => ['only_booleans' => true], - 'native_function_invocation' => true, NoUselessCommentFixer::name() => true, SingleSpaceAfterStatementFixer::name() => true, SingleSpaceBeforeStatementFixer::name() => true, PhpdocParamTypeFixer::name() => true, - NoSuperfluousConcatenationFixer::name() => true, NoUselessStrlenFixer::name() => true, NoUselessParenthesisFixer::name() => true, + PhpUnitDedicatedAssertFixer::name() => true, + PhpUnitAssertArgumentsOrderFixer::name() => true, + PhpdocNoIncorrectVarAnnotationFixer::name() => true, + NoUselessDirnameCallFixer::name() => true, ]) ->setFinder($finder); diff --git a/tests/Component/Api/ApiClient.php b/tests/Component/Api/ApiClient.php index 028f235..1662993 100644 --- a/tests/Component/Api/ApiClient.php +++ b/tests/Component/Api/ApiClient.php @@ -4,8 +4,11 @@ namespace Shopware\Component\Api; +use Exception; use Faker\Factory as FakerFactory; +use Faker\Generator; use GuzzleHttp\Client as Guzzle; +use RuntimeException; class ApiClient { @@ -17,51 +20,35 @@ class ApiClient public const METHOD_POST = 'POST'; public const METHOD_DELETE = 'DELETE'; - private $validMethods = [ + private array $validMethods = [ self::METHOD_GET, self::METHOD_PUT, self::METHOD_POST, self::METHOD_DELETE, ]; - /** - * @var string - */ - private $apiUrl; + private string $apiUrl; - /** - * @var string - */ - private $assetUrl; + private string $assetUrl; - /** - * @var array - */ - private $auth; + private array $auth; - /** - * @var \Faker\Generator - */ - private $faker; + private Generator $faker; - /** - * @param string $apiUrl - * @param string $assetUrl - * @param string $username - * @param string $apiKey - */ - public function __construct($apiUrl, $assetUrl, $username, $apiKey) + private Guzzle $client; + + public function __construct(string $apiUrl, string $assetUrl, string $username, string $apiKey) { $this->apiUrl = rtrim($apiUrl, '/') . '/'; $this->assetUrl = rtrim($assetUrl, '/') . '/'; $this->client = new Guzzle(); if (empty($username)) { - throw new \RuntimeException('Missing API username.'); + throw new RuntimeException('Missing API username.'); } if (empty($apiKey)) { - throw new \RuntimeException('Missing API password.'); + throw new RuntimeException('Missing API password.'); } $this->auth = [$username, $apiKey, 'basic']; @@ -71,57 +58,38 @@ public function __construct($apiUrl, $assetUrl, $username, $apiKey) /** * Perform GET request on API - * - * @param string $url - * @param array $params - * - * @return array */ - public function get($url, $params = []) + public function get(string $url, array $params = []): array { return $this->call($url, self::METHOD_GET, [], $params); } /** * Perform POST request on API - * - * @param array $data - * @param array $params - * - * @return array */ - public function post($url, $data = [], $params = []) + public function post(string $url, array $data = [], array $params = []): array { return $this->call($url, self::METHOD_POST, ['json' => $data], $params); } /** * Perform PUT request on API - * - * @param array $data - * @param array $params - * - * @return array */ - public function put($url, $data = [], $params = []) + public function put(string $url, array $data = [], array $params = []): array { return $this->call($url, self::METHOD_PUT, $data, $params); } /** * Perform DELETE request on API - * - * @param array $params - * - * @return array */ - public function delete($url, $params = []) + public function delete(string $url, array $params = []): array { return $this->call($url, self::METHOD_DELETE, [], $params); } /** - * @throws \Exception + * @throws Exception */ public function articleExistsByName(string $name): bool { @@ -140,7 +108,7 @@ public function articleExistsByName(string $name): bool * * @return int the ID of the created product */ - public function createArticle($product) + public function createArticle(array $product): int { $categories = $product['categories']; $categoryIds = []; @@ -150,19 +118,17 @@ public function createArticle($product) $response = $this->post('api/articles', $this->buildArticleDataArray($product, $categoryIds)); - return $response['data']['id']; + return (int) $response['data']['id']; } /** * @param string $categoryTrees Trees delimited by ; and Categories delimited by > - * - * @return array */ - public function createCategoryTrees($categoryTrees) + public function createCategoryTrees(string $categoryTrees): array { - $categoryTrees = explode(';', $categoryTrees); + $categoryTreesArray = explode(';', $categoryTrees); $categoryIds = []; - foreach ($categoryTrees as $categoryTree) { + foreach ($categoryTreesArray as $categoryTree) { $categoryIds[] = $this->createCategoryTree(trim($categoryTree)); } @@ -170,21 +136,19 @@ public function createCategoryTrees($categoryTrees) } /** - * @throws \RuntimeException - * - * @return int + * @throws RuntimeException */ - public function createCategoryTree($categories) + public function createCategoryTree(string $categories): int { - $categories = explode('>', $categories); - $rootCategory = trim(array_shift($categories)); + $categoriesArray = explode('>', $categories); + $rootCategory = trim(array_shift($categoriesArray)); if ($rootCategory !== 'Root') { - throw new \RuntimeException('The first element of a category path has to be Root.'); + throw new RuntimeException('The first element of a category path has to be Root.'); } $parentId = 1; - foreach ($categories as $category) { + foreach ($categoriesArray as $category) { $category = trim($category); $existsResponse = $this->get('api/categories', [ 'filter' => [ @@ -200,8 +164,7 @@ public function createCategoryTree($categories) } if ($existsResponse['total'] > 1) { - throw new \RuntimeException(\sprintf('There are multiple definitions for "%s" with parent id %i.', - $category, $parentId)); + throw new RuntimeException(\sprintf('There are multiple definitions for "%s" with parent id %s.', $category, $parentId)); } $parentId = $existsResponse['data'][0]['id']; @@ -210,89 +173,11 @@ public function createCategoryTree($categories) return $parentId; } - /** - * @param string $name - * @param int $parentId - * - * @return array - */ - private function createCategory($name, $parentId) - { - return $this->post('api/categories', [ - 'parentId' => $parentId, - 'name' => $name, - ]); - } - - /** - * @return array - */ - private function buildArticleDataArray(array $product, array $categories) - { - $this->throwExceptionWhenEmpty($product, ['name']); - - $faker = $this->faker; - - $articleData = [ - 'name' => $product['name'], - 'active' => \array_key_exists('active', $product) ? $product['active'] : true, - 'description' => \array_key_exists('description', - $product) ? $product['description'] : $faker->realText($faker->numberBetween(10, 20)), - 'description_long' => \array_key_exists('description_long', - $product) ? $product['description_long'] : $faker->realText($faker->numberBetween(50, 200)), - 'tax' => \array_key_exists('tax', $product) ? $product['tax'] : 19, - 'supplier' => \array_key_exists('supplier', $product) ? $product['supplier'] : 'NoName GmbH', - 'priceGroupId' => \array_key_exists('priceGroupId', $product) ? $product['priceGroupId'] : 1, - - 'images' => [ - ['link' => $this->assetUrl . '800x600/' . urlencode($product['name']) . '.jpg'], - ], - - 'mainDetail' => [ - 'number' => \array_key_exists('number', $product) ? $product['number'] : 'swTEST' . uniqid(), - 'inStock' => \array_key_exists('inStock', $product) ? $product['inStock'] : 16, - 'active' => \array_key_exists('active', $product) ? $product['active'] : true, - 'prices' => [ - [ - 'customerGroupKey' => \array_key_exists('customerGroupKey', - $product) ? $product['customerGroupKey'] : 'EK', - 'price' => \array_key_exists('price', $product) ? $product['price'] : 99.34, - ], - ], - ], - ]; - if (!empty($categories)) { - $articleData['categories'] = []; - foreach ($categories as $category) { - $articleData['categories'][] = ['id' => $category]; - } - } - - return $articleData; - } - - /** - * @throws \Exception - */ - private function throwExceptionWhenEmpty(array $array, array $expectedFields) - { - foreach ($expectedFields as $field) { - if (empty($array[$field])) { - throw new \Exception("Field $field is required."); - } - } - } - - /** - * @param string $email - * - * @return bool - */ - public function customerExists($email) + public function customerExists(string $email): bool { $response = $this->get('api/customers', [ 'filter' => [ - 'email' => (string) $email, + 'email' => $email, ], 'limit' => 1, ]); @@ -303,7 +188,7 @@ public function customerExists($email) /** * @return int ID of the customer that was created */ - public function createCustomer(array $customer) + public function createCustomer(array $customer): int { $this->throwExceptionWhenEmpty($customer, ['email', 'password']); $response = $this->post('api/customers', $this->buildCustomerDataArray($customer)); @@ -311,74 +196,23 @@ public function createCustomer(array $customer) return $response['data']['id']; } - /** - * @return array - */ - private function buildCustomerDataArray(array $customer) - { - $faker = $this->faker; - $birthday = $faker->dateTimeBetween('-70 years', '-18 years')->format($faker->iso8601); - - return [ - 'paymentId' => \array_key_exists('paymentId', $customer) ? $customer['paymentId'] : 5, - 'groupKey' => \array_key_exists('groupKey', $customer) ? $customer['groupKey'] : 'EK', - 'shopId' => \array_key_exists('shopId', $customer) ? $customer['shopId'] : 1, - 'priceGroupId' => \array_key_exists('priceGroupId', $customer) ? $customer['active'] : null, - 'encoderName' => \array_key_exists('encoderName', $customer) ? $customer['encoderName'] : 'bcrypt', - 'password' => $customer['password'], - 'active' => \array_key_exists('active', $customer) ? $customer['active'] : true, - 'email' => $customer['email'], - 'paymentPreset' => \array_key_exists('paymentPreset', $customer) ? $customer['paymentPreset'] : 5, - 'languageId' => \array_key_exists('languageId', $customer) ? $customer['languageId'] : '1', - 'salutation' => \array_key_exists('salutation', $customer) ? $customer['salutation'] : 'mr', - 'title' => \array_key_exists('title', $customer) ? $customer['title'] : '', - 'firstname' => \array_key_exists('firstname', $customer) ? $customer['firstname'] : $faker->firstName, - 'lastname' => \array_key_exists('lastname', $customer) ? $customer['lastname'] : $faker->lastName, - 'birthday' => \array_key_exists('birthday', $customer) ? $customer['birthday'] : $birthday, - 'country' => \array_key_exists('country', $customer) ? $customer['country'] : 2, - 'street' => \array_key_exists('street', - $customer) ? $customer['street'] : $faker->streetName . ' ' . rand(1, - 101), - 'city' => \array_key_exists('city', $customer) ? $customer['city'] : $faker->city, - 'zipcode' => \array_key_exists('zip', $customer) ? $customer['zip'] : rand(11111, 99999), - 'billing' => [ - 'salutation' => \array_key_exists('salutation', $customer) ? $customer['salutation'] : 'mr', - 'title' => \array_key_exists('title', $customer) ? $customer['title'] : '', - 'firstname' => \array_key_exists('firstname', $customer) ? $customer['firstname'] : $faker->firstName, - 'lastname' => \array_key_exists('lastname', $customer) ? $customer['lastname'] : $faker->lastName, - 'birthday' => \array_key_exists('birthday', $customer) ? $customer['birthday'] : $birthday, - 'street' => \array_key_exists('street', - $customer) ? $customer['street'] : $faker->streetName . ' ' . rand(1, 101), - 'city' => \array_key_exists('city', $customer) ? $customer['city'] : $faker->city, - 'zipcode' => \array_key_exists('zip', $customer) ? $customer['zip'] : rand(11111, 99999), - 'country' => \array_key_exists('country', $customer) ? $customer['country'] : 2, - ], - ]; - } - /** * Get the internal country id for a given ISO * - * @param string $iso - * - * @throws \Exception - * - * @return int + * @throws Exception */ - public function getCountryIdByISO($iso) + public function getCountryIdByISO(string $iso): int { - $countries = $this->get('api/countries')['data']; - - foreach ($countries as $country) { + foreach ($this->get('api/countries')['data'] as $country) { if (\array_key_exists('iso', $country) && $country['iso'] === $iso) { return $country['id']; } } - throw new \Exception('Could not find country by ISO ' . $iso); + throw new Exception('Could not find country by ISO ' . $iso); } - public function setCountryData(array $data) + public function setCountryData(array $data): void { $countries = []; @@ -418,7 +252,7 @@ public function setCountryData(array $data) $this->put('api/countries/' . $country['id'], ['json' => $data]); ++$countriesFound; } - if ($countryCount == $countriesFound) { + if ($countryCount === $countriesFound) { break; } } @@ -427,7 +261,7 @@ public function setCountryData(array $data) /** * Create a new order */ - public function createOrder(array $orderData) + public function createOrder(array $orderData): void { if ($this->customerExists($orderData['customer.email'])) { $this->deleteCustomerByEmail($orderData['customer.email']); @@ -510,72 +344,20 @@ public function createOrder(array $orderData) ]); } - /** - * @return bool - */ - public function customerGroupExistsByKey($key) + public function customerGroupExistsByKey($key): bool { $id = $this->getCustomerGroupIdByKey($key); - if ($id === null) { - return false; - } - - return true; + return $id !== null; } - /** - * @param string $key - * - * @throws \Exception - * - * @return int|null - */ - private function getCustomerGroupIdByKey($key) - { - $response = $this->get('api/customerGroups', [ - 'filter' => [ - 'key' => (string) $key, - ], - 'limit' => 1, - ]); - - if ($response['success'] !== true) { - throw new \Exception('API communication unsuccessful: ' . print_r($response, true)); - } - - if ($response['total'] === 0) { - return null; - } - - return (int) $response['data'][0]['id']; - } - - public function createCustomerGroup($customerGroup) + public function createCustomerGroup(array $customerGroup): void { $this->throwExceptionWhenEmpty($customerGroup, ['key', 'name']); $this->post('api/customerGroups', $this->buildCustomerGroupDataArray($customerGroup)); } - /** - * @return array - */ - private function buildCustomerGroupDataArray(array $group) - { - return [ - 'key' => $group['key'], - 'name' => $group['name'], - 'tax' => \array_key_exists('tax', $group) ? $group['tax'] : true, - 'taxInput' => \array_key_exists('taxInput', $group) ? $group['taxInput'] : true, - 'mode' => \array_key_exists('mode', $group) ? $group['mode'] : false, - 'discount' => \array_key_exists('discount', $group) ? $group['discount'] : 0, - 'minimumOrder' => \array_key_exists('minimumOrder', $group) ? $group['minimumOrder'] : 10, - 'minimumOrderSurcharge' => \array_key_exists('minimumOrderSurcharge', - $group) ? $group['minimumOrderSurcharge'] : 5, - ]; - } - - public function updateCustomerGroup($customerGroup) + public function updateCustomerGroup(array $customerGroup): void { $this->throwExceptionWhenEmpty($customerGroup, ['key', 'name']); @@ -587,18 +369,16 @@ public function updateCustomerGroup($customerGroup) /** * Deletes the user account associated with the given e-mail address - * - * @param string $email */ - public function deleteCustomerByEmail($email) + public function deleteCustomerByEmail(string $email): void { $response = $this->get('api/customers', [ 'filter' => [ - 'email' => (string) $email, + 'email' => $email, ], 'limit' => 1, ]); - if ($response['total'] == 0) { + if ((int) $response['total'] === 0) { return; } $this->deleteCustomerById((int) $response['data'][0]['id']); @@ -607,7 +387,7 @@ public function deleteCustomerByEmail($email) /** * Helper function that deletes all existing customers */ - public function deleteAllCustomers() + public function deleteAllCustomers(): void { $response = $this->get('api/customers'); foreach ($response['data'] as $customer) { @@ -617,26 +397,21 @@ public function deleteAllCustomers() /** * Deletes the user account with the given id - * - * @param int $id */ - public function deleteCustomerById($id) + public function deleteCustomerById(int $id): void { $this->delete('api/customers/' . $id); } /** - * @param string $method - * @param array $data - * @param array $params - * @param int $retries Number of times the request is repeated if it was unsuccessful + * @param int $retries Number of times the request is repeated if it was unsuccessful * - * @throws \Exception + * @throws Exception */ - public function call($url, $method = self::METHOD_GET, $data = [], $params = [], $retries = 1) + public function call(string $url, string $method = self::METHOD_GET, array $data = [], array $params = [], int $retries = 1): array { - if (!\in_array($method, $this->validMethods)) { - throw new \Exception('Invalid HTTP-Method: ' . $method); + if (!\in_array($method, $this->validMethods, true)) { + throw new Exception('Invalid HTTP-Method: ' . $method); } $queryString = ''; @@ -650,8 +425,6 @@ public function call($url, $method = self::METHOD_GET, $data = [], $params = [], $data['auth'] = $this->auth; $data['debug'] = false; - $response = null; - // Retry API requests for enhanced test stability do { $response = $this->client->request($method, $url, $data); @@ -659,16 +432,33 @@ public function call($url, $method = self::METHOD_GET, $data = [], $params = [], --$retries; } while ($statusCode !== 200 && $retries > 0); - $httpCode = $response->getStatusCode(); $result = $response->getBody()->getContents(); - return $this->prepareResponse($result, $httpCode); + return $this->prepareResponse($result); + } + + /** + * @throws Exception + */ + public function createProperty(array $property): void + { + $propertiesArray = [ + 'name' => $property['set'], + 'position' => 1, + 'comparable' => 1, + 'sortmode' => 1, + ]; + $this->post('api/propertyGroups', $propertiesArray); + + $this->throwExceptionWhenEmpty($property, ['key', 'set', 'group', 'option']); + + $this->post('api/articles', $this->buildPropertyDataArray($property)); } /** - * @throws \Exception + * @throws Exception */ - protected function prepareResponse($result, $httpCode) + protected function prepareResponse(string $result): array { if (null === $decodedResult = json_decode($result, true)) { $jsonErrors = [ @@ -681,44 +471,162 @@ protected function prepareResponse($result, $httpCode) $error .= 'json_last_error: ' . $jsonErrors[json_last_error()]; $error .= '
Raw:
'; $error .= '
' . print_r($result, true) . '
'; - throw new \Exception($error); + throw new Exception($error); } if (!isset($decodedResult['success'])) { - throw new \Exception('Invalid Response'); + throw new Exception('Invalid Response'); } if (!$decodedResult['success']) { $error = '

No Success

'; $error .= '

' . $decodedResult['message'] . '

'; - throw new \Exception($error); + throw new Exception($error); } return $decodedResult; } + private function createCategory(string $name, int $parentId): array + { + return $this->post('api/categories', [ + 'parentId' => $parentId, + 'name' => $name, + ]); + } + + private function buildArticleDataArray(array $product, array $categories): array + { + $this->throwExceptionWhenEmpty($product, ['name']); + + $faker = $this->faker; + + $articleData = [ + 'name' => $product['name'], + 'active' => \array_key_exists('active', $product) ? $product['active'] : true, + 'description' => \array_key_exists('description', + $product) ? $product['description'] : $faker->realText($faker->numberBetween(10, 20)), + 'description_long' => \array_key_exists('description_long', + $product) ? $product['description_long'] : $faker->realText($faker->numberBetween(50, 200)), + 'tax' => \array_key_exists('tax', $product) ? $product['tax'] : 19, + 'supplier' => \array_key_exists('supplier', $product) ? $product['supplier'] : 'NoName GmbH', + 'priceGroupId' => \array_key_exists('priceGroupId', $product) ? $product['priceGroupId'] : 1, + + 'images' => [ + ['link' => $this->assetUrl . '800x600/' . urlencode($product['name']) . '.jpg'], + ], + + 'mainDetail' => [ + 'number' => \array_key_exists('number', $product) ? $product['number'] : 'swTEST' . uniqid(), + 'inStock' => \array_key_exists('inStock', $product) ? $product['inStock'] : 16, + 'active' => \array_key_exists('active', $product) ? $product['active'] : true, + 'prices' => [ + [ + 'customerGroupKey' => \array_key_exists('customerGroupKey', + $product) ? $product['customerGroupKey'] : 'EK', + 'price' => \array_key_exists('price', $product) ? $product['price'] : 99.34, + ], + ], + ], + ]; + if (!empty($categories)) { + $articleData['categories'] = []; + foreach ($categories as $category) { + $articleData['categories'][] = ['id' => $category]; + } + } + + return $articleData; + } + /** - * @param array $property - * - * @throws \Exception + * @throws Exception */ - public function createProperty($property) + private function throwExceptionWhenEmpty(array $array, array $expectedFields): void { - $propertiesArray = [ - 'name' => $property['set'], - 'position' => 1, - 'comparable' => 1, - 'sortmode' => 1, - ]; - $this->post('api/propertyGroups', $propertiesArray); + foreach ($expectedFields as $field) { + if (empty($array[$field])) { + throw new Exception("Field $field is required."); + } + } + } - $this->throwExceptionWhenEmpty($property, ['key', 'set', 'group', 'option']); + private function buildCustomerDataArray(array $customer): array + { + $faker = $this->faker; + $birthday = $faker->dateTimeBetween('-70 years', '-18 years')->format($faker->iso8601); - $this->post('api/articles', $this->buildPropertyDataArray($property)); + return [ + 'paymentId' => \array_key_exists('paymentId', $customer) ? $customer['paymentId'] : 5, + 'groupKey' => \array_key_exists('groupKey', $customer) ? $customer['groupKey'] : 'EK', + 'shopId' => \array_key_exists('shopId', $customer) ? $customer['shopId'] : 1, + 'priceGroupId' => \array_key_exists('priceGroupId', $customer) ? $customer['active'] : null, + 'encoderName' => \array_key_exists('encoderName', $customer) ? $customer['encoderName'] : 'bcrypt', + 'password' => $customer['password'], + 'active' => \array_key_exists('active', $customer) ? $customer['active'] : true, + 'email' => $customer['email'], + 'paymentPreset' => \array_key_exists('paymentPreset', $customer) ? $customer['paymentPreset'] : 5, + 'languageId' => \array_key_exists('languageId', $customer) ? $customer['languageId'] : '1', + 'salutation' => \array_key_exists('salutation', $customer) ? $customer['salutation'] : 'mr', + 'title' => \array_key_exists('title', $customer) ? $customer['title'] : '', + 'firstname' => \array_key_exists('firstname', $customer) ? $customer['firstname'] : $faker->firstName, + 'lastname' => \array_key_exists('lastname', $customer) ? $customer['lastname'] : $faker->lastName, + 'birthday' => \array_key_exists('birthday', $customer) ? $customer['birthday'] : $birthday, + 'country' => \array_key_exists('country', $customer) ? $customer['country'] : 2, + 'street' => \array_key_exists('street', $customer) ? $customer['street'] : $faker->streetName . ' ' . random_int(1, 101), + 'city' => \array_key_exists('city', $customer) ? $customer['city'] : $faker->city, + 'zipcode' => \array_key_exists('zip', $customer) ? $customer['zip'] : random_int(11111, 99999), + 'billing' => [ + 'salutation' => \array_key_exists('salutation', $customer) ? $customer['salutation'] : 'mr', + 'title' => \array_key_exists('title', $customer) ? $customer['title'] : '', + 'firstname' => \array_key_exists('firstname', $customer) ? $customer['firstname'] : $faker->firstName, + 'lastname' => \array_key_exists('lastname', $customer) ? $customer['lastname'] : $faker->lastName, + 'birthday' => \array_key_exists('birthday', $customer) ? $customer['birthday'] : $birthday, + 'street' => \array_key_exists('street', $customer) ? $customer['street'] : $faker->streetName . ' ' . random_int(1, 101), + 'city' => \array_key_exists('city', $customer) ? $customer['city'] : $faker->city, + 'zipcode' => \array_key_exists('zip', $customer) ? $customer['zip'] : random_int(11111, 99999), + 'country' => \array_key_exists('country', $customer) ? $customer['country'] : 2, + ], + ]; } /** - * @return array + * @throws Exception */ - private function buildPropertyDataArray($group) + private function getCustomerGroupIdByKey(string $key): ?int + { + $response = $this->get('api/customerGroups', [ + 'filter' => [ + 'key' => $key, + ], + 'limit' => 1, + ]); + + if ($response['success'] !== true) { + throw new Exception('API communication unsuccessful: ' . print_r($response, true)); + } + + if ($response['total'] === 0) { + return null; + } + + return (int) $response['data'][0]['id']; + } + + private function buildCustomerGroupDataArray(array $group): array + { + return [ + 'key' => $group['key'], + 'name' => $group['name'], + 'tax' => \array_key_exists('tax', $group) ? $group['tax'] : true, + 'taxInput' => \array_key_exists('taxInput', $group) ? $group['taxInput'] : true, + 'mode' => \array_key_exists('mode', $group) ? $group['mode'] : false, + 'discount' => \array_key_exists('discount', $group) ? $group['discount'] : 0, + 'minimumOrder' => \array_key_exists('minimumOrder', $group) ? $group['minimumOrder'] : 10, + 'minimumOrderSurcharge' => \array_key_exists('minimumOrderSurcharge', + $group) ? $group['minimumOrderSurcharge'] : 5, + ]; + } + + private function buildPropertyDataArray($group): array { return [ 'key' => $group['key'], diff --git a/tests/Component/SpinTrait/SpinTrait.php b/tests/Component/SpinTrait/SpinTrait.php index 9b30b48..c43bc44 100644 --- a/tests/Component/SpinTrait/SpinTrait.php +++ b/tests/Component/SpinTrait/SpinTrait.php @@ -4,6 +4,8 @@ namespace Shopware\Component\SpinTrait; +use Exception; + trait SpinTrait { /** @@ -13,12 +15,12 @@ trait SpinTrait * * @param callable $lambda * - * @throws \Exception + * @throws Exception */ protected function spin($lambda, int $wait = 10): void { if (!$this->spinWithNoException($lambda, $wait)) { - throw new \Exception(\sprintf('Spin function timed out after %s seconds', $wait)); + throw new Exception(\sprintf('Spin function timed out after %s seconds', $wait)); } } @@ -38,7 +40,7 @@ protected function spinWithNoException($lambda, int $wait = 10): bool if ($lambda($this)) { return true; } - } catch (\Exception $e) { + } catch (Exception $e) { // do nothing } diff --git a/tests/Component/XpathBuilder/BackendXpathBuilder.php b/tests/Component/XpathBuilder/BackendXpathBuilder.php index 22056be..cf39f38 100644 --- a/tests/Component/XpathBuilder/BackendXpathBuilder.php +++ b/tests/Component/XpathBuilder/BackendXpathBuilder.php @@ -4,6 +4,9 @@ namespace Shopware\Component\XpathBuilder; +use Exception; +use RuntimeException; + class BackendXpathBuilder extends BaseXpathBuilder { /** @@ -91,19 +94,17 @@ public static function getTabXpathByLabel(string $label): string /** * Return xpath to extJs icon by type * - * @throws \Exception + * @throws Exception */ public static function getIconXpathByType(string $type): string { switch ($type) { case 'edit': return (new self())->child('img', ['~class' => 'sprite-pencil'])->getXpath(); - break; case 'delete': return (new self())->child('img', ['~class' => 'sprite-minus-circle-frame'])->getXpath(); - break; default: - throw new \RuntimeException('Unknown icon type ' . $type); + throw new RuntimeException('Unknown icon type ' . $type); } } diff --git a/tests/Component/XpathBuilder/BaseXpathBuilder.php b/tests/Component/XpathBuilder/BaseXpathBuilder.php index 3d8d0ae..219e8f4 100644 --- a/tests/Component/XpathBuilder/BaseXpathBuilder.php +++ b/tests/Component/XpathBuilder/BaseXpathBuilder.php @@ -4,6 +4,9 @@ namespace Shopware\Component\XpathBuilder; +use Exception; +use RuntimeException; + class BaseXpathBuilder { private string $xpath; @@ -15,10 +18,8 @@ public function __construct(string $xpath = '/') /** * Create and return empty Xpath Builder instance - * - * @return BaseXpathBuilder */ - public static function create(string $xpath = '/') + public static function create(string $xpath = '/'): BaseXpathBuilder { return new self($xpath); } @@ -141,7 +142,7 @@ public static function getContainsAttributeString($string, string $attribute): s * * @param array> $conditions * - * @throws \Exception + * @throws Exception */ protected function parseConditions(array $conditions): string { @@ -156,7 +157,7 @@ protected function parseConditions(array $conditions): string switch ($target) { case 'starts-with': if (!\is_array($condition) || \count($condition) !== 2) { - throw new \Exception('Invalid number of arguments for SubConditionHandler starts-with: ' + throw new Exception('Invalid number of arguments for SubConditionHandler starts-with: ' . "\n" . print_r($target, true) . "\n" . print_r($condition, true) . "\n" . print_r($conditions, true) . "\n"); @@ -165,14 +166,14 @@ protected function parseConditions(array $conditions): string break; case 'ends-with': if (!\is_array($condition) || \count($condition) !== 2) { - throw new \Exception('Invalid number of arguments for SubConditionHandler: ' . $target); + throw new Exception('Invalid number of arguments for SubConditionHandler: ' . $target); } $attr = $condition[0]; $text = $condition[1]; $conditionString .= "'" . $text . "'=substring(" . $attr . ', string-length(' . $attr . ")- string-length('" . $text . "') +1) "; break; default: - throw new \Exception('SubConditionHandler not implemented: ' . $target); + throw new Exception('SubConditionHandler not implemented: ' . $target); } continue; } @@ -197,14 +198,14 @@ protected function parseConditions(array $conditions): string $conditionString .= 'not('; break; default: - throw new \Exception('TargetModifiersPrefixHandler not implemented: ' . $targetModifiersPrefix); + throw new Exception('TargetModifiersPrefixHandler not implemented: ' . $targetModifiersPrefix); } } switch ($targetModifier) { case '@': if (!\is_string($condition)) { - throw new \RuntimeException('condition must be string at this point'); + throw new RuntimeException('condition must be string at this point'); } $conditionString .= $this->equals($target, $condition) . ' '; break; @@ -213,17 +214,13 @@ protected function parseConditions(array $conditions): string break; default: if (!\is_string($condition)) { - throw new \RuntimeException('condition must be string at this point'); + throw new RuntimeException('condition must be string at this point'); } $conditionString .= $condition . ' '; } - if ($targetModifiersPrefix) { - switch ($targetModifiersPrefix) { - case '!': - $conditionString .= ')'; - break; - } + if ($targetModifiersPrefix === '!') { + $conditionString .= ')'; } } @@ -234,13 +231,13 @@ protected function parseConditions(array $conditions): string * Internal helper function to append a new search selector to the xpath * that is being built. * - * @throws \Exception + * @throws Exception */ private function appendPartialPath(string $tag, string $prefix, array $conditions, ?int $index): BaseXpathBuilder { // Input validation if ($tag === '') { - throw new \Exception('Invalid argument: Tag cannot be empty.'); + throw new Exception('Invalid argument: Tag cannot be empty.'); } // Add prefix diff --git a/tests/Component/XpathBuilder/FrontendXpathBuilder.php b/tests/Component/XpathBuilder/FrontendXpathBuilder.php index e3ac229..c405fc8 100644 --- a/tests/Component/XpathBuilder/FrontendXpathBuilder.php +++ b/tests/Component/XpathBuilder/FrontendXpathBuilder.php @@ -8,37 +8,24 @@ class FrontendXpathBuilder extends BaseXpathBuilder { /** * Returns xpath that selects an input field with an exact id - * - * @param string $id - * - * @return string */ - public static function getInputById($id) + public static function getInputById(string $id): string { return (new self())->child('input', ['@id' => $id])->getXpath(); } /** * Return xpath to an element by its name - * - * @param string $tag - * @param string $name - * - * @return string */ - public static function getElementXpathByName($tag, $name) + public static function getElementXpathByName(string $tag, string $name): string { return (new self())->child($tag, ['~name' => $name])->getXpath(); } /** * Returns xpath that selects a form based on its action - * - * @param string $action - * - * @return string */ - public static function getFormByAction($action) + public static function getFormByAction(string $action): string { return (new self())->child('form', ['@action' => $action])->getXpath(); } diff --git a/tests/Context/ApiContext.php b/tests/Context/ApiContext.php index 94fbe8c..526d4f7 100644 --- a/tests/Context/ApiContext.php +++ b/tests/Context/ApiContext.php @@ -5,6 +5,8 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; +use RuntimeException; use Shopware\Component\Api\ApiClient; class ApiContext extends SubContext @@ -68,7 +70,7 @@ public function theFollowingCustomerGroupsExist(TableNode $table): void /** * @Given the following properties exist in the store: * - * @throws \Exception + * @throws Exception */ public function theFollowingPropertiesExistInTheStore(TableNode $table): void { @@ -82,7 +84,7 @@ public function theFollowingPropertiesExistInTheStore(TableNode $table): void /** * @Given there is no customer registered with e-mail address :email * - * @throws \RuntimeException + * @throws RuntimeException */ public function thereIsNoCustomerRegisteredWithEMailAddress(string $email): void { @@ -101,6 +103,16 @@ public function theFollowingCategoryIsAvailable(string $tree): void $api->createCategoryTree($tree); } + /** + * @Given the following orders exist: + */ + public function theFollowingOrdersExist(TableNode $orders): void + { + foreach ($orders as $order) { + $this->getApiClient()->createOrder($order); + } + } + private function createCustomer(string $email, string $password = '', string $group = '', string $country = ''): void { $api = $this->getApiClient(); @@ -126,7 +138,7 @@ private function createCustomer(string $email, string $password = '', string $gr } /** - * @throws \RuntimeException + * @throws RuntimeException */ private function getApiClient(): ApiClient { @@ -140,29 +152,19 @@ private function getApiClient(): ApiClient $assetUrl = getenv('assets_url'); if (empty($apiKey)) { - throw new \RuntimeException('Please set the api_key parameter in .env'); + throw new RuntimeException('Please set the api_key parameter in .env'); } if (empty($baseUrl)) { - throw new \RuntimeException('Please set the base_url parameter in behat.yml'); + throw new RuntimeException('Please set the base_url parameter in behat.yml'); } if (empty($assetUrl)) { - throw new \RuntimeException('Please set the asset_url parameter in .env'); + throw new RuntimeException('Please set the asset_url parameter in .env'); } $this->apiClient = new ApiClient($baseUrl, $assetUrl, $apiUser, $apiKey); return $this->apiClient; } - - /** - * @Given the following orders exist: - */ - public function theFollowingOrdersExist(TableNode $orders): void - { - foreach ($orders as $order) { - $this->getApiClient()->createOrder($order); - } - } } diff --git a/tests/Context/BackendArticleContext.php b/tests/Context/BackendArticleContext.php index 9ba4b16..04d6fbe 100644 --- a/tests/Context/BackendArticleContext.php +++ b/tests/Context/BackendArticleContext.php @@ -5,40 +5,17 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use Shopware\Page\Backend\BackendModule; use Shopware\Page\Backend\ExistingArticleModule; use Shopware\Page\Backend\NewArticleModule; class BackendArticleContext extends SubContext { - /** - * @throws \Exception - */ - private function getBackendModulePage(): BackendModule - { - return $this->getValidPage(BackendModule::class); - } - - /** - * @throws \Exception - */ - private function getExistingArticleModulePage(): ExistingArticleModule - { - return $this->getValidPage(ExistingArticleModule::class); - } - - /** - * @throws \Exception - */ - private function getNewArticleModulePage(): NewArticleModule - { - return $this->getValidPage(NewArticleModule::class); - } - /** * @Given I set :price as the article price * - * @throws \Exception + * @throws Exception */ public function iSetAsTheArticlePriceForTheCustomerGroup(string $price): void { @@ -48,7 +25,7 @@ public function iSetAsTheArticlePriceForTheCustomerGroup(string $price): void /** * @Given I choose :text as article description * - * @throws \Exception + * @throws Exception */ public function iChooseAsArticleDescription(string $text): void { @@ -58,7 +35,7 @@ public function iChooseAsArticleDescription(string $text): void /** * @Then I am able to save my article * - * @throws \Exception + * @throws Exception */ public function iAmAbleToSaveMyArticle(): void { @@ -68,7 +45,7 @@ public function iAmAbleToSaveMyArticle(): void /** * @When I click to add the category with name :name to the article * - * @throws \Exception + * @throws Exception */ public function iClickTheIconToAdd(string $name): void { @@ -78,7 +55,7 @@ public function iClickTheIconToAdd(string $name): void /** * @Then I should find the category with name :title in :area * - * @throws \Exception + * @throws Exception */ public function iShouldFindInTheArea(string $title, string $area): void { @@ -88,7 +65,7 @@ public function iShouldFindInTheArea(string $title, string $area): void /** * @When I fill in the basic configuration: * - * @throws \Exception + * @throws Exception */ public function iFillInTheBasicConfiguration(TableNode $table): void { @@ -99,7 +76,7 @@ public function iFillInTheBasicConfiguration(TableNode $table): void /** * @When I expand the :label element * - * @throws \Exception + * @throws Exception */ public function iExpandTheCategoryElement(string $label): void { @@ -119,7 +96,7 @@ public function iCheckIfMyArticleDataIsDisplayed(TableNode $table): void /** * @When I change the article name to :productName * - * @throws \Exception + * @throws Exception */ public function iChangeTheArticleNameTo(string $productName): void { @@ -129,7 +106,7 @@ public function iChangeTheArticleNameTo(string $productName): void /** * @When I click the edit icon of the entry :name * - * @throws \Exception + * @throws Exception */ public function iClickTheEditIconOfTheEntry(string $name): void { @@ -139,7 +116,7 @@ public function iClickTheEditIconOfTheEntry(string $name): void /** * @When I click the delete icon of the entry :name * - * @throws \Exception + * @throws Exception */ public function iClickTheDeleteIconOfTheEntry(string $name): void { @@ -149,7 +126,7 @@ public function iClickTheDeleteIconOfTheEntry(string $name): void /** * @Given I confirm to delete the entry * - * @throws \Exception + * @throws Exception */ public function iConfirmToDeleteTheEntry(): void { @@ -159,7 +136,7 @@ public function iConfirmToDeleteTheEntry(): void /** * @When I create the :title group via :label * - * @throws \Exception + * @throws Exception */ public function iCreateTheGroup(string $groupName, string $label): void { @@ -170,7 +147,7 @@ public function iCreateTheGroup(string $groupName, string $label): void * @Given the group :title should be listed in the area :area * @Given the option :title should be listed in the area :area * - * @throws \Exception + * @throws Exception */ public function theGroupShouldBeListedAsAnActiveGroup(string $title, string $area): void { @@ -180,7 +157,7 @@ public function theGroupShouldBeListedAsAnActiveGroup(string $title, string $are /** * @When I click :group to create the options of it * - * @throws \Exception + * @throws Exception */ public function iClickToCreateTheOptionsOfIt(string $groupName): void { @@ -190,7 +167,7 @@ public function iClickToCreateTheOptionsOfIt(string $groupName): void /** * @Then I create the following options options: * - * @throws \Exception + * @throws Exception */ public function iCreateTheFollowingOptionsOptions(TableNode $table): void { @@ -201,7 +178,7 @@ public function iCreateTheFollowingOptionsOptions(TableNode $table): void * @When I limit the price :price for an amount up to :max * @When I set the price :price for any number from here * - * @throws \Exception + * @throws Exception */ public function iLimitThePriceForAnAmountOfTo(string $price, string $maxAmount = '0'): void { @@ -232,7 +209,7 @@ public function iShouldSeeAsFromPriceToAnyNumber(string $amount): void /** * @When I fill in the property configuration: * - * @throws \Exception + * @throws Exception */ public function iFillInThePropertyConfiguration(TableNode $table): void { @@ -243,7 +220,7 @@ public function iFillInThePropertyConfiguration(TableNode $table): void /** * @Then I should see :group as corresponding value to :value * - * @throws \Exception + * @throws Exception */ public function iShouldSeeAsCorrespondingValueTo(string $group, string $value): void { @@ -265,4 +242,28 @@ public function iOpenVariantDetailPageOfVariant(string $orderNumber): void { $this->getExistingArticleModulePage()->openVariantDetailPage($orderNumber); } + + /** + * @throws Exception + */ + private function getBackendModulePage(): BackendModule + { + return $this->getValidPage(BackendModule::class); + } + + /** + * @throws Exception + */ + private function getExistingArticleModulePage(): ExistingArticleModule + { + return $this->getValidPage(ExistingArticleModule::class); + } + + /** + * @throws Exception + */ + private function getNewArticleModulePage(): NewArticleModule + { + return $this->getValidPage(NewArticleModule::class); + } } diff --git a/tests/Context/BackendCustomerContext.php b/tests/Context/BackendCustomerContext.php index 5368cc7..c3fe025 100644 --- a/tests/Context/BackendCustomerContext.php +++ b/tests/Context/BackendCustomerContext.php @@ -5,6 +5,7 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use Shopware\Page\Backend\CustomerModule; class BackendCustomerContext extends SubContext @@ -28,7 +29,7 @@ public function fillNewCustomerForm(TableNode $table): void /** * @When I click the edit icon on customer :firstname * - * @throws \Exception + * @throws Exception */ public function iClickTheEditIconOnCustomer(string $name): void { diff --git a/tests/Context/BackendOrderContext.php b/tests/Context/BackendOrderContext.php index 44a93aa..bf33100 100644 --- a/tests/Context/BackendOrderContext.php +++ b/tests/Context/BackendOrderContext.php @@ -5,7 +5,9 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use PHPUnit\Framework\Assert; +use RuntimeException; use Shopware\Page\Backend\OrderModule; use Smalot\PdfParser\Parser; @@ -14,7 +16,7 @@ class BackendOrderContext extends SubContext /** * @When I open the order from email :email * - * @throws \RuntimeException + * @throws RuntimeException */ public function iOpenTheOrderFromEmail(string $email): void { @@ -48,13 +50,13 @@ public function iFilterTheBackendOrderListForShippingCountry(string $country): v /** * @Then I should see exactly :amount order in the order list * - * @throws \Exception + * @throws Exception */ public function iShouldSeeExactlyOneOrderInTheOrderList(string $amount): void { $actualAmount = $this->getModulePage()->getNumberOfOrdersInOrderList(); if ((int) $amount !== $actualAmount) { - throw new \Exception(\sprintf('Expected %s order, found %s.', $amount, $actualAmount)); + throw new Exception(\sprintf('Expected %s order, found %s.', $amount, $actualAmount)); } } @@ -69,14 +71,14 @@ public function iSortTheBackendOrderListByOrderValueAscendingly(): void /** * @Then I should see the order from :email at the top of the order list * - * @throws \Exception + * @throws Exception */ public function iShouldSeeTheOrderFromAtTheTopOfTheOrderList(string $email): void { $topmostOrder = $this->getModulePage()->getTopmostOrderFromList(); if (strpos($topmostOrder->getHtml(), $email) === false) { - throw new \Exception(\sprintf('Expected order from %s would be at top of list.', $email)); + throw new Exception(\sprintf('Expected order from %s would be at top of list.', $email)); } } @@ -91,7 +93,7 @@ public function iShouldBeAbleToSendANotificationToTheCustomer(): void /** * @Given the invoice should contain the following: * - * @throws \Exception + * @throws Exception */ public function theInvoiceShouldContain(TableNode $content): void { @@ -102,7 +104,7 @@ public function theInvoiceShouldContain(TableNode $content): void $documents = glob($documentsPath . '/*.pdf'); if (empty($documents)) { - throw new \Exception('Could not find generated PDF document.'); + throw new Exception('Could not find generated PDF document.'); } $pdfContent = $this->getPdfTextContent($documents[0]); @@ -120,14 +122,14 @@ private function getModulePage(): OrderModule } /** - * @throws \Exception + * @throws Exception */ private function getDocumentsDirectory(): string { $documentsPath = getenv('base_path') . '/files/documents'; if (!is_dir($documentsPath)) { - throw new \RuntimeException('Could not open document directory at ' . $documentsPath); + throw new RuntimeException('Could not open document directory at ' . $documentsPath); } return $documentsPath; @@ -136,7 +138,7 @@ private function getDocumentsDirectory(): string private function getPdfTextContent(string $filepath): string { if (!is_file($filepath)) { - throw new \RuntimeException('Could not open file ' . $filepath); + throw new RuntimeException('Could not open file ' . $filepath); } return (new Parser())->parseFile($filepath)->getText(); diff --git a/tests/Context/BackendQuestionMarkContext.php b/tests/Context/BackendQuestionMarkContext.php index 9db41d6..823d763 100644 --- a/tests/Context/BackendQuestionMarkContext.php +++ b/tests/Context/BackendQuestionMarkContext.php @@ -4,6 +4,7 @@ namespace Shopware\Context; +use Exception; use Shopware\Page\Backend\QuestionMarkModule; class BackendQuestionMarkContext extends SubContext @@ -16,7 +17,7 @@ public function iShouldSeeACorrectBuildNumber(): void $questionMark = $this->getValidPage(QuestionMarkModule::class); $buildNr = $questionMark->getBuildNr(); if (!strtotime($buildNr)) { - throw new \Exception('Build number wrong'); + throw new Exception('Build number wrong'); } } @@ -28,7 +29,7 @@ public function iShouldSeeACorrectVersionNumber(): void $questionMark = $this->getValidPage(QuestionMarkModule::class); $versionNr = $questionMark->getVersionNr(); if (!version_compare($versionNr, '0.0.1', '>')) { - throw new \Exception('Version number wrong!'); + throw new Exception('Version number wrong!'); } } } diff --git a/tests/Context/BackendVoucherContext.php b/tests/Context/BackendVoucherContext.php index 2f885e0..bee6f9b 100644 --- a/tests/Context/BackendVoucherContext.php +++ b/tests/Context/BackendVoucherContext.php @@ -5,6 +5,7 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use PHPUnit\Framework\Assert; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Page\Backend\Backend; @@ -51,7 +52,7 @@ public function iAddTheVoucherToMyCart(string $code): void /** * @Given I should be able to use the code exactly once * - * @throws \Exception + * @throws Exception */ public function iShouldBeAbleToUseTheCodeExactlyOnce(): void { @@ -95,13 +96,13 @@ private function loginAsFrontendUser(): void } /** - * @throws \Exception + * @throws Exception */ private function fillCartWithProductsAndGeneratedVoucher(string $voucherCode): void { $cartPage = $this->getValidPage(CheckoutCart::class); $cartPage->fillCartWithProducts([ - ['number' => 'SWT0001', 'quantity' => 1], + ['number' => 'SWT0001', 'quantity' => '1'], ]); $cartPage->addVoucher($voucherCode); } diff --git a/tests/Context/DebugContext.php b/tests/Context/DebugContext.php index b52eae9..392c018 100644 --- a/tests/Context/DebugContext.php +++ b/tests/Context/DebugContext.php @@ -9,6 +9,7 @@ use Behat\Mink\Exception\Exception; use Behat\Mink\Session; use Behat\Testwork\Tester\Result\TestResult; +use RuntimeException; class DebugContext extends SubContext { @@ -25,21 +26,6 @@ public function onAfterStep(AfterStepScope $scope): void } } - /** - * Take a screenshot of the current Selenium Driver instance - */ - private function takeScreenshot(): void - { - $driver = $this->getSession()->getDriver(); - if (!$driver instanceof Selenium2Driver) { - return; - } - - $filePath = \dirname(__FILE__, 2) . '/logs/mink'; - - $this->saveScreenshot(null, $filePath); - } - /** * Save a screenshot of the current window to the file system. * @@ -52,11 +38,26 @@ public function saveScreenshot(?string $filename = null, ?string $filepath = nul { $filename = $filename ?: \sprintf('%s_%s_%s.%s', $this->getMinkParameter('browser_name'), time(), uniqid('', true), 'png'); - $filepath = $filepath ?: (\ini_get('upload_tmp_dir') ? \ini_get('upload_tmp_dir') : sys_get_temp_dir()); + $filepath = $filepath ?: (\ini_get('upload_tmp_dir') ?: sys_get_temp_dir()); file_put_contents($filepath . '/' . $filename, $this->getSession()->getScreenshot()); } + /** + * Take a screenshot of the current Selenium Driver instance + */ + private function takeScreenshot(): void + { + $driver = $this->getSession()->getDriver(); + if (!$driver instanceof Selenium2Driver) { + return; + } + + $filePath = \dirname(__FILE__, 2) . '/logs/mink'; + + $this->saveScreenshot(null, $filePath); + } + /** * Log information about the current request */ @@ -80,7 +81,7 @@ private function saveLog(string $content, string $type): void $path = \sprintf('%s/behat-%s.%s', $logDir, $currentDateAsString, $type); if (!file_put_contents($path, $content)) { - throw new \RuntimeException(\sprintf('Failed while trying to write log in "%s".', $path)); + throw new RuntimeException(\sprintf('Failed while trying to write log in "%s".', $path)); } } diff --git a/tests/Context/Exception/PageNotDefinedException.php b/tests/Context/Exception/PageNotDefinedException.php index abbb7e8..89a5c2b 100644 --- a/tests/Context/Exception/PageNotDefinedException.php +++ b/tests/Context/Exception/PageNotDefinedException.php @@ -4,14 +4,16 @@ namespace Shopware\Context\Exception; +use RuntimeException; use SensioLabs\Behat\PageObjectExtension\PageObject\Page; +use Throwable; -class PageNotDefinedException extends \RuntimeException +class PageNotDefinedException extends RuntimeException { /** * @param class-string $pageClass */ - public function __construct(string $pageClass, int $code = 0, ?\Throwable $previous = null) + public function __construct(string $pageClass, int $code = 0, ?Throwable $previous = null) { $message = \sprintf('Page "%s" is not defined', $pageClass); parent::__construct($message, $code, $previous); diff --git a/tests/Context/FileCheckContext.php b/tests/Context/FileCheckContext.php index 00940aa..71b186e 100644 --- a/tests/Context/FileCheckContext.php +++ b/tests/Context/FileCheckContext.php @@ -8,7 +8,7 @@ class FileCheckContext extends SubContext { - private $testPath; + private string $testPath; private string $folderRequirementLabel = 'media/music/'; @@ -21,7 +21,7 @@ class FileCheckContext extends SubContext public function __construct() { parent::__construct(); - $this->testPath = getenv('base_path'); + $this->testPath = (string) getenv('base_path'); } /** @@ -35,7 +35,7 @@ public function theFilecheckRequirementsAreNotMet(): void /** * @When I correct the :requirement requirement */ - public function iCorrectTheRequirement($requirement): void + public function iCorrectTheRequirement(string $requirement): void { $this->setRequirementsFulfillment(true, $requirement); } @@ -44,7 +44,7 @@ public function iCorrectTheRequirement($requirement): void * @Then a :requirement requirement should have a :icon as status * @Then all :requirement requirements should have a :icon as status */ - public function aRequirementShouldOwnAsStatus($requirement, $icon): void + public function aRequirementShouldOwnAsStatus(string $requirement, string $icon): void { $page = $this->getValidPage(SystemInfoModule::class); diff --git a/tests/Context/FrontendCheckoutContext.php b/tests/Context/FrontendCheckoutContext.php index 4c458a7..dfff3a5 100644 --- a/tests/Context/FrontendCheckoutContext.php +++ b/tests/Context/FrontendCheckoutContext.php @@ -5,6 +5,7 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use Shopware\Page\Frontend\Account; use Shopware\Page\Frontend\CheckoutCart; use Shopware\Page\Frontend\CheckoutConfirm; @@ -48,7 +49,7 @@ public function iAddTheArticleToMyBasket(string $number): void public function iRemoveTheArticleOnPosition(string $position): void { $page = $this->getValidPage(CheckoutCart::class); - $page->removeCartPositionAtIndex($position); + $page->removeCartPositionAtIndex((int) $position); } /** @@ -92,7 +93,7 @@ public function iProceedToCheckoutConfirmation(): void /** * @Given the cart contains the following products: * - * @throws \Exception + * @throws Exception */ public function theCartContainsTheFollowingProducts(TableNode $items): void { diff --git a/tests/Context/FrontendContext.php b/tests/Context/FrontendContext.php index d6f6da2..975f533 100644 --- a/tests/Context/FrontendContext.php +++ b/tests/Context/FrontendContext.php @@ -4,6 +4,7 @@ namespace Shopware\Context; +use Exception; use PHPUnit\Framework\Assert; use Shopware\Component\XpathBuilder\BaseXpathBuilder; use Shopware\Page\Frontend\Account; @@ -42,7 +43,7 @@ public function iAmLoggedInWithAccount(string $email, string $password = ''): vo /** * @Then the cart should contain :quantity articles with a value of :amount * - * @throws \Exception + * @throws Exception */ public function theCartShouldContainArticlesWithAValueOf(string $quantity, string $amount): void { @@ -92,7 +93,7 @@ public function iShouldBeAbleToSeeTheProductWithPrice(string $name, string $test /** * @Given I click on :text * - * @throws \Exception + * @throws Exception */ public function iClickOn(string $text): void { @@ -112,6 +113,6 @@ public function iClickOn(string $text): void return; } - throw new \Exception('Could not find element by content ' . $text); + throw new Exception('Could not find element by content ' . $text); } } diff --git a/tests/Context/FrontendDetailContext.php b/tests/Context/FrontendDetailContext.php index 0294948..b30794c 100644 --- a/tests/Context/FrontendDetailContext.php +++ b/tests/Context/FrontendDetailContext.php @@ -5,33 +5,18 @@ namespace Shopware\Context; use Behat\Gherkin\Node\TableNode; +use Exception; use Shopware\Page\Frontend\Detail; use Shopware\Page\Frontend\Search; class FrontendDetailContext extends SubContext { - /** - * @throws \Exception - */ - private function getDetailPage(): Detail - { - return $this->getValidPage(Detail::class); - } - - /** - * @throws \Exception - */ - private function getSearchPage(): Search - { - return $this->getValidPage(Search::class); - } - /** * @When I choose the variant with the number :optionNumber * - * @throws \Exception + * @throws Exception */ - public function iChooseTheVariantWithTheNumber($optionNumber): void + public function iChooseTheVariantWithTheNumber(string $optionNumber): void { $this->getDetailPage()->fillField('group[5]', $optionNumber); } @@ -39,7 +24,7 @@ public function iChooseTheVariantWithTheNumber($optionNumber): void /** * @Given I wait for the loading indicator to disappear * - * @throws \Exception + * @throws Exception */ public function iWaitForTheLoadingIndicatorToDisappear(): void { @@ -49,7 +34,7 @@ public function iWaitForTheLoadingIndicatorToDisappear(): void /** * @Given I am on the detail page for article with ordernumber :ordernumber * - * @throws \Exception + * @throws Exception */ public function iAmOnTheDetailPageForArticleWithOrdernumber(string $ordernumber): void { @@ -59,7 +44,7 @@ public function iAmOnTheDetailPageForArticleWithOrdernumber(string $ordernumber) /** * @When I put the current article :quantity times into the basket * - * @throws \Exception + * @throws Exception */ public function iPutTheArticleTimesIntoTheBasket(string $quantity): void { @@ -70,28 +55,40 @@ public function iPutTheArticleTimesIntoTheBasket(string $quantity): void /** * @Then I should see the following graduated prices: * - * @throws \Exception + * @throws Exception */ public function iShouldSeeTheFollowingGraduatedPrices(TableNode $table): void { - $data = $table->getHash(); - - foreach ($data as $graduatedprice) { - $this->getDetailPage()->checkGraduatedPrice($graduatedprice); + foreach ($table->getHash() as $graduatedPrice) { + $this->getDetailPage()->checkGraduatedPrice($graduatedPrice); } } /** * @Given I should see the base price information: * - * @throws \Exception + * @throws Exception */ public function iShouldSeeTheBasePriceInformation(TableNode $table): void { - $data = $table->getHash(); - - foreach ($data as $entry) { + foreach ($table->getHash() as $entry) { $this->getDetailPage()->checkBasePrice($entry); } } + + /** + * @throws Exception + */ + private function getDetailPage(): Detail + { + return $this->getValidPage(Detail::class); + } + + /** + * @throws Exception + */ + private function getSearchPage(): Search + { + return $this->getValidPage(Search::class); + } } diff --git a/tests/Context/GeneralContext.php b/tests/Context/GeneralContext.php index e577e05..9eaeb5c 100644 --- a/tests/Context/GeneralContext.php +++ b/tests/Context/GeneralContext.php @@ -55,7 +55,7 @@ public function onBeforeScenario(): void /** * @Given I wait for :amount seconds */ - public function iWaitForSeconds($amount): void + public function iWaitForSeconds(string $amount): void { sleep((int) $amount); } @@ -63,7 +63,7 @@ public function iWaitForSeconds($amount): void /** * @Given /^I scroll down "([^"]*)" px$/ */ - public function iScrollDown($pixels): void + public function iScrollDown(string $pixels): void { $this->getSession()->executeScript(\sprintf('window.scroll(0, %s)', $pixels)); } diff --git a/tests/Context/InstallerContext.php b/tests/Context/InstallerContext.php index 43ca411..9e219b6 100644 --- a/tests/Context/InstallerContext.php +++ b/tests/Context/InstallerContext.php @@ -102,7 +102,7 @@ public function iShouldSeeTheLinkLeadingTo(string $linktext, string $target): vo /** * @Then I should see :text after import is finished */ - public function iShouldSeeAfterImportIsFinished($text): void + public function iShouldSeeAfterImportIsFinished(string $text): void { $builder = new BackendXpathBuilder(); $this->waitForTextInElement($builder->child('div', ['@class' => 'counter-container'])->getXpath(), $text, 0, 120); diff --git a/tests/Context/ProductExportContext.php b/tests/Context/ProductExportContext.php index 21ab599..33e0d72 100644 --- a/tests/Context/ProductExportContext.php +++ b/tests/Context/ProductExportContext.php @@ -6,6 +6,7 @@ use Behat\Gherkin\Node\PyStringNode; use Behat\Gherkin\Node\TableNode; +use Exception; use Shopware\Page\Backend\ProductExportModule; class ProductExportContext extends SubContext @@ -13,7 +14,7 @@ class ProductExportContext extends SubContext /** * @When I fill in the product export configuration: * - * @throws \Exception + * @throws Exception */ public function iFillInTheProductExportGeneralConfiguration(TableNode $table): void { @@ -31,7 +32,7 @@ public function iEnterTheTemplate(PyStringNode $template): void /** * @Given I open the :title export file * - * @throws \Exception + * @throws Exception */ public function iOpenTheCreatedExportFile(string $title): void { diff --git a/tests/Context/SubContext.php b/tests/Context/SubContext.php index d3c53bf..c6c65ff 100644 --- a/tests/Context/SubContext.php +++ b/tests/Context/SubContext.php @@ -36,7 +36,7 @@ public function __construct() * * @param Mink $mink Mink session manager */ - public function setMink(Mink $mink) + public function setMink(Mink $mink): void { $this->mink = $mink; } @@ -49,7 +49,7 @@ public function getMink(): Mink /** * Sets parameters provided for Mink. */ - public function setMinkParameters(array $parameters) + public function setMinkParameters(array $parameters): void { $this->minkParameters = $parameters; } @@ -57,7 +57,7 @@ public function setMinkParameters(array $parameters) /** * Returns specific mink parameter. */ - public function getMinkParameter(string $name) + public function getMinkParameter(string $name): ?string { return $this->minkParameters[$name] ?? null; } @@ -192,7 +192,7 @@ protected function waitIfThereIsText(string $text, int $wait = 5): bool }, $wait); } - protected function slugify($text, $separator = ''): string + protected function slugify(string $text, string $separator = ''): string { $slugify = new Slugify(); $slugify->addRule('@', 'at'); diff --git a/tests/Context/SubshopContext.php b/tests/Context/SubshopContext.php index 1f08f7b..d4d41a0 100644 --- a/tests/Context/SubshopContext.php +++ b/tests/Context/SubshopContext.php @@ -9,24 +9,6 @@ class SubshopContext extends SubContext { - /** - * @Given I am in subshop with URL :url - */ - public function iAmInSubshopWithURL($url): void - { - if (substr($url, 0, 4) === 'http') { - $this->setMinkParameters([ - 'base_url' => $url, - ]); - - return; - } - $baseUrl = $this->getMinkParameter('base_url'); - $this->setMinkParameters([ - 'base_url' => rtrim($baseUrl, '/') . '/' . ltrim($url, '/'), - ]); - } - /** * @Then I should be able to access the subshop via using :url * @Then I should be able to access the shop via using :url @@ -57,7 +39,7 @@ public function iClickTheSettingsElement(string $label): void /** * @Given I fill in and submit the :formname configuration form: */ - public function iFillTheConfigurationForm($formname, TableNode $table): void + public function iFillTheConfigurationForm(TableNode $table): void { $page = $this->getValidPage(SettingsModule::class); diff --git a/tests/Context/UpdaterContext.php b/tests/Context/UpdaterContext.php index 8697f0c..805a343 100644 --- a/tests/Context/UpdaterContext.php +++ b/tests/Context/UpdaterContext.php @@ -79,19 +79,6 @@ public function theUpdateRequirementsAreNotMet(): void $this->setRequirementsFulfillment(false); } - /** - * Sets the access privileges of a directory according to the situation to simulate system requirements - */ - private function setRequirementsFulfillment(bool $meetRequirements): void - { - if ($meetRequirements === false) { - chmod($this->testPath, 0444); - - return; - } - chmod($this->testPath, 0777); - } - /** * @When I correct the requirements */ @@ -108,4 +95,17 @@ public function iAdvanceToTheNextRequirementsStep(string $stepName): void $page = $this->getValidPage(UpdaterIndex::class); $page->advanceToStep($stepName); } + + /** + * Sets the access privileges of a directory according to the situation to simulate system requirements + */ + private function setRequirementsFulfillment(bool $meetRequirements): void + { + if ($meetRequirements === false) { + chmod($this->testPath, 0444); + + return; + } + chmod($this->testPath, 0777); + } } diff --git a/tests/Element/Backend/ExtJsElement.php b/tests/Element/Backend/ExtJsElement.php index 038183a..281ed37 100644 --- a/tests/Element/Backend/ExtJsElement.php +++ b/tests/Element/Backend/ExtJsElement.php @@ -6,6 +6,7 @@ use Behat\Mink\Element\NodeElement; use Behat\Mink\Session; +use RuntimeException; /** * Base class for all ExtJs element representations. @@ -62,12 +63,12 @@ protected function waitForElementAvailable(): void // Check if object exists if (!$this->isValid()) { - throw new \RuntimeException('Could not find element of type ' . \get_class($this) . ' with xpath: ' . $this->getXpath()); + throw new RuntimeException('Could not find element of type ' . \get_class($this) . ' with xpath: ' . $this->getXpath()); } // Check if object is visible if (!$this->isVisible()) { - throw new \RuntimeException('Element of type ' . \get_class($this) . ' not visible.'); + throw new RuntimeException('Element of type ' . \get_class($this) . ' not visible.'); } } } diff --git a/tests/Element/Backend/Form/Checkbox.php b/tests/Element/Backend/Form/Checkbox.php index 66978d2..577f5a8 100644 --- a/tests/Element/Backend/Form/Checkbox.php +++ b/tests/Element/Backend/Form/Checkbox.php @@ -9,10 +9,7 @@ class Checkbox extends ExtJsElement { - /** - * @return bool - */ - public function isChecked() + public function isChecked(): bool { $checkedXpath = BackendXpathBuilder::create() ->ancestor('table', ['~class' => 'x-form-cb-checked'], 1) @@ -23,7 +20,7 @@ public function isChecked() return $checked !== null; } - public function toggle() + public function toggle(): void { $this->click(); } diff --git a/tests/Element/Backend/Form/Combobox.php b/tests/Element/Backend/Form/Combobox.php index 9656104..0e07eac 100644 --- a/tests/Element/Backend/Form/Combobox.php +++ b/tests/Element/Backend/Form/Combobox.php @@ -5,6 +5,9 @@ namespace Shopware\Element\Backend\Form; use Behat\Mink\Element\NodeElement; +use Exception; +use InvalidArgumentException; +use RuntimeException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\ExtJsElement; @@ -15,6 +18,9 @@ class Combobox extends ExtJsElement */ public function setValue($value): void { + if (!\is_string($value)) { + throw new InvalidArgumentException('Value must be a string'); + } // Open combobox dropdown $pebble = $this->getComboboxPebble(); $pebble->click(); @@ -28,7 +34,7 @@ public function setValue($value): void // Click on correct dropdown entry $option = $this->getOptionByValue($value, $dropdown); if (!$option instanceof NodeElement) { - throw new \RuntimeException(\sprintf('Could not find option with value "%s"', print_r($value, true))); + throw new RuntimeException(\sprintf('Could not find option with value "%s"', print_r($value, true))); } $option->click(); @@ -41,11 +47,17 @@ public function setValue($value): void private function elementsTouch(NodeElement $elemA, NodeElement $elemB): bool { $idA = $elemA->getAttribute('id'); - $aTop = $this->getYCoordinateForElement($idA, 'top'); + if (!\is_string($idA)) { + throw new Exception(\sprintf('Element A has no id attribute: %s', $elemA->getText())); + } + $aTop = $this->getYCoordinateForElement($idA); $aBottom = $this->getYCoordinateForElement($idA, 'bottom'); $idB = $elemB->getAttribute('id'); - $bTop = $this->getYCoordinateForElement($idB, 'top'); + if (!\is_string($idB)) { + throw new Exception(\sprintf('Element B has no id attribute: %s', $elemB->getText())); + } + $bTop = $this->getYCoordinateForElement($idB); $bBottom = $this->getYCoordinateForElement($idB, 'bottom'); return abs($aTop - $bBottom) < 5 || abs($aBottom - $bTop) < 5; @@ -64,15 +76,15 @@ private function getYCoordinateForElement(string $id, string $side = 'top'): int } /** - * @throws \Exception + * @throws Exception */ private function getComboboxPebble(): NodeElement { $pebbleXpath = BackendXpathBuilder::create()->child('div', ['~class' => 'x-form-trigger'])->getXpath(); $pebble = $this->find('xpath', $pebbleXpath); - if (!$pebble->isVisible()) { - throw new \Exception('Pebble for combobox not visible.'); + if (!$pebble || !$pebble->isVisible()) { + throw new Exception('Pebble for combobox not visible.'); } return $pebble; diff --git a/tests/Element/Backend/Form/Selecttree.php b/tests/Element/Backend/Form/Selecttree.php index d0a9a27..5787667 100644 --- a/tests/Element/Backend/Form/Selecttree.php +++ b/tests/Element/Backend/Form/Selecttree.php @@ -5,22 +5,16 @@ namespace Shopware\Element\Backend\Form; use Behat\Mink\Element\NodeElement; +use InvalidArgumentException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\ExtJsElement; use Shopware\Element\Backend\Window; class Selecttree extends ExtJsElement { - /** - * @param string $xpath - * - * @return Selecttree - */ - public static function createFromXpath($xpath, Window $window) + public static function createFromXpath(string $xpath, Window $window): Selecttree { - $selecttree = new self($xpath, $window->getSession()); - - return $selecttree; + return new self($xpath, $window->getSession()); } /** @@ -28,6 +22,9 @@ public static function createFromXpath($xpath, Window $window) */ public function setValue($value) { + if (!\is_string($value)) { + throw new InvalidArgumentException('Value must be a string'); + } // Open dropdown $this->click(); @@ -45,12 +42,8 @@ public function setValue($value) /** * Return a list of all elements of a select tree - * - * @param string $selectString - * - * @return array */ - private function getSelectTreeElementXpaths($selectString) + private function getSelectTreeElementXpaths(string $selectString): array { $xpaths = []; @@ -76,23 +69,15 @@ private function getSelectTreeElementXpaths($selectString) return $xpaths; } - /** - * @return string - */ - private function getSelecttreeDropdownXpath() + private function getSelecttreeDropdownXpath(): string { - $dropdownXpath = BackendXpathBuilder::create() + return BackendXpathBuilder::create() ->descendant('div', ['@text' => 'Deutsch']) ->ancestor('div', ['~class' => 'x-tree-panel']) ->getXpath(); - - return $dropdownXpath; } - /** - * @return NodeElement|null - */ - private function getDropdownFromWindow($dropdownXpath) + private function getDropdownFromWindow(string $dropdownXpath): ?NodeElement { $dropdown = null; $this->waitFor(10, function () use (&$dropdown, $dropdownXpath) { diff --git a/tests/Element/Backend/GridView/GridView.php b/tests/Element/Backend/GridView/GridView.php index 5b8cd71..7609525 100644 --- a/tests/Element/Backend/GridView/GridView.php +++ b/tests/Element/Backend/GridView/GridView.php @@ -5,6 +5,7 @@ namespace Shopware\Element\Backend\GridView; use Behat\Mink\Element\NodeElement; +use RuntimeException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\ExtJsElement; @@ -50,7 +51,7 @@ public function getFirstRow(): GridViewRow $xPath = $this->getGridViewFirstRowXpath(); $element = $this->find('xpath', $xPath); if (!$element instanceof NodeElement) { - throw new \RuntimeException(\sprintf('Could not find grid view row with xPath: "%s"', $xPath)); + throw new RuntimeException(\sprintf('Could not find grid view row with xPath: "%s"', $xPath)); } return new GridViewRow($element->getXpath(), $this->getSession()); @@ -67,7 +68,7 @@ public function getRowByContent(string $content): GridViewRow } } - throw new \RuntimeException('Could not find grid view row by with content: ' . $content); + throw new RuntimeException('Could not find grid view row by with content: ' . $content); } /** diff --git a/tests/Element/Backend/GridView/GridViewRow.php b/tests/Element/Backend/GridView/GridViewRow.php index bd3b8ee..900e22e 100644 --- a/tests/Element/Backend/GridView/GridViewRow.php +++ b/tests/Element/Backend/GridView/GridViewRow.php @@ -12,10 +12,8 @@ class GridViewRow extends ExtJsElement /** * Click an icon in a grid view row. * This could e.g. be an edit icon for a customer ('sprite-pencil') or some other extJS icon. - * - * @param string $iconClass */ - public function clickActionIcon($iconClass) + public function clickActionIcon(string $iconClass): void { $iconXpath = BackendXpathBuilder::create()->child('img', ['~class' => $iconClass])->getXpath(); $icon = $this->find('xpath', $iconXpath); diff --git a/tests/Element/Backend/Window.php b/tests/Element/Backend/Window.php index b22cab7..af8d957 100644 --- a/tests/Element/Backend/Window.php +++ b/tests/Element/Backend/Window.php @@ -42,7 +42,7 @@ public static function createFromTitle(string $title, Session $session, bool $ex * by providing an arbitrary string that appears within the grid view that * is to be selected. */ - public function getGridView(?string $containsText = ''): GridView + public function getGridView(string $containsText = ''): GridView { return new GridView($this->getGridViewXpath($containsText), $this->getSession()); } @@ -102,6 +102,24 @@ public function getSelecttree(string $label, ?string $fieldset = null): Selecttr return Selecttree::createFromXpath($this->getSelecttreeXpath($label, $fieldset), $this); } + /** + * @param string[]|string $locator + * + * @throws ElementNotFoundException + */ + public function find(string $selector, $locator): NodeElement + { + $element = parent::find($selector, $locator); + if ($element === null) { + if (\is_array($locator)) { + $locator = implode(' ', $locator); + } + throw new ElementNotFoundException($this->getDriver(), null, $selector, $locator); + } + + return $element; + } + private function getGridViewXpath(string $containsText = ''): string { return BackendXpathBuilder::create($this->getXpath()) @@ -163,23 +181,4 @@ private function getSelecttreeXpath(string $label, ?string $fieldset): string ->descendant('div', ['~class' => 'x-form-trigger']) ->getXpath(); } - - /** - * @param string $selector - * @param string[]|string $locator - * - * @throws ElementNotFoundException - */ - public function find($selector, $locator): NodeElement - { - $element = parent::find($selector, $locator); - if ($element === null) { - if (\is_array($locator)) { - $locator = implode(' ', $locator); - } - throw new ElementNotFoundException($this->getDriver(), null, $selector, $locator); - } - - return $element; - } } diff --git a/tests/Element/Frontend/Checkout/CartPosition.php b/tests/Element/Frontend/Checkout/CartPosition.php index a6896ae..cd674ea 100644 --- a/tests/Element/Frontend/Checkout/CartPosition.php +++ b/tests/Element/Frontend/Checkout/CartPosition.php @@ -4,40 +4,20 @@ namespace Shopware\Element\Frontend\Checkout; +use Exception; + class CartPosition { - /** - * @var string - */ private string $name; - /** - * @var string - */ private string $number; - /** - * @var int - */ private int $quantity; - /** - * @var float - */ private float $itemPrice; - /** - * @var float - */ private float $sum; - /** - * @param string $name - * @param string $number - * @param int $quantity - * @param float $itemPrice - * @param float $sum - */ private function __construct(string $name, string $number, int $quantity, float $itemPrice, float $sum) { $this->name = $name; @@ -48,9 +28,7 @@ private function __construct(string $name, string $number, int $quantity, float } /** - * @throws \Exception - * - * @return CartPosition + * @throws Exception */ public static function fromArray(array $data): CartPosition { @@ -60,7 +38,7 @@ public static function fromArray(array $data): CartPosition || !\array_key_exists('itemPrice', $data) || !\array_key_exists('sum', $data) ) { - throw new \Exception('Not enough arguments to create CartPosition from array.'); + throw new Exception('Not enough arguments to create CartPosition from array.'); } $data['itemPrice'] = self::toFloat($data['itemPrice']); @@ -75,41 +53,26 @@ public static function fromArray(array $data): CartPosition ); } - /** - * @return string - */ public function getName(): string { return $this->name; } - /** - * @return string - */ public function getNumber(): string { return $this->number; } - /** - * @return int - */ public function getQuantity(): int { return $this->quantity; } - /** - * @return float - */ public function getItemPrice(): float { return $this->itemPrice; } - /** - * @return float - */ public function getSum(): float { return $this->sum; @@ -118,7 +81,7 @@ public function getSum(): float /** * Convert a given string value to a float * - * @return float + * @param string|float $string */ private static function toFloat($string): float { diff --git a/tests/Page/Backend/BackendModule.php b/tests/Page/Backend/BackendModule.php index 53462e3..6953769 100644 --- a/tests/Page/Backend/BackendModule.php +++ b/tests/Page/Backend/BackendModule.php @@ -5,6 +5,7 @@ namespace Shopware\Page\Backend; use Behat\Mink\Element\NodeElement; +use Exception; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\Window; use Shopware\Page\ContextAwarePage; @@ -34,12 +35,12 @@ class BackendModule extends ContextAwarePage * * @param array> $formElements * - * @throws \Exception + * @throws Exception */ public function fillExtJsForm(Window $formParent, array $formElements): void { foreach ($formElements as $element) { - $element['fieldset'] = isset($element['fieldset']) ? $element['fieldset'] : ''; + $element['fieldset'] = $element['fieldset'] ?? ''; switch ($element['type']) { case 'input': $input = $formParent->getInput($element['label'], $element['fieldset']); @@ -97,7 +98,7 @@ public function expandCategoryCollapsible(string $label): void /** * Chooses the desired answer in a message box * - * @throws \Exception + * @throws Exception */ public function answerMessageBox(string $answer): void { @@ -110,6 +111,25 @@ public function answerMessageBox(string $answer): void $answerButton->click(); } + /** + * Clicks the selected icon for the entry with a given name. + * + * @throws Exception + */ + public function clickEntryIconByName(string $name, string $icon): void + { + $editIconXpath = (new BackendXpathBuilder()) + ->child('div') + ->contains($name) + ->ancestor('tr', ['~class' => 'x-grid-row']) + ->descendant('img', ['~class' => $icon]) + ->getXpath(); + + $this->waitForXpathElementPresent($editIconXpath); + $editIcon = $this->find('xpath', $editIconXpath); + $editIcon->click(); + } + /** * Helper method that returns the current module window */ @@ -135,23 +155,4 @@ protected function getEditorWindow(bool $exactMatch = true): Window return $this->editorWindow; } - - /** - * Clicks the selected icon for the entry with a given name. - * - * @throws \Exception - */ - public function clickEntryIconByName(string $name, string $icon): void - { - $editIconXpath = (new BackendXpathBuilder()) - ->child('div') - ->contains($name) - ->ancestor('tr', ['~class' => 'x-grid-row']) - ->descendant('img', ['~class' => $icon]) - ->getXpath(); - - $this->waitForXpathElementPresent($editIconXpath); - $editIcon = $this->find('xpath', $editIconXpath); - $editIcon->click(); - } } diff --git a/tests/Page/Backend/CustomerModule.php b/tests/Page/Backend/CustomerModule.php index 22055e1..3bc9303 100644 --- a/tests/Page/Backend/CustomerModule.php +++ b/tests/Page/Backend/CustomerModule.php @@ -5,6 +5,7 @@ namespace Shopware\Page\Backend; use Behat\Mink\Element\NodeElement; +use Exception; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\Window; @@ -20,7 +21,7 @@ class CustomerModule extends BackendModule /** * Helper function that skips the intro wizard of the customer module */ - public function skipIntroWizardIfNecessary() + public function skipIntroWizardIfNecessary(): void { if ($this->waitIfThereIsText('Überspringen')) { $skipButton = $this->find('xpath', BackendXpathBuilder::getButtonXpathByLabel('Überspringen')); @@ -32,7 +33,7 @@ public function skipIntroWizardIfNecessary() * Fill the new customer form of the backend module with * the supplied data. */ - public function fillNewCustomerFormWith(array $data) + public function fillNewCustomerFormWith(array $data): void { $window = $this->getNewCustomerWindow(); $this->fillCustomerForm($window, $data); @@ -41,7 +42,7 @@ public function fillNewCustomerFormWith(array $data) /** * Fill the edit customer form with the supplied data */ - public function fillEditCustomerFormWith(array $data) + public function fillEditCustomerFormWith(array $data): void { $window = $this->getEditCustomerWindow(); $this->fillCustomerForm($window, $data); @@ -51,10 +52,9 @@ public function fillEditCustomerFormWith(array $data) * Click the edit icon for the customer with a given * firstname. */ - public function openEditFormForCustomer($firstname) + public function openEditFormForCustomer(string $firstname): void { - $window = $this->getModuleWindow(); - $customerRow = $window->getGridView()->getRowByContent($firstname); + $customerRow = $this->getModuleWindow()->getGridView()->getRowByContent($firstname); $customerRow->clickActionIcon('sprite-pencil'); } @@ -62,17 +62,16 @@ public function openEditFormForCustomer($firstname) * Click the delete icon for the customer with a given * firstname. */ - public function clickDeleteIconForCustomer($firstname) + public function clickDeleteIconForCustomer(string $firstname): void { - $window = $this->getModuleWindow(); - $customerRow = $window->getGridView()->getRowByContent($firstname); + $customerRow = $this->getModuleWindow()->getGridView()->getRowByContent($firstname); $customerRow->clickActionIcon('sprite-minus-circle-frame'); } /** * Fill a form within the supplied window with the supplied form data */ - private function fillCustomerForm(Window $window, array $data) + private function fillCustomerForm(Window $window, array $data): void { // Fill most form elements $this->fillExtJsForm($window, $data); @@ -89,10 +88,8 @@ private function fillCustomerForm(Window $window, array $data) /** * Special helper method that fills an extJS payment info combobox - * - * @param string $value */ - private function fillPaymentCombobox(NodeElement $combobox, $value) + private function fillPaymentCombobox(NodeElement $combobox, string $value): void { $builder = new BackendXpathBuilder(); @@ -107,27 +104,23 @@ private function fillPaymentCombobox(NodeElement $combobox, $value) foreach ($options as $option) { try { $option->click(); - } catch (\Exception $e) { + } catch (Exception $e) { } } } /** * Helper method to get the "new customer" window node element - * - * @return Window */ - private function getNewCustomerWindow() + private function getNewCustomerWindow(): Window { return Window::createFromTitle('Kunden-Administration - Neuen Kunden erstellen', $this->getSession()); } /** * Helper method to get the "edit customer" window node element - * - * @return Window */ - private function getEditCustomerWindow() + private function getEditCustomerWindow(): Window { return Window::createFromTitle('Kundenkonto:', $this->getSession(), false); } diff --git a/tests/Page/Backend/ExistingArticleModule.php b/tests/Page/Backend/ExistingArticleModule.php index b7b8fd3..4db03ef 100644 --- a/tests/Page/Backend/ExistingArticleModule.php +++ b/tests/Page/Backend/ExistingArticleModule.php @@ -5,6 +5,8 @@ namespace Shopware\Page\Backend; use Behat\Mink\Exception\ElementNotFoundException; +use Exception; +use RuntimeException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; class ExistingArticleModule extends NewArticleModule @@ -107,7 +109,7 @@ public function createOptionsForGroup(array $data, string $label): void * * @param array> $data * - * @throws \Exception + * @throws Exception */ public function selectProperty(array $data): void { @@ -123,40 +125,10 @@ public function selectProperty(array $data): void } } - /** - * Assigns an option to a selected group - * - * @throws \Exception - */ - private function chooseOption(string $value): void - { - $builder = new BackendXpathBuilder(); - $comboBoxXpath = $builder - ->child('table', ['@data-action' => 'values-table']) - ->descendant('td', [], 1) - ->followingSibling('td', [], 1) - ->descendant('div', ['~class' => 'x-form-trigger']) - ->getXpath(); - - $pebble = $this->find('xpath', $comboBoxXpath); - $pebble->click(); - sleep(1); - - $options = $this->findAll('xpath', - $builder->reset()->child('li', ['~class' => 'x-boundlist-item', 'and', '@text' => $value])->getXpath()); - - foreach ($options as $option) { - try { - $option->click(); - } catch (\Exception $e) { - } - } - } - /** * Checks if a specific value matches to a given property correctly * - * @throws \Exception + * @throws Exception */ public function checkCorrespondingPropertyValues(string $group, string $value): void { @@ -190,7 +162,7 @@ public function doInlineEditingOfVariant(string $orderNumber, string $additional $orderNumberInputField = $this->find('xpath', $orderNumberInputFieldXPath); $value = $orderNumberInputField->getValue(); if (!\is_string($value)) { - throw new \RuntimeException('Value of order number input field needs to be string'); + throw new RuntimeException('Value of order number input field needs to be string'); } $orderNumberInputField->setValue($value . $additionalText); @@ -202,4 +174,34 @@ public function openVariantDetailPage(string $orderNumber): void $variantRow = $this->getModuleWindow(false)->getGridView($orderNumber)->getRowByContent($orderNumber); $variantRow->clickActionIcon('sprite-pencil'); } + + /** + * Assigns an option to a selected group + * + * @throws Exception + */ + private function chooseOption(string $value): void + { + $builder = new BackendXpathBuilder(); + $comboBoxXpath = $builder + ->child('table', ['@data-action' => 'values-table']) + ->descendant('td', [], 1) + ->followingSibling('td', [], 1) + ->descendant('div', ['~class' => 'x-form-trigger']) + ->getXpath(); + + $pebble = $this->find('xpath', $comboBoxXpath); + $pebble->click(); + sleep(1); + + $options = $this->findAll('xpath', + $builder->reset()->child('li', ['~class' => 'x-boundlist-item', 'and', '@text' => $value])->getXpath()); + + foreach ($options as $option) { + try { + $option->click(); + } catch (Exception $e) { + } + } + } } diff --git a/tests/Page/Backend/NewArticleModule.php b/tests/Page/Backend/NewArticleModule.php index b5855b0..c8701a6 100644 --- a/tests/Page/Backend/NewArticleModule.php +++ b/tests/Page/Backend/NewArticleModule.php @@ -5,18 +5,20 @@ namespace Shopware\Page\Backend; use Behat\Mink\Element\NodeElement; +use Exception; +use RuntimeException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; class NewArticleModule extends BackendModule { - private $priceRowAnchor = 'Beliebig'; - protected string $moduleWindowTitle = 'Artikeldetails :'; + private string $priceRowAnchor = 'Beliebig'; + /** * Sets the price or other data for the article * - * @throws \Exception + * @throws Exception */ public function setArticlePriceData(string $value, string $cellAnchor, string $inputName): void { @@ -33,10 +35,74 @@ public function setArticlePriceData(string $value, string $cellAnchor, string $i $this->setPriceData($value, $priceCellPosition, $inputName); } + /** + * Sets the text for the short description + */ + public function setDescription(string $text): void + { + $this->getDriver()->executeScript("tinymce.get()[0].setContent('" . $text . "');"); + } + + /** + * Sets the basic information of the article + * + * @throws Exception + */ + public function setBasicData(array $data): void + { + $window = $this->getModuleWindow(false); + $this->fillExtJsForm($window, $data); + } + + /** + * Adds the category to the article + * + * @throws Exception + */ + public function addCategory(string $name): void + { + $window = $this->getModuleWindow(false); + $plusXpath = (new BackendXpathBuilder()) + ->child('div', ['@text' => $name]) + ->ancestor('tr', [], 1) + ->descendant('td', [], 2) + ->descendant('img') + ->getXpath(); + + $plus = $window->find('xpath', $plusXpath); + $plus->click(); + } + + /** + * Checks if the category is connected to the article correctly + * + * @throws Exception + */ + public function checkAddedCategory(string $name, string $area): void + { + $window = $this->getModuleWindow(false); + $plusXpath = (new BackendXpathBuilder()) + ->child('div', ['@text' => $name]) + ->ancestor('div', ['~class' => 'x-panel'], 1) + ->descendant('span', ['@text' => $area], 1) + ->getXpath(); + + $window->find('xpath', $plusXpath); + } + + /** + * Saves the article + */ + public function saveArticle(): void + { + $button = $this->waitForSelectorPresent('xpath', BackendXpathBuilder::getButtonXpathByLabel('Artikel speichern')); + $button->click(); + } + /** * Finds the field position for the price * - * @throws \Exception + * @throws Exception * * @return int position */ @@ -57,13 +123,13 @@ private function findPriceDataFieldPosition(NodeElement $cellElement, string $an } ++$positionIndex; } - throw new \Exception('Corresponding input field is missing.'); + throw new Exception('Corresponding input field is missing.'); } /** * Sets the price in the corresponding input field * - * @throws \Exception + * @throws Exception */ private function setPriceData(string $value, int $position, string $inputName): void { @@ -86,7 +152,7 @@ private function setPriceData(string $value, int $position, string $inputName): $this->waitForSelectorVisible('xpath', $priceFieldXpath); $priceField = $row->find('xpath', $priceFieldXpath); if (!$priceField instanceof NodeElement) { - throw new \RuntimeException(\sprintf('Could not find price field with xPath "%s"', $priceFieldXpath)); + throw new RuntimeException(\sprintf('Could not find price field with xPath "%s"', $priceFieldXpath)); } $priceField->click(); @@ -101,77 +167,4 @@ private function setPriceData(string $value, int $position, string $inputName): // Minks keyPress-method is buggy unfortunately, this is a workaround to de-focus the price input so its value is actually set. $window->click(); } - - /** - * Sets the text for the short description - * - * @param string $text - */ - public function setDescription($text) - { - $this->getDriver()->executeScript("tinymce.get()[0].setContent('" . $text . "');"); - } - - /** - * Sets the basic information of the article - * - * @param array $data - * - * @throws \Exception - */ - public function setBasicData($data) - { - $window = $this->getModuleWindow(false); - $this->fillExtJsForm($window, $data); - } - - /** - * Adds the category to the article - * - * @param string $name - * - * @throws \Exception - */ - public function addCategory($name) - { - $window = $this->getModuleWindow(false); - $plusXpath = (new BackendXpathBuilder()) - ->child('div', ['@text' => $name]) - ->ancestor('tr', [], 1) - ->descendant('td', [], 2) - ->descendant('img') - ->getXpath(); - - $plus = $window->find('xpath', $plusXpath); - $plus->click(); - } - - /** - * Checks if the category is connected to the article correctly - * - * @param string $name - * @param string $area - * - * @throws \Exception - */ - public function checkAddedCategory($name, $area): void - { - $window = $this->getModuleWindow(false); - $plusXpath = (new BackendXpathBuilder()) - ->child('div', ['@text' => $name]) - ->ancestor('div', ['~class' => 'x-panel'], 1) - ->descendant('span', ['@text' => $area], 1) - ->getXpath(); - - $window->find('xpath', $plusXpath); - } - - /** - * Saves the article - */ - public function saveArticle(): void - { - $button = $this->waitForSelectorPresent('xpath', BackendXpathBuilder::getButtonXpathByLabel('Artikel speichern')); - $button->click(); - } } diff --git a/tests/Page/Backend/PaymentModule.php b/tests/Page/Backend/PaymentModule.php index 14bacb2..adc93d3 100644 --- a/tests/Page/Backend/PaymentModule.php +++ b/tests/Page/Backend/PaymentModule.php @@ -5,6 +5,7 @@ namespace Shopware\Page\Backend; use Behat\Mink\Element\NodeElement; +use RuntimeException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; class PaymentModule extends BackendModule @@ -41,7 +42,7 @@ public function activatePaymentMethod(string $name): void $saveButton = $window->findButton('Speichern'); if (!$saveButton instanceof NodeElement) { - throw new \RuntimeException('Could not find save button'); + throw new RuntimeException('Could not find save button'); } $saveButton->click(); $this->waitForText('Zahlungsart gespeichert', 1); diff --git a/tests/Page/Backend/ProductExportModule.php b/tests/Page/Backend/ProductExportModule.php index e753276..de93662 100644 --- a/tests/Page/Backend/ProductExportModule.php +++ b/tests/Page/Backend/ProductExportModule.php @@ -5,6 +5,7 @@ namespace Shopware\Page\Backend; use Behat\Mink\Exception\ElementNotFoundException; +use Exception; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\GridView\GridViewRow; @@ -35,10 +36,8 @@ public function verify(array $urlParameters): bool /** * Fills in the product export configuration form - * - * @param array $formData */ - public function fillConfigurationForm($formData) + public function fillConfigurationForm(array $formData): void { $editor = $this->getEditorWindow(false); $this->fillExtJsForm($editor, $formData); @@ -49,7 +48,7 @@ public function fillConfigurationForm($formData) * * @param string $template The template itself * - * @throws \Exception + * @throws Exception */ public function enterTemplate(string $template): void { @@ -70,22 +69,17 @@ public function enterTemplate(string $template): void /** * Open a product export * - * @throws \Exception + * @throws Exception */ - public function openExport($exportTitle) + public function openExport(string $exportTitle): void { - $window = $this->getModuleWindow(); - - $exportRow = $window->getGridView()->getRowByContent($exportTitle); + $exportRow = $this->getModuleWindow()->getGridView()->getRowByContent($exportTitle); $exportUrl = $this->getExportUrl($exportRow); $this->getSession()->visit($exportUrl); } - /** - * @param string $supplierName - */ - public function blockSupplier($supplierName) + public function blockSupplier(string $supplierName): void { $supplierXpath = BackendXpathBuilder::create() ->child('span', ['@text' => 'Verfügbare Hersteller']) @@ -105,53 +99,41 @@ public function blockSupplier($supplierName) $this->waitForSelectorPresent('xpath', $buttonXpath)->click(); } - /** - * @param string $minPrice - */ - public function addMinimumPriceFilter($minPrice) + public function addMinimumPriceFilter(string $minPrice): void { $this->getEditorWindow()->getInput('Preis grösser:')->setValue($minPrice); } /** * Click the edit icon on the given export - * - * @param string $exportName */ - public function clickEditIconForExport($exportName) + public function clickEditIconForExport(string $exportName): void { $exportRow = $this->getModuleWindow()->getGridView()->getRowByContent($exportName); $exportRow->clickActionIcon('sprite-pencil'); } /** - * @throws \Exception + * @throws Exception */ public function checkExportResult(string $expected): void { $actual = $this->getText(); if ($this->normalizeText($expected) !== $this->normalizeText($actual)) { - throw new \Exception('Product stream not as expected.. Expected: ' . $expected . ' but got ' . $actual); + throw new Exception('Product stream not as expected.. Expected: ' . $expected . ' but got ' . $actual); } } /** * Normalize a given string by removing tabs, spaces and newlines from, allowing better comparison - * - * @param string $text - * - * @return string */ - private function normalizeText($text) + private function normalizeText(string $text): string { return str_replace([' ', '\t', '\n'], '', $text); } - /** - * @return string - */ - private function getExportUrl(GridViewRow $exportRow) + private function getExportUrl(GridViewRow $exportRow): string { $fileLinkXpath = BackendXpathBuilder::create()->descendant('a', [], 1)->getXpath(); $fileLink = $exportRow->find('xpath', $fileLinkXpath)->getAttribute('href'); diff --git a/tests/Page/Backend/QuestionMarkModule.php b/tests/Page/Backend/QuestionMarkModule.php index 6c580cc..a4d92c3 100644 --- a/tests/Page/Backend/QuestionMarkModule.php +++ b/tests/Page/Backend/QuestionMarkModule.php @@ -59,7 +59,7 @@ public function getVersionNr(): string * * @return string buildnr */ - public function getBuildNr() + public function getBuildNr(): string { $xpath = BackendXpathBuilder::create() ->child('div', diff --git a/tests/Page/Backend/SettingsModule.php b/tests/Page/Backend/SettingsModule.php index 42f398e..63c5753 100644 --- a/tests/Page/Backend/SettingsModule.php +++ b/tests/Page/Backend/SettingsModule.php @@ -14,7 +14,7 @@ class SettingsModule extends BackendModule * * @param string $elementName Name of the element */ - public function clickOnMenuElement($elementName) + public function clickOnMenuElement(string $elementName): void { $xpath = BackendXpathBuilder::create() ->child('span', ['@text' => $elementName, 'and', '~class' => 'x-menu-item-text']) @@ -31,7 +31,7 @@ public function clickOnMenuElement($elementName) * * @param string $elementName Name of the element */ - public function clickOnSettingsMenuElement($elementName) + public function clickOnSettingsMenuElement(string $elementName): void { $xpath = BackendXpathBuilder::create() ->child('div', ['@text' => $elementName, 'and', '~class' => 'x-grid-cell-inner']) @@ -48,7 +48,7 @@ public function clickOnSettingsMenuElement($elementName) * * @param array $data Defines the form field and their data */ - public function fillShopConfigurationForm(array $data) + public function fillShopConfigurationForm(array $data): void { $window = Window::createFromTitle('Grundeinstellungen - Shops', $this->getSession()); $this->fillExtJsForm($window, $data); diff --git a/tests/Page/Backend/ShippingModule.php b/tests/Page/Backend/ShippingModule.php index 8075d94..98eac83 100644 --- a/tests/Page/Backend/ShippingModule.php +++ b/tests/Page/Backend/ShippingModule.php @@ -6,6 +6,7 @@ use Behat\Mink\Element\NodeElement; use Behat\Mink\Exception\ElementNotFoundException; +use Exception; use Shopware\Component\XpathBuilder\BackendXpathBuilder; use Shopware\Element\Backend\Window; @@ -23,7 +24,7 @@ class ShippingModule extends BackendModule /** * Create a new shipping method from the details provided. */ - public function createShippingMethodIfNotExists(array $shipping) + public function createShippingMethodIfNotExists(array $shipping): void { $this->open(); @@ -65,10 +66,8 @@ public function createShippingMethodIfNotExists(array $shipping) /** * Delete a shipping method by its name - * - * @param string $shippingMethod */ - public function deleteShippingMethod($shippingMethod) + public function deleteShippingMethod(string $shippingMethod): void { $shippingRow = $this->getModuleWindow()->getGridView()->getRowByContent($shippingMethod); $shippingRow->clickActionIcon('sprite-minus-circle-frame'); @@ -81,7 +80,7 @@ public function deleteShippingMethod($shippingMethod) /** * Set the shipping cost configuration for a given shipping method * - * @throws \Exception + * @throws Exception */ public function setShippingCosts(string $methodName, array $costData): void { @@ -89,7 +88,7 @@ public function setShippingCosts(string $methodName, array $costData): void $window = $this->getModuleWindow(); if (!$this->shippingMethodExists($methodName)) { - throw new \Exception(\sprintf('Missing shipping method "%s"', $methodName)); + throw new Exception(\sprintf('Missing shipping method "%s"', $methodName)); } $methodRow = $window->getGridView()->getRowByContent($methodName); @@ -125,7 +124,7 @@ public function setShippingCosts(string $methodName, array $costData): void /** * Helper method that clicks the 'Add Shipping Method' button */ - private function clickAddShippingMethodButton() + private function clickAddShippingMethodButton(): void { $buttonXpath = '//button[@data-action="addShipping"]'; $this->waitForSelectorPresent('xpath', $buttonXpath, 7); @@ -165,7 +164,7 @@ private function activatePaymentMethods(NodeElement $editor, array $paymentMetho /** * Activated a given set of countries for the shipping method that is currently being edited */ - private function activateCountries(NodeElement $editor, array $countries) + private function activateCountries(NodeElement $editor, array $countries): void { $countriesTabXpath = BackendXpathBuilder::getTabXpathByLabel('Länder Auswahl'); $editor->find('xpath', $countriesTabXpath)->click(); @@ -181,12 +180,8 @@ private function activateCountries(NodeElement $editor, array $countries) /** * Helper method to get an extJs grid row by its content. Useful for assigning countries and payment methods * to a shipping method. - * - * @param string $text - * - * @return NodeElement|null */ - private function getGridRowByContent($text, ?NodeElement $scope = null) + private function getGridRowByContent(string $text, ?NodeElement $scope = null): ?NodeElement { $xpath = BackendXpathBuilder::create() ->child('div', ['@text' => $text]) @@ -200,20 +195,15 @@ private function getGridRowByContent($text, ?NodeElement $scope = null) /** * Helper method that fills a given cell with a value - * - * @param string $columnValue */ - private function fillCell(NodeElement $cell, $columnValue) + private function fillCell(NodeElement $cell, string $columnValue): void { $cell->doubleClick(); $focusedInput = $this->waitForSelectorPresent('xpath', BackendXpathBuilder::getFocusedElementXpath()); $focusedInput->setValue($columnValue); } - /** - * @return array - */ - private function buildShippingConfigFormData(array $shipping) + private function buildShippingConfigFormData(array $shipping): array { return [ ['label' => 'Name:', 'value' => $shipping['name'], 'type' => 'input'], @@ -228,45 +218,31 @@ private function buildShippingConfigFormData(array $shipping) ]; } - /** - * @return NodeElement - */ - private function getShippingCostCell(NodeElement $editor) + private function getShippingCostCell(NodeElement $editor): NodeElement { $costCellXpath = BackendXpathBuilder::create() ->child('tr', ['~class' => 'x-grid-row'], 1) ->descendant('div', ['~class' => 'x-grid-cell-inner'], 3) ->getXpath(); - $costCell = $editor->find('xpath', $costCellXpath); - return $costCell; + return $editor->find('xpath', $costCellXpath); } - /** - * @return array - */ - private function extractPaymentMethodsToActivate(array $shipping) + private function extractPaymentMethodsToActivate(array $shipping): array { - $paymentMethods = strpos($shipping['activePaymentMethods'], ',') + return strpos($shipping['activePaymentMethods'], ',') ? explode(', ', $shipping['activePaymentMethods']) : [$shipping['activePaymentMethods']]; - - return $paymentMethods; } - /** - * @return array - */ - private function extractShippingCountriesToActivate(array $shipping) + private function extractShippingCountriesToActivate(array $shipping): array { - $countries = strpos($shipping['activeCountries'], ',') + return strpos($shipping['activeCountries'], ',') ? explode(', ', $shipping['activeCountries']) : [$shipping['activeCountries']]; - - return $countries; } - private function emptyShippingCostConfiguration(Window $editor) + private function emptyShippingCostConfiguration(Window $editor): void { $costRowsXpath = BackendXpathBuilder::create()->child('tr', ['~class' => 'x-grid-row'])->getXpath(); $costRows = $editor->findAll('xpath', $costRowsXpath); diff --git a/tests/Page/Backend/SystemInfoModule.php b/tests/Page/Backend/SystemInfoModule.php index 8c3d2b6..70cf537 100644 --- a/tests/Page/Backend/SystemInfoModule.php +++ b/tests/Page/Backend/SystemInfoModule.php @@ -5,7 +5,6 @@ namespace Shopware\Page\Backend; use Behat\Mink\Element\NodeElement; -use Behat\Mink\Exception\ElementNotFoundException; use Shopware\Component\XpathBuilder\BackendXpathBuilder; class SystemInfoModule extends BackendModule @@ -18,7 +17,7 @@ class SystemInfoModule extends BackendModule * @param string $item The requirement which should be checked * @param bool $expectedStatus Determines if the requirement should be met or not **/ - public function checkRequirements($item, $expectedStatus) + public function checkRequirements(string $item, bool $expectedStatus): void { if ($expectedStatus) { $this->checkStatus($item, 'sprite-tick'); @@ -29,13 +28,8 @@ public function checkRequirements($item, $expectedStatus) /** * Check if a given requirement has a given state - * - * @param string $item - * @param string $class - * - * @return bool */ - private function checkStatus($item, $class) + private function checkStatus(string $item, string $class): void { $grid = $this->getGridForGridItem($item); $statusXpath = BackendXpathBuilder::create() @@ -44,13 +38,7 @@ private function checkStatus($item, $class) ->descendant('div', ['~class' => $class]) ->getXpath(); - try { - $grid->find('xpath', $statusXpath); - } catch (ElementNotFoundException $e) { - return false; - } - - return true; + $grid->find('xpath', $statusXpath); } /** diff --git a/tests/Page/Backend/VoucherModule.php b/tests/Page/Backend/VoucherModule.php index 32cbc7b..31b68a9 100644 --- a/tests/Page/Backend/VoucherModule.php +++ b/tests/Page/Backend/VoucherModule.php @@ -11,21 +11,15 @@ class VoucherModule extends BackendModule */ protected $path = '/backend/?app=Voucher'; - /** - * {@inheritdoc} - */ protected string $moduleWindowTitle = 'Gutschein-Administration'; - /** - * {@inheritdoc} - */ protected string $editorWindowTitle = 'Gutschein-Konfiguration'; /** * Fill the new voucher form of the backend module with * the supplied data. */ - public function fillVoucherEditorFormWith(array $data) + public function fillVoucherEditorFormWith(array $data): void { $window = $this->getEditorWindow(); $this->fillExtJsForm($window, $data); @@ -34,7 +28,7 @@ public function fillVoucherEditorFormWith(array $data) /** * Click the edit icon for the row containing $name */ - public function openEditFormForVoucher($name) + public function openEditFormForVoucher(string $name): void { $voucherRow = $this->getModuleWindow()->getGridView()->getRowByContent($name); $voucherRow->clickActionIcon('sprite-pencil'); @@ -43,7 +37,7 @@ public function openEditFormForVoucher($name) /** * Delete a voucher by its name */ - public function deleteVoucher($name) + public function deleteVoucher(string $name): void { $voucherRow = $this->getModuleWindow()->getGridView()->getRowByContent($name); $voucherRow->clickActionIcon('sprite-minus-circle-frame'); diff --git a/tests/Page/ContextAwarePage.php b/tests/Page/ContextAwarePage.php index f0e2e38..85abf3d 100644 --- a/tests/Page/ContextAwarePage.php +++ b/tests/Page/ContextAwarePage.php @@ -6,6 +6,7 @@ use Behat\Mink\Element\NodeElement; use Behat\Mink\Exception\ElementNotFoundException; +use Exception; use SensioLabs\Behat\PageObjectExtension\PageObject\Page; use Shopware\Component\SpinTrait\SpinTrait; @@ -13,10 +14,40 @@ class ContextAwarePage extends Page { use SpinTrait; + /** + * @param string[]|string $locator + * + * @throws ElementNotFoundException + */ + public function find(string $selector, $locator): NodeElement + { + $element = parent::find($selector, $locator); + if ($element === null) { + if (\is_array($locator)) { + $locator = implode(' ', $locator); + } + throw new ElementNotFoundException($this->getDriver(), null, $selector, $locator); + } + + return $element; + } + + /** + * @param array|string $locator + */ + public function has(string $selector, $locator): bool + { + try { + return parent::has($selector, $locator); + } catch (ElementNotFoundException $e) { + return false; + } + } + /** * Checks via spin function if a string exists, with sleep at the beginning (default 2) * - * @throws \Exception + * @throws Exception */ protected function waitForText(string $text, int $sleep = 2): void { @@ -53,7 +84,7 @@ protected function checkIfThereIsText(string $text, ContextAwarePage $context): * * @param string $selector css, xpath... * - * @throws \Exception + * @throws Exception */ protected function waitForSelectorPresent(string $selector, string $locator, int $sleep = 2): NodeElement { @@ -80,7 +111,7 @@ protected function waitForSelectorPresent(string $selector, string $locator, int * * @param string $selector css, xpath... * - * @throws \Exception + * @throws Exception */ protected function waitForSelectorNotPresent(string $selector, string $locator, int $sleep = 2): void { @@ -98,7 +129,7 @@ protected function waitForSelectorNotPresent(string $selector, string $locator, /** * Checks via spin function if an element is present on page via given xpath, with sleep at the beginning (default 2) * - * @throws \Exception + * @throws Exception */ protected function waitForXpathElementPresent(string $xpath, int $sleep = 2): void { @@ -116,7 +147,7 @@ protected function waitForXpathElementPresent(string $xpath, int $sleep = 2): vo /** * Checks via spin function if a string exists, with sleep at the beginning (default 2) * - * @throws \Exception + * @throws Exception */ protected function waitForTextNotPresent(string $text, int $sleep = 2): void { @@ -128,7 +159,7 @@ protected function waitForTextNotPresent(string $text, int $sleep = 2): void * * @param string $selector css, xpath... * - * @throws \Exception + * @throws Exception */ protected function waitForSelectorVisible(string $selector, string $locator): void { @@ -153,36 +184,4 @@ protected function waitForSelectorInvisible(string $selector, string $locator, i return empty($elem) || !$elem->isVisible(); }, 90); } - - /** - * @param string $selector - * @param string[]|string $locator - * - * @throws ElementNotFoundException - */ - public function find($selector, $locator): NodeElement - { - $element = parent::find($selector, $locator); - if ($element === null) { - if (\is_array($locator)) { - $locator = implode(' ', $locator); - } - throw new ElementNotFoundException($this->getDriver(), null, $selector, $locator); - } - - return $element; - } - - /** - * @param string $selector - * @param array|string $locator - */ - public function has($selector, $locator): bool - { - try { - return parent::has($selector, $locator); - } catch (ElementNotFoundException $e) { - return false; - } - } } diff --git a/tests/Page/Frontend/Account.php b/tests/Page/Frontend/Account.php index 58fd2bd..6a3c5e1 100644 --- a/tests/Page/Frontend/Account.php +++ b/tests/Page/Frontend/Account.php @@ -19,11 +19,8 @@ class Account extends ContextAwarePage /** * Logs a user into the frontend - * - * @param string $email - * @param string $password */ - public function login($email, $password) + public function login(string $email, string $password): void { $this->open(); @@ -42,7 +39,7 @@ public function login($email, $password) /** * Log the currently authenticated user out of the frontend */ - public function logout() + public function logout(): void { $this->open(); $this->getDriver()->visit($this->getDriver()->getCurrentUrl() . '/logout'); @@ -51,7 +48,7 @@ public function logout() /** * Fills the fields of the registration form and submits it */ - public function register(array $data) + public function register(array $data): void { $this->open(); $this->fillForm($this, $data); diff --git a/tests/Page/Frontend/CheckoutCart.php b/tests/Page/Frontend/CheckoutCart.php index 534f683..d64d8c2 100644 --- a/tests/Page/Frontend/CheckoutCart.php +++ b/tests/Page/Frontend/CheckoutCart.php @@ -4,6 +4,7 @@ namespace Shopware\Page\Frontend; +use Exception; use Shopware\Component\XpathBuilder\FrontendXpathBuilder; use Shopware\Element\Frontend\Checkout\CartPosition; use Shopware\Page\ContextAwarePage; @@ -15,10 +16,7 @@ class CheckoutCart extends ContextAwarePage */ protected $path = '/checkout/cart'; - /** - * {@inheritdoc} - */ - public function getCssSelectors() + public function getCssSelectors(): array { return [ 'sum' => 'li.entry--sum > div.entry--value', @@ -28,10 +26,7 @@ public function getCssSelectors() ]; } - /** - * {@inheritdoc} - */ - public function getXPathSelectors() + public function getXPathSelectors(): array { return [ 'addProductInput' => FrontendXpathBuilder::create() @@ -61,7 +56,7 @@ public function getXPathSelectors() /** * Validate the cart contains the given expected cart positions */ - public function validateCart(array $positionData) + public function validateCart(array $positionData): void { $expectedPositions = $this->hydratePositionData($positionData); $actualPositions = $this->extractActualCartPositions(); @@ -71,10 +66,8 @@ public function validateCart(array $positionData) /** * Adds an article to the cart - * - * @param string $article */ - public function addArticle($article) + public function addArticle(string $article): void { $addProductInputXpath = $this->getXPathSelectors()['addProductInput']; $addProductSubmitXpath = $this->getXPathSelectors()['addProductSubmit']; @@ -88,18 +81,15 @@ public function addArticle($article) /** * Remove the cart position at the specified index * - * @param int $position - * - * @throws \Exception + * @throws Exception */ - public function removeCartPositionAtIndex($position) + public function removeCartPositionAtIndex(int $position): void { $this->open(); $rows = $this->findAll('xpath', $this->getXPathSelectors()['cartPositionRow']); - $position = (int) $position; if ($position > \count($rows)) { - throw new \Exception(\sprintf('Can\'t delete cart position #%s - no such position', $position)); + throw new Exception(\sprintf('Can\'t delete cart position #%s - no such position', $position)); } $row = $rows[$position - 1]; @@ -109,7 +99,7 @@ public function removeCartPositionAtIndex($position) /** * Checks the aggregation * - * @throws \Exception + * @throws Exception */ public function checkAggregation(array $aggregation): void { @@ -121,28 +111,28 @@ public function checkAggregation(array $aggregation): void $element = $this->find('css', $this->getCssSelectors()['sum']); $value = $element->getText(); if (self::toFloat($value) !== self::toFloat($row['value'])) { - throw new \Exception('Expected cart sum to be ' . $row['value'] . ', got ' . $value); + throw new Exception('Expected cart sum to be ' . $row['value'] . ', got ' . $value); } break; case 'shipping': $element = $this->find('css', $this->getCssSelectors()['shipping']); $value = $element->getText(); if (self::toFloat($value) !== self::toFloat($row['value'])) { - throw new \Exception('Expected shipping to be ' . $row['value'] . ', got ' . $value); + throw new Exception('Expected shipping to be ' . $row['value'] . ', got ' . $value); } break; case 'total': $element = $this->find('css', $this->getCssSelectors()['total']); $value = $element->getText(); if (self::toFloat($value) !== self::toFloat($row['value'])) { - throw new \Exception('Expected total to be ' . $row['value'] . ', got ' . $value); + throw new Exception('Expected total to be ' . $row['value'] . ', got ' . $value); } break; case 'sumWithoutVat': $element = $this->find('css', $this->getCssSelectors()['sumWithoutVat']); $value = $element->getText(); if (self::toFloat($value) !== self::toFloat($row['value'])) { - throw new \Exception('Expected sum without vat to be ' . $row['value'] . ', got ' . $value); + throw new Exception('Expected sum without vat to be ' . $row['value'] . ', got ' . $value); } break; } @@ -152,9 +142,9 @@ public function checkAggregation(array $aggregation): void /** * Fills the cart with products * - * @throws \Exception + * @throws Exception */ - public function fillCartWithProducts(array $items) + public function fillCartWithProducts(array $items): void { $originalPath = $this->path; @@ -176,12 +166,10 @@ public function fillCartWithProducts(array $items) /** * Remove all products from the cart */ - public function emptyCart() + public function emptyCart(): void { $this->open(); - $rows = $this->findAll('xpath', $this->getXPathSelectors()['cartPositionRow']); - - foreach ($rows as $row) { + foreach ($this->findAll('xpath', $this->getXPathSelectors()['cartPositionRow']) as $row) { $row->findButton('Löschen')->click(); } } @@ -189,12 +177,12 @@ public function emptyCart() /** * Check the cart position count and cart sum * - * @throws \Exception + * @throws Exception */ - public function checkPositionCountAndCartSum(string $quantity, string $amount) + public function checkPositionCountAndCartSum(string $quantity, string $amount): void { if ($this->getCartPositionCount() !== (int) $quantity || $this->getCartSum() !== self::toFloat($amount)) { - throw new \Exception(\sprintf('Expected %s positions with a sum of %s, but got %s with a sum of %s', + throw new Exception(\sprintf('Expected %s positions with a sum of %s, but got %s with a sum of %s', $quantity, $amount, $this->getCartPositionCount(), $this->getCartSum())); } } @@ -202,18 +190,44 @@ public function checkPositionCountAndCartSum(string $quantity, string $amount) /** * Proceeds to the confirmation page */ - public function proceedToOrderConfirmation() + public function proceedToOrderConfirmation(): void { $this->open(); $this->clickLink('Zur Kasse'); } + /** + * Add voucher to the cart + */ + public function addVoucher(string $code): void + { + $this->open(); + + $voucherInputXpath = FrontendXpathBuilder::getElementXpathByName('input', 'sVoucher'); + $this->waitForSelectorPresent('xpath', $voucherInputXpath); + $this->find('xpath', $voucherInputXpath)->setValue($code); + + $voucherSubmitXpath = FrontendXpathBuilder::create($voucherInputXpath)->followingSibling('button')->getXpath(); + $this->waitForSelectorPresent('xpath', $voucherSubmitXpath); + $this->find('xpath', $voucherSubmitXpath)->click(); + } + + /** + * {@inheritdoc} + */ + protected function verifyPage(): bool + { + if (strpos($this->getHtml(), 'is--ctl-checkout is--act-cart') === false) { + throw new Exception('Could not verify page - expected to be on checkout/cart.'); + } + + return true; + } + /** * Return number of positions in cart - * - * @return int */ - private function getCartPositionCount() + private function getCartPositionCount(): int { $this->open(); $rows = $this->findAll('xpath', $this->getXPathSelectors()['cartPositionRow']); @@ -237,7 +251,7 @@ private function getCartSum(): float * * @return CartPosition[] */ - private function extractActualCartPositions() + private function extractActualCartPositions(): array { $this->open(); $rows = $this->findAll('xpath', $this->getXPathSelectors()['cartPositionRow']); @@ -263,12 +277,12 @@ private function extractActualCartPositions() * @param CartPosition[] $expected * @param CartPosition[] $actual * - * @throws \Exception + * @throws Exception */ - private function assertCartPositionListsAreEqual(array $expected, array $actual) + private function assertCartPositionListsAreEqual(array $expected, array $actual): void { if (\count($expected) !== \count($actual)) { - throw new \Exception(\sprintf('Expected %s cart positions, got %s.', \count($expected), \count($actual))); + throw new Exception(\sprintf('Expected %s cart positions, got %s.', \count($expected), \count($actual))); } foreach ($expected as $expectedPosition) { @@ -278,23 +292,21 @@ private function assertCartPositionListsAreEqual(array $expected, array $actual) continue 2; } - throw new \Exception(\sprintf('Cart positions not as expected: Expected: %s Got: %s', + throw new Exception(\sprintf('Cart positions not as expected: Expected: %s Got: %s', print_r($expectedPosition, true), print_r($actualPosition, true)) ); } } - throw new \Exception(\sprintf('Could not find position %s', print_r($expectedPosition, true))); + throw new Exception(\sprintf('Could not find position %s', print_r($expectedPosition, true))); } } /** * Compare two cart positions for equality - * - * @return bool */ - private function compareCartPositions(CartPosition $expected, CartPosition $actual) + private function compareCartPositions(CartPosition $expected, CartPosition $actual): bool { return $actual->getName() === $expected->getName() && strpos($actual->getNumber(), $expected->getNumber()) !== false @@ -305,10 +317,8 @@ private function compareCartPositions(CartPosition $expected, CartPosition $actu /** * Returns true if the cart contains a product with a given number and a given quantity - * - * @return bool */ - private function hasCartProductWithQuantity($number, $quantity) + private function hasCartProductWithQuantity(string $number, string $quantity): bool { $xPath = "//p[contains(text(), '" . $number . "')]//ancestor::div[contains(concat(' ', normalize-space(@class), ' '), ' row--product ')]//input[@name='sArticle' and @value='" . $quantity . "']"; @@ -317,6 +327,8 @@ private function hasCartProductWithQuantity($number, $quantity) /** * Convert a given string value to a float + * + * @param string|float $string */ private static function toFloat($string): float { @@ -330,42 +342,9 @@ private static function toFloat($string): float return (float) ($matches[0] ?? 0.0); } - /** - * Add voucher to the cart - * - * @param string $code - */ - public function addVoucher($code) - { - $this->open(); - - $voucherInputXpath = FrontendXpathBuilder::getElementXpathByName('input', 'sVoucher'); - $this->waitForSelectorPresent('xpath', $voucherInputXpath); - $this->find('xpath', $voucherInputXpath)->setValue($code); - - $voucherSubmitXpath = FrontendXpathBuilder::create($voucherInputXpath)->followingSibling('button')->getXpath(); - $this->waitForSelectorPresent('xpath', $voucherSubmitXpath); - $this->find('xpath', $voucherSubmitXpath)->click(); - } - - /** - * {@inheritdoc} - */ - protected function verifyPage() - { - if (!strpos($this->getHtml(), 'is--ctl-checkout is--act-cart')) { - throw new \Exception('Could not verify page - expected to be on checkout/cart.'); - } - - return true; - } - - /** - * @return array - */ private function hydratePositionData(array $positionData): array { - return array_map(function ($position) { + return array_map(static function (array $position) { return CartPosition::fromArray($position); }, $positionData); } diff --git a/tests/Page/Frontend/CheckoutConfirm.php b/tests/Page/Frontend/CheckoutConfirm.php index 878c6e3..3f4824f 100644 --- a/tests/Page/Frontend/CheckoutConfirm.php +++ b/tests/Page/Frontend/CheckoutConfirm.php @@ -4,6 +4,7 @@ namespace Shopware\Page\Frontend; +use RuntimeException; use Shopware\Component\Form\FormFillerTrait; use Shopware\Page\ContextAwarePage; @@ -19,21 +20,22 @@ class CheckoutConfirm extends ContextAwarePage /** * Proceeds the checkout */ - public function proceedToCheckout() + public function proceedToCheckout(): void { $this->open(); $this->checkField('sAGB'); $button = $this->findButton('Zahlungspflichtig bestellen'); + if ($button === null) { + throw new RuntimeException('Could not find the submit button'); + } $button->focus(); $button->click(); } /** * Fill out the registration form during checkout - * - * @param array $formData */ - public function fillOutRegistrationForm($formData) + public function fillOutRegistrationForm(array $formData): void { $this->fillForm($this, $formData); } diff --git a/tests/Page/Frontend/CheckoutShippingPayment.php b/tests/Page/Frontend/CheckoutShippingPayment.php index d3dea86..24eb172 100644 --- a/tests/Page/Frontend/CheckoutShippingPayment.php +++ b/tests/Page/Frontend/CheckoutShippingPayment.php @@ -30,10 +30,8 @@ public function changeShippingMethodTo(string $shippingMethod): void /** * Change the currently selected payment method - * - * @param string $paymentMethod */ - public function changePaymentMethodTo($paymentMethod) + public function changePaymentMethodTo(string $paymentMethod): void { if (!$this->verifyUrl()) { $this->open(); @@ -48,12 +46,8 @@ public function changePaymentMethodTo($paymentMethod) /** * Return the shipping or payment method with the given name - * - * @param string $methodName - * - * @return NodeElement|null */ - public function getMethodElement($methodName) + public function getMethodElement(string $methodName): NodeElement { $elementXpath = FrontendXpathBuilder::create() ->child('label', ['@text' => $methodName]) @@ -66,10 +60,8 @@ public function getMethodElement($methodName) /** * Verifies that we currently are on the shipping/payment page - * - * @return bool */ - protected function verifyUrl(array $urlParameters = []) + protected function verifyUrl(array $urlParameters = []): bool { return $this->getDriver()->getCurrentUrl() === $this->getUrl($urlParameters); } @@ -77,7 +69,7 @@ protected function verifyUrl(array $urlParameters = []) /** * Select a shipping method from the list in the frontend */ - private function selectShippingMethod($shippingMethod) + private function selectShippingMethod(string $shippingMethod): void { $element = $this->getMethodElement($shippingMethod); $element->click(); @@ -87,7 +79,7 @@ private function selectShippingMethod($shippingMethod) * Select a payment method from the list in the frontend and * fill in some demo SEPA data if necessary */ - private function selectPaymentMethod($paymentMethod) + private function selectPaymentMethod(string $paymentMethod): void { $element = $this->getMethodElement($paymentMethod); $element->click(); diff --git a/tests/Page/Frontend/Detail.php b/tests/Page/Frontend/Detail.php index 91bd5b7..4016dcd 100644 --- a/tests/Page/Frontend/Detail.php +++ b/tests/Page/Frontend/Detail.php @@ -5,6 +5,7 @@ namespace Shopware\Page\Frontend; use Behat\Mink\Exception\ElementNotFoundException; +use Exception; use Shopware\Component\XpathBuilder\FrontendXpathBuilder; use Shopware\Page\ContextAwarePage; @@ -18,11 +19,9 @@ class Detail extends ContextAwarePage /** * Puts the current article times to basket * - * @param string $quantity - * * @throws ElementNotFoundException */ - public function toBasket($quantity = '1') + public function toBasket(string $quantity = '1'): void { $this->fillField('sQuantity', $quantity); $this->pressButton('In den Warenkorb'); @@ -31,13 +30,11 @@ public function toBasket($quantity = '1') /** * Checks if the variants are applied in the frontend correctly * - * @throws \Exception + * @throws Exception */ - public function waitForOverlayToDisappear() + public function waitForOverlayToDisappear(): void { - $builder = new FrontendXpathBuilder(); - - $overlayXpath = $builder + $overlayXpath = (new FrontendXpathBuilder()) ->child('div', ['~class' => 'js--overlay'], 1) ->getXpath(); @@ -47,18 +44,14 @@ public function waitForOverlayToDisappear() /** * Checks if the amount and the corresponding graduated price are matching correctly * - * @param string $graduatedprice - * - * @throws \Exception + * @throws Exception */ - public function checkGraduatedPrice($graduatedprice) + public function checkGraduatedPrice(array $graduatedPrice): void { - $builder = new FrontendXpathBuilder(); - - $grPriceXpath = $builder - ->child('span', ['~text' => $graduatedprice['amount'], 'and', '~class' => 'block-prices--quantity'], 1) + $grPriceXpath = (new FrontendXpathBuilder()) + ->child('span', ['~text' => $graduatedPrice['amount'], 'and', '~class' => 'block-prices--quantity'], 1) ->ancestor('tr', [], 1) - ->child('td', ['~text' => $graduatedprice['price'], 'and', '~class' => 'block-prices--cell'], 1) + ->child('td', ['~text' => $graduatedPrice['price'], 'and', '~class' => 'block-prices--cell'], 1) ->getXpath(); $this->waitForSelectorPresent('xpath', $grPriceXpath); @@ -67,11 +60,9 @@ public function checkGraduatedPrice($graduatedprice) /** * Checks if the base price information is shown correctly * - * @param string $entry - * - * @throws \Exception + * @throws Exception */ - public function checkBasePrice($entry) + public function checkBasePrice(array $entry): void { $builder = new FrontendXpathBuilder(); diff --git a/tests/Page/Frontend/Index.php b/tests/Page/Frontend/Index.php index 72fbc39..ab08468 100644 --- a/tests/Page/Frontend/Index.php +++ b/tests/Page/Frontend/Index.php @@ -15,10 +15,7 @@ class Index extends ContextAwarePage */ protected $path = '/'; - /** - * {@inheritdoc} - */ - public function getXPathSelectors() + public function getXPathSelectors(): array { return [ 'templateMainNav' => FrontendXpathBuilder::create() @@ -45,32 +42,17 @@ public function getXPathSelectors() ]; } - /** - * @param string $subCategory - * - * @return NodeElement|null - */ - public function getSubNavElement($subCategory) + public function getSubNavElement(string $subCategory): ?NodeElement { return $this->getNavElement($subCategory, 'templateSubNav'); } - /** - * @param string $mainCategory - * - * @return NodeElement|null - */ - public function getMainNavElement($mainCategory) + public function getMainNavElement(string $mainCategory): ?NodeElement { return $this->getNavElement($mainCategory, 'templateMainNav'); } - /** - * @param string $productName - * - * @return NodeElement - */ - public function getProductListingBoxElement($productName) + public function getProductListingBoxElement(string $productName): NodeElement { $xpath = $this->getXPathSelectors()['templateListingProductBoxByName']; diff --git a/tests/Page/Installer/InstallerIndex.php b/tests/Page/Installer/InstallerIndex.php index 48cee28..1223b53 100644 --- a/tests/Page/Installer/InstallerIndex.php +++ b/tests/Page/Installer/InstallerIndex.php @@ -4,6 +4,7 @@ namespace Shopware\Page\Installer; +use Exception; use Shopware\Component\XpathBuilder\FrontendXpathBuilder; use Shopware\Page\ContextAwarePage; @@ -14,10 +15,7 @@ class InstallerIndex extends ContextAwarePage */ protected $path = '/recovery/install/index.php'; - /** - * {@inheritdoc} - */ - public function getXPathSelectors() + public function getXPathSelectors(): array { $builder = new FrontendXpathBuilder(); @@ -45,10 +43,7 @@ public function getXPathSelectors() ]; } - /** - * {@inheritdoc} - */ - public function getCssSelectors() + public function getCssSelectors(): array { return [ 'ce' => '#optionsRadios1', @@ -62,7 +57,7 @@ public function getCssSelectors() /** * Advances to the next page */ - public function advance() + public function advance(): void { $forwardButton = $this->waitForSelectorPresent('xpath', $this->getXPathSelectors()['forwardButton']); $forwardButton->click(); @@ -73,7 +68,7 @@ public function advance() * * @param string $identifier Xpath identifier from InstallerIndex */ - public function tickCheckbox($identifier) + public function tickCheckbox(string $identifier): void { $checkboxButton = $this->find('xpath', $this->getXPathSelectors()[$identifier]); $checkboxButton->check(); @@ -82,9 +77,9 @@ public function tickCheckbox($identifier) /** * Checks, if a particular field is required * - * @param string $field The given field of the form + * @param array $field The given field of the form */ - public function checkRequiredFields($field) + public function checkRequiredFields(array $field): void { $this->find('xpath', $this->getXPathSelectors()[$field['fieldname']])->hasAttribute('required'); } @@ -94,7 +89,7 @@ public function checkRequiredFields($field) * * @param array $data The data of the form */ - public function fillInAndSubmitForm($data) + public function fillInAndSubmitForm(array $data): void { foreach ($data as $formElement) { $elementXpath = FrontendXpathBuilder::getElementXpathByName('input', $formElement['field']); @@ -111,7 +106,7 @@ public function fillInAndSubmitForm($data) * * @param string $text The text of the element */ - public function clickOnElementWithText($text) + public function clickOnElementWithText(string $text): void { $elementXpath = $this->getXPathSelectors()[$text]; $this->waitForSelectorPresent('xpath', $elementXpath); @@ -121,7 +116,7 @@ public function clickOnElementWithText($text) /** * Returns to the previous page when the database was already imported */ - public function returnToPreviousDbPage() + public function returnToPreviousDbPage(): void { $forwardButton = $this->find('xpath', $this->getXPathSelectors()['backwardDbButton']); $forwardButton->click(); @@ -132,7 +127,7 @@ public function returnToPreviousDbPage() * * @param string $value The label of the option */ - public function tickRadioButtonOption($value) + public function tickRadioButtonOption(string $value): void { $css = $this->getCssSelectors(); @@ -146,9 +141,9 @@ public function tickRadioButtonOption($value) * @param string $selector Defines which selector should be used * @param string $locator Indicates which field would be checked * - * @throws \Exception + * @throws Exception */ - public function checkIfDisabled($selector, $locator) + public function checkIfDisabled(string $selector, string $locator): void { $css = $this->getCssSelectors(); @@ -156,7 +151,7 @@ public function checkIfDisabled($selector, $locator) $element->hasAttribute('disabled'); if ($element->hasAttribute('disabled')) { - throw new \Exception('License agreement field should be enabled in this case, but is not.'); + throw new Exception('License agreement field should be enabled in this case, but is not.'); } } @@ -166,7 +161,7 @@ public function checkIfDisabled($selector, $locator) * @param string $type Frontend or Backend of the shop * @param string $target Actual target of the link **/ - public function checkIfShopIsAvailable($type, $target) + public function checkIfShopIsAvailable(string $type, string $target): void { $shopLink = $this->find('xpath', $this->getXPathSelectors()[$type]); @@ -179,7 +174,7 @@ public function checkIfShopIsAvailable($type, $target) * * @param string $text Text of the element used for skipping **/ - public function clickOnElementToSkip($text) + public function clickOnElementToSkip(string $text): void { $this->find('named', ['link', $text])->click(); } diff --git a/tests/Page/Updater/UpdaterIndex.php b/tests/Page/Updater/UpdaterIndex.php index 022d7ea..11a3b89 100644 --- a/tests/Page/Updater/UpdaterIndex.php +++ b/tests/Page/Updater/UpdaterIndex.php @@ -14,9 +14,6 @@ class UpdaterIndex extends ContextAwarePage */ protected $path = '/recovery/update/'; - /** - * {@inheritdoc} - */ public function getXPathSelectors(): array { return [ @@ -30,9 +27,6 @@ public function getXPathSelectors(): array ]; } - /** - * {@inheritdoc} - */ public function getCssSelectors(): array { return [ diff --git a/tests/behat b/tests/behat index 8906f8b..2d9e852 100755 --- a/tests/behat +++ b/tests/behat @@ -1,4 +1,4 @@ #!/bin/sh set -eu -"$(pwd)"/vendor/bin/behat "$@" +"$(pwd)"/vendor/bin/behat "$@" --stop-on-failure diff --git a/tests/phpstan-baseline.neon b/tests/phpstan-baseline.neon index a660b8f..7dc69cc 100644 --- a/tests/phpstan-baseline.neon +++ b/tests/phpstan-baseline.neon @@ -5,16 +5,6 @@ parameters: count: 1 path: ../www/assetgenerator/classes/RandomImageGenerator.php - - - message: "#^Access to an undefined property Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:\\$client\\.$#" - count: 2 - path: Component/Api/ApiClient.php - - - - message: "#^Call to sprintf contains 1 placeholder, 2 values given\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:buildArticleDataArray\\(\\) has parameter \\$categories with no value type specified in iterable type array\\.$#" count: 1 @@ -60,11 +50,6 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:call\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:call\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 @@ -76,12 +61,12 @@ parameters: path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:call\\(\\) has parameter \\$url with no type specified\\.$#" + message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:call\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createArticle\\(\\) has parameter \\$product with no type specified\\.$#" + message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createArticle\\(\\) has parameter \\$product with no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php @@ -90,11 +75,6 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createCategoryTree\\(\\) has parameter \\$categories with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createCategoryTrees\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 @@ -106,17 +86,7 @@ parameters: path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createCustomerGroup\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createCustomerGroup\\(\\) has parameter \\$customerGroup with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createOrder\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createCustomerGroup\\(\\) has parameter \\$customerGroup with no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php @@ -125,11 +95,6 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createProperty\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:createProperty\\(\\) has parameter \\$property with no value type specified in iterable type array\\.$#" count: 1 @@ -145,31 +110,11 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:delete\\(\\) has parameter \\$url with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:delete\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:deleteAllCustomers\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:deleteCustomerByEmail\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:deleteCustomerById\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:get\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#" count: 1 @@ -190,28 +135,13 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:post\\(\\) has parameter \\$url with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:post\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:prepareResponse\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:prepareResponse\\(\\) has parameter \\$httpCode with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:prepareResponse\\(\\) has parameter \\$result with no type specified\\.$#" + message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:prepareResponse\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php @@ -225,31 +155,16 @@ parameters: count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:put\\(\\) has parameter \\$url with no type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:put\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:setCountryData\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:setCountryData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:throwExceptionWhenEmpty\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:throwExceptionWhenEmpty\\(\\) has parameter \\$array with no value type specified in iterable type array\\.$#" count: 1 @@ -261,12 +176,7 @@ parameters: path: Component/Api/ApiClient.php - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:updateCustomerGroup\\(\\) has no return type specified\\.$#" - count: 1 - path: Component/Api/ApiClient.php - - - - message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:updateCustomerGroup\\(\\) has parameter \\$customerGroup with no type specified\\.$#" + message: "#^Method Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:updateCustomerGroup\\(\\) has parameter \\$customerGroup with no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php @@ -276,15 +186,10 @@ parameters: path: Component/Api/ApiClient.php - - message: "#^Property Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:\\$validMethods has no type specified\\.$#" + message: "#^Property Shopware\\\\Component\\\\Api\\\\ApiClient\\:\\:\\$validMethods type has no value type specified in iterable type array\\.$#" count: 1 path: Component/Api/ApiClient.php - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 2 - path: Component/XpathBuilder/BackendXpathBuilder.php - - message: "#^Method Shopware\\\\Component\\\\XpathBuilder\\\\BaseXpathBuilder\\:\\:ancestor\\(\\) has parameter \\$conditions with no value type specified in iterable type array\\.$#" count: 1 @@ -325,31 +230,6 @@ parameters: count: 1 path: Component/XpathBuilder/BaseXpathBuilder.php - - - message: "#^Method Shopware\\\\Context\\\\FileCheckContext\\:\\:aRequirementShouldOwnAsStatus\\(\\) has parameter \\$icon with no type specified\\.$#" - count: 1 - path: Context/FileCheckContext.php - - - - message: "#^Method Shopware\\\\Context\\\\FileCheckContext\\:\\:aRequirementShouldOwnAsStatus\\(\\) has parameter \\$requirement with no type specified\\.$#" - count: 1 - path: Context/FileCheckContext.php - - - - message: "#^Method Shopware\\\\Context\\\\FileCheckContext\\:\\:iCorrectTheRequirement\\(\\) has parameter \\$requirement with no type specified\\.$#" - count: 1 - path: Context/FileCheckContext.php - - - - message: "#^Property Shopware\\\\Context\\\\FileCheckContext\\:\\:\\$testPath has no type specified\\.$#" - count: 1 - path: Context/FileCheckContext.php - - - - message: "#^Parameter \\#1 \\$position of method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:removeCartPositionAtIndex\\(\\) expects int, string given\\.$#" - count: 1 - path: Context/FrontendCheckoutContext.php - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 2 @@ -360,56 +240,11 @@ parameters: count: 1 path: Context/FrontendContext.php - - - message: "#^Method Shopware\\\\Context\\\\FrontendDetailContext\\:\\:iChooseTheVariantWithTheNumber\\(\\) has parameter \\$optionNumber with no type specified\\.$#" - count: 1 - path: Context/FrontendDetailContext.php - - - - message: "#^Method Shopware\\\\Context\\\\GeneralContext\\:\\:iScrollDown\\(\\) has parameter \\$pixels with no type specified\\.$#" - count: 1 - path: Context/GeneralContext.php - - - - message: "#^Method Shopware\\\\Context\\\\GeneralContext\\:\\:iWaitForSeconds\\(\\) has parameter \\$amount with no type specified\\.$#" - count: 1 - path: Context/GeneralContext.php - - - - message: "#^Method Shopware\\\\Context\\\\InstallerContext\\:\\:iShouldSeeAfterImportIsFinished\\(\\) has parameter \\$text with no type specified\\.$#" - count: 1 - path: Context/InstallerContext.php - - - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:getMinkParameter\\(\\) has no return type specified\\.$#" - count: 1 - path: Context/SubContext.php - - - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:setMink\\(\\) has no return type specified\\.$#" - count: 1 - path: Context/SubContext.php - - - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:setMinkParameters\\(\\) has no return type specified\\.$#" - count: 1 - path: Context/SubContext.php - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:setMinkParameters\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#" count: 1 path: Context/SubContext.php - - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:slugify\\(\\) has parameter \\$separator with no type specified\\.$#" - count: 1 - path: Context/SubContext.php - - - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:slugify\\(\\) has parameter \\$text with no type specified\\.$#" - count: 1 - path: Context/SubContext.php - - message: "#^Method Shopware\\\\Context\\\\SubContext\\:\\:waitForSelectorPresent\\(\\) should return Behat\\\\Mink\\\\Element\\\\NodeElement but returns Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 1 @@ -420,16 +255,6 @@ parameters: count: 1 path: Context/SubContext.php - - - message: "#^Method Shopware\\\\Context\\\\SubshopContext\\:\\:iAmInSubshopWithURL\\(\\) has parameter \\$url with no type specified\\.$#" - count: 1 - path: Context/SubshopContext.php - - - - message: "#^Method Shopware\\\\Context\\\\SubshopContext\\:\\:iFillTheConfigurationForm\\(\\) has parameter \\$formname with no type specified\\.$#" - count: 1 - path: Context/SubshopContext.php - - message: "#^Negated boolean expression is always true\\.$#" count: 1 @@ -440,36 +265,11 @@ parameters: count: 1 path: Element/Backend/ExtJsElement.php - - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\Form\\\\Checkbox\\:\\:toggle\\(\\) has no return type specified\\.$#" - count: 1 - path: Element/Backend/Form/Checkbox.php - - - - message: "#^Cannot call method isVisible\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" - count: 1 - path: Element/Backend/Form/Combobox.php - - - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\Form\\\\Combobox\\:\\:getComboboxPebble\\(\\) should return Behat\\\\Mink\\\\Element\\\\NodeElement but returns Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" - count: 1 - path: Element/Backend/Form/Combobox.php - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\Form\\\\Combobox\\:\\:setValue\\(\\) has parameter \\$value with no value type specified in iterable type array\\.$#" count: 1 path: Element/Backend/Form/Combobox.php - - - message: "#^Parameter \\#1 \\$id of method Shopware\\\\Element\\\\Backend\\\\Form\\\\Combobox\\:\\:getYCoordinateForElement\\(\\) expects string, string\\|null given\\.$#" - count: 4 - path: Element/Backend/Form/Combobox.php - - - - message: "#^Parameter \\#1 \\$value of method Shopware\\\\Element\\\\Backend\\\\Form\\\\Combobox\\:\\:getOptionByValue\\(\\) expects string, array\\|bool\\|string given\\.$#" - count: 1 - path: Element/Backend/Form/Combobox.php - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 1 @@ -480,11 +280,6 @@ parameters: count: 1 path: Element/Backend/Form/Selecttree.php - - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\Form\\\\Selecttree\\:\\:getDropdownFromWindow\\(\\) has parameter \\$dropdownXpath with no type specified\\.$#" - count: 1 - path: Element/Backend/Form/Selecttree.php - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\Form\\\\Selecttree\\:\\:getSelectTreeElementXpaths\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 @@ -495,11 +290,6 @@ parameters: count: 1 path: Element/Backend/Form/Selecttree.php - - - message: "#^Parameter \\#1 \\$selectString of method Shopware\\\\Element\\\\Backend\\\\Form\\\\Selecttree\\:\\:getSelectTreeElementXpaths\\(\\) expects string, array\\|bool\\|string given\\.$#" - count: 1 - path: Element/Backend/Form/Selecttree.php - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 2 @@ -515,116 +305,36 @@ parameters: count: 1 path: Element/Backend/GridView/GridViewRow.php - - - message: "#^Method Shopware\\\\Element\\\\Backend\\\\GridView\\\\GridViewRow\\:\\:clickActionIcon\\(\\) has no return type specified\\.$#" - count: 1 - path: Element/Backend/GridView/GridViewRow.php - - - - message: "#^Parameter \\#1 \\$containsText of method Shopware\\\\Element\\\\Backend\\\\Window\\:\\:getGridViewXpath\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: Element/Backend/Window.php - - message: "#^Method Shopware\\\\Element\\\\Frontend\\\\Checkout\\\\CartPosition\\:\\:fromArray\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Element/Frontend/Checkout/CartPosition.php - - - message: "#^Method Shopware\\\\Element\\\\Frontend\\\\Checkout\\\\CartPosition\\:\\:toFloat\\(\\) has parameter \\$string with no type specified\\.$#" - count: 1 - path: Element/Frontend/Checkout/CartPosition.php - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 1 path: Page/Backend/CustomerModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:clickDeleteIconForCustomer\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:clickDeleteIconForCustomer\\(\\) has parameter \\$firstname with no type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillCustomerForm\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillCustomerForm\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/CustomerModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillEditCustomerFormWith\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillEditCustomerFormWith\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/CustomerModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillNewCustomerFormWith\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillNewCustomerFormWith\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/CustomerModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:fillPaymentCombobox\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:openEditFormForCustomer\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:openEditFormForCustomer\\(\\) has parameter \\$firstname with no type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\CustomerModule\\:\\:skipIntroWizardIfNecessary\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/CustomerModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\NewArticleModule\\:\\:addCategory\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/NewArticleModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\NewArticleModule\\:\\:setBasicData\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/NewArticleModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\NewArticleModule\\:\\:setBasicData\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/NewArticleModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\NewArticleModule\\:\\:setDescription\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/NewArticleModule.php - - - - message: "#^Property Shopware\\\\Page\\\\Backend\\\\NewArticleModule\\:\\:\\$priceRowAnchor has no type specified\\.$#" - count: 1 - path: Page/Backend/NewArticleModule.php - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 1 @@ -640,66 +350,16 @@ parameters: count: 1 path: Page/Backend/ProductExportModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:addMinimumPriceFilter\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:blockSupplier\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:clickEditIconForExport\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:fillConfigurationForm\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:fillConfigurationForm\\(\\) has parameter \\$formData with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/ProductExportModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:openExport\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:openExport\\(\\) has parameter \\$exportTitle with no type specified\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ProductExportModule\\:\\:verify\\(\\) has parameter \\$urlParameters with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/ProductExportModule.php - - - message: "#^Parameter \\#1 \\$value of method Behat\\\\Mink\\\\Element\\\\NodeElement\\:\\:setValue\\(\\) expects array\\|bool\\|string, int given\\.$#" - count: 1 - path: Page/Backend/ProductExportModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\SettingsModule\\:\\:clickOnMenuElement\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/SettingsModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\SettingsModule\\:\\:clickOnSettingsMenuElement\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/SettingsModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\SettingsModule\\:\\:fillShopConfigurationForm\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/SettingsModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\SettingsModule\\:\\:fillShopConfigurationForm\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 @@ -710,11 +370,6 @@ parameters: count: 6 path: Page/Backend/ShippingModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:activateCountries\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:activateCountries\\(\\) has parameter \\$countries with no value type specified in iterable type array\\.$#" count: 1 @@ -735,31 +390,11 @@ parameters: count: 1 path: Page/Backend/ShippingModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:clickAddShippingMethodButton\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:createShippingMethodIfNotExists\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:createShippingMethodIfNotExists\\(\\) has parameter \\$shipping with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/ShippingModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:deleteShippingMethod\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:emptyShippingCostConfiguration\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:extractPaymentMethodsToActivate\\(\\) has parameter \\$shipping with no value type specified in iterable type array\\.$#" count: 1 @@ -780,11 +415,6 @@ parameters: count: 1 path: Page/Backend/ShippingModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:fillCell\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/ShippingModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\ShippingModule\\:\\:getShippingCostCell\\(\\) should return Behat\\\\Mink\\\\Element\\\\NodeElement but returns Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" count: 1 @@ -795,41 +425,11 @@ parameters: count: 1 path: Page/Backend/ShippingModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\SystemInfoModule\\:\\:checkRequirements\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/SystemInfoModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:deleteVoucher\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/VoucherModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:deleteVoucher\\(\\) has parameter \\$name with no type specified\\.$#" - count: 1 - path: Page/Backend/VoucherModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:fillVoucherEditorFormWith\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/VoucherModule.php - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:fillVoucherEditorFormWith\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 path: Page/Backend/VoucherModule.php - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:openEditFormForVoucher\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Backend/VoucherModule.php - - - - message: "#^Method Shopware\\\\Page\\\\Backend\\\\VoucherModule\\:\\:openEditFormForVoucher\\(\\) has parameter \\$name with no type specified\\.$#" - count: 1 - path: Page/Backend/VoucherModule.php - - message: "#^Method Shopware\\\\Page\\\\ContextAwarePage\\:\\:has\\(\\) has parameter \\$locator with no value type specified in iterable type array\\.$#" count: 1 @@ -840,21 +440,6 @@ parameters: count: 1 path: Page/Frontend/Account.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Account\\:\\:login\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/Account.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Account\\:\\:logout\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/Account.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Account\\:\\:register\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/Account.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Account\\:\\:register\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 @@ -870,63 +455,23 @@ parameters: count: 5 path: Page/Frontend/CheckoutCart.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:addArticle\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:addVoucher\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:assertCartPositionListsAreEqual\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:checkAggregation\\(\\) has parameter \\$aggregation with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutCart.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:checkPositionCountAndCartSum\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:emptyCart\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:fillCartWithProducts\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:fillCartWithProducts\\(\\) has parameter \\$items with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutCart.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:getCssSelectors\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:getCssSelectors\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutCart.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:getXPathSelectors\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:hasCartProductWithQuantity\\(\\) has parameter \\$number with no type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:hasCartProductWithQuantity\\(\\) has parameter \\$quantity with no type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:getXPathSelectors\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutCart.php @@ -940,138 +485,33 @@ parameters: count: 1 path: Page/Frontend/CheckoutCart.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:proceedToOrderConfirmation\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:removeCartPositionAtIndex\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:toFloat\\(\\) has parameter \\$string with no type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:validateCart\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:validateCart\\(\\) has parameter \\$positionData with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutCart.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutCart\\:\\:verifyPage\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutCart.php - - - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" - count: 1 - path: Page/Frontend/CheckoutConfirm.php - - - - message: "#^Cannot call method focus\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" - count: 1 - path: Page/Frontend/CheckoutConfirm.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutConfirm\\:\\:fillOutRegistrationForm\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutConfirm.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutConfirm\\:\\:fillOutRegistrationForm\\(\\) has parameter \\$formData with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutConfirm.php - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutConfirm\\:\\:proceedToCheckout\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutConfirm.php - - - - message: "#^Cannot call method click\\(\\) on Behat\\\\Mink\\\\Element\\\\NodeElement\\|null\\.$#" - count: 2 - path: Page/Frontend/CheckoutShippingPayment.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:changePaymentMethodTo\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutShippingPayment.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:selectPaymentMethod\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutShippingPayment.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:selectPaymentMethod\\(\\) has parameter \\$paymentMethod with no type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutShippingPayment.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:selectShippingMethod\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutShippingPayment.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:selectShippingMethod\\(\\) has parameter \\$shippingMethod with no type specified\\.$#" - count: 1 - path: Page/Frontend/CheckoutShippingPayment.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\CheckoutShippingPayment\\:\\:verifyUrl\\(\\) has parameter \\$urlParameters with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/CheckoutShippingPayment.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:checkBasePrice\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:checkBasePrice\\(\\) has parameter \\$entry with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/Detail.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:checkGraduatedPrice\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:checkGraduatedPrice\\(\\) has parameter \\$graduatedPrice with no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/Detail.php - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:toBasket\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/Detail.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Detail\\:\\:waitForOverlayToDisappear\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Frontend/Detail.php - - - - message: "#^Offset 'amount' does not exist on string\\.$#" - count: 1 - path: Page/Frontend/Detail.php - - - - message: "#^Offset 'data' does not exist on string\\.$#" - count: 2 - path: Page/Frontend/Detail.php - - - - message: "#^Offset 'information' does not exist on string\\.$#" - count: 1 - path: Page/Frontend/Detail.php - - - - message: "#^Offset 'price' does not exist on string\\.$#" - count: 1 - path: Page/Frontend/Detail.php - - - - message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Index\\:\\:getXPathSelectors\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Frontend\\\\Index\\:\\:getXPathSelectors\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Page/Frontend/Index.php @@ -1081,37 +521,7 @@ parameters: path: Page/Frontend/Search.php - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:advance\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:checkIfDisabled\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:checkIfShopIsAvailable\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:checkRequiredFields\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:clickOnElementToSkip\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:clickOnElementWithText\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:fillInAndSubmitForm\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:checkRequiredFields\\(\\) has parameter \\$field with no value type specified in iterable type array\\.$#" count: 1 path: Page/Installer/InstallerIndex.php @@ -1121,32 +531,12 @@ parameters: path: Page/Installer/InstallerIndex.php - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:getCssSelectors\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:getXPathSelectors\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:returnToPreviousDbPage\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:tickCheckbox\\(\\) has no return type specified\\.$#" - count: 1 - path: Page/Installer/InstallerIndex.php - - - - message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:tickRadioButtonOption\\(\\) has no return type specified\\.$#" + message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:getCssSelectors\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Page/Installer/InstallerIndex.php - - message: "#^Offset 'fieldname' does not exist on string\\.$#" + message: "#^Method Shopware\\\\Page\\\\Installer\\\\InstallerIndex\\:\\:getXPathSelectors\\(\\) return type has no value type specified in iterable type array\\.$#" count: 1 path: Page/Installer/InstallerIndex.php diff --git a/tests/phpstan.neon b/tests/phpstan.neon index 96e2fcf..57dc912 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -5,6 +5,11 @@ includes: parameters: level: 8 phpVersion: 70400 + treatPhpDocTypesAsCertain: false + inferPrivatePropertyTypeFromConstructor: true + reportUnmatchedIgnoredErrors: true + checkFunctionNameCase: true + checkInternalClassCaseSensitivity: true paths: - Component - Context