diff --git a/.gitignore b/.gitignore index d6ad9e81c..fad995502 100755 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ dev/tests/mftf.log dev/tests/docs/* dev/tests/_output dev/tests/functional.suite.yml + diff --git a/.travis.yml b/.travis.yml index f807d7415..b4dfd3717 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,17 @@ language: php php: - - 7.1 - - 7.2 - 7.3 + - 7.4 +services: + - docker +before_install: + - docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:3.141.59-zirconium install: composer install --no-interaction --prefer-source env: matrix: - VERIFICATION_TOOL=phpunit-checks - VERIFICATION_TOOL=static-checks + - VERIFICATION_TOOL=functional script: - bin/$VERIFICATION_TOOL after_success: diff --git a/CHANGELOG.md b/CHANGELOG.md index f6ed24d38..5a24b5f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,94 @@ Magento Functional Testing Framework Changelog ================================================ -2.6.3 +3.0.0 +--------- + +### Enhancements + +* Customizability + * Introduced MFTF helpers `` to create custom actions outside of MFTF.[See custom-helpers page for details](./docs/custom-helpers.md) + * Removed deprecated actions `` and ``. + * `` no longer skips a test. Instead, the test is added to the `skip` group. + +* Maintainability + * Added support for PHP 7.4. + * Added support for PHPUnit 9. + * Dropped support for PHP 7.0, 7.1, 7.2. + * Schema updates for test entities to only allow single entity per file except Data and Metadata. + * Support for sub-folders in test modules. + * Removed support to read test entities from `dev/tests/acceptance/tests/functional/Magento/FunctionalTest`. + * Removed file attribute for `` in suiteSchema. + * Removed action `pauseExecution` and added `pause`. [See actions page for details](./docs/test/actions.md#pause) + * Removed action `formatMoney` and added `formatCurrency`. [See actions page for details](./docs/test/actions.md#formatcurrency) + * Improved assertion actions to support PHPUnit 9 changes. [See assertions page for details](./docs/test/assertions.md) + * Added new actions: `assertEqualsWithDelta`, `assertNotEqualsWithDelta`, `assertEqualsCanonicalizing`, `assertNotEqualsCanonicalizing`, `assertEqualsIgnoringCase`, `assertNotEqualsIgnoringCase`. + * Added new actions: `assertStringContainsString`, `assertStringNotContainsString`, `assertStringContainsStringIgnoringCase`, `assertStringNotContainsStringIgnoringCase` for string haystacks. + * Removed actions: `assertInternalType`, `assertNotInternalType`, `assertArraySubset`. + * Removed delta option from `assertEquals` and `assertNotEquals`. + * Added static check `deprecatedEntityUsage` that checks and reports references to deprecated test entities. + * Added static check `annotations` that checks and reports missing annotations in tests. + * Updated `bin/mftf static-checks` command to allow executing static-checks defined in `staticRuleSet.json` by default. [See command page for details](./docs/commands/mftf.md#static-checks) + * Added support for Two-Factor Authentication (2FA). [See configure-2fa page for details](./docs/configure-2fa.md) + * Added new upgrade script to remove unused arguments from action groups. + * `mftf.log` no longer includes notices and warnings at test execution time. + * Added unhandledPromptBehavior driver capability for Chrome 75+ support. + * Added the Chrome option `--ignore-certificate-errors` to `functional.suite.dist.yml`. + +* Traceability + * Removed `--debug` option `NONE` to disallow ability to turn off schema validation. + * Notices added for test entity naming convention violations. + * Metadata file names changed to `*Meta.xml`. + * Introduced new `.env` configuration `VERBOSE_ARTIFACTS` to toggle saving attachments in Allure. [See configuration page for details](./docs/configuration.md) + * Changed the `bin/mftf static-checks` error file directory from the current working directory to `TESTS_BP/tests/_output/static-results/`. + +* Readability + * Support only nested assertion syntax [See assertions page for details](./docs/test/assertions.md). + * Documented [3.0.0 Backward Incompatible Changes](./docs/backward-incompatible-changes.md). + * Removed blacklist/whitelist terminology in MFTF. + +* Upgrade scripts added to upgrade tests to MFTF major version requirements. See upgrade instructions below. +* Bumped dependencies to support PHP/PHPUnit upgrade. + +### Upgrade Instructions + +* Run `bin/mftf reset --hard` to remove old generated configurations. +* Run `bin/mftf build:project` to generate new configurations. +* Run `bin/mftf upgrade:tests`. [See command page for details](./docs/commands/mftf.md#upgradetests). +* After running the above command, some tests may need manually updates: + * Remove all occurrences of `` and ``. + * Remove all occurrences of `` from any ``s. + * Ensure all `` actions in your tests have a valid schema. +* Lastly, try to generate all tests. Tests should all be generated as a result of the upgrades. + * If not, the most likely issue will be a changed XML schema. Check error messaging and search your codebase for the attributes listed. + +### Fixes + +* Throw exception during generation when leaving out .url for `amOnPage`. +* `request_timeout` and `connection_timeout` added to functional.suite.yml.dist. +* Fixed `ModuleResolver` to resolve test modules moved out of deprecated path. +* Fixed issue of resolving arguments of type `entity` in action groups within a custom helper. +* Fixed reporting issue in output file for `testDependencies` static check. +* Fixed a bug in `actionGroupArguments` static check when action group filename is missing `ActionGroup`. +* Fixed issue of running suites under root `_suite` directory in Standalone MFTF. +* Fixed issue with custom helper usage in suites. +* Fixed issue with decryption of secrets during data entity creation. +* Fixed issue with merging of `array` items in data entity. +* Fixed issue where an extended data entity would not merge array items. Array items should merge properly now. +* Fixed issue where Chrome remains running after MFTF suite finishes. +* Fixed javascript error seen on Chrome 83 for dragAndDrop action. +* Fixed allure issue when `WebDriverCurlException` is encountered in `afterStep`. + +### GitHub Issues/Pull Requests + +* [#567](https://github.com/magento/magento2-functional-testing-framework/pull/567) -- log attachments for failed requests. + +### Demo Video links + +* [MFTF 3.0.0 RC1](https://www.youtube.com/watch?v=z0ZaZCmnw-A&t=2s) +* [MFTF 3.0.0 RC2](https://www.youtube.com/watch?v=BJOQAw6dX5o) +* [MFTF 3.0.0 RC3](https://www.youtube.com/watch?v=scLb7pi8pR0) + +2.6.4 ----- ### Fixes @@ -70,9 +158,9 @@ Magento Functional Testing Framework Changelog * Command verifies and troubleshoots some configuration steps required for running tests * Please see DevDocs for more details * `<*Data>` actions now contain `API Endpoint` and `Request Header` artifacts. - * Introduced new `.env` configurations `ENABLE_BROWSER_LOG` and `BROWSER_LOG_BLACKLIST` + * Introduced new `.env` configurations `ENABLE_BROWSER_LOG` and `BROWSER_LOG_BLOCKLIST` * Configuration enables allure artifacts for browser log entries if they are present after the step. - * Blacklist filters out logs from specific sources. + * Blocklist filters out logs from specific sources. * Customizability * Introduced `timeout=""` to `magentoCLI` actions. diff --git a/bin/blacklist.txt b/bin/blocklist.txt similarity index 96% rename from bin/blacklist.txt rename to bin/blocklist.txt index 39b3a6700..6d9f6f4e2 100644 --- a/bin/blacklist.txt +++ b/bin/blocklist.txt @@ -3,7 +3,7 @@ # # # THIS FILE CANNOT CONTAIN BLANK LINES # ################################################################### -bin/blacklist.txt +bin/blocklist.txt dev/tests/static/Magento/Sniffs/Commenting/FunctionCommentSniff.php dev/tests/static/Magento/Sniffs/Commenting/VariableCommentSniff.php dev/tests/verification/_generated diff --git a/bin/copyright-check b/bin/copyright-check index 79fe8df06..dc9976d77 100755 --- a/bin/copyright-check +++ b/bin/copyright-check @@ -5,13 +5,13 @@ FILE_EXTENSIONS='.php\|.xml\|.xsd' -BLACKLIST='bin/blacklist.txt' +BLOCKLIST='bin/blocklist.txt' RESULT='' # Iterate through the list of tracked files # that have the expected extensions # that are not ignored -for i in `git ls-tree --full-tree -r --name-only HEAD | grep $FILE_EXTENSIONS | grep -v -f $BLACKLIST` +for i in `git ls-tree --full-tree -r --name-only HEAD | grep $FILE_EXTENSIONS | grep -v -f $BLOCKLIST` do if echo `cat $i` | grep -q -v "Copyright © Magento, Inc. All rights reserved."; then # Copyright is missing diff --git a/bin/copyright-check.bat b/bin/copyright-check.bat index 9f2e23bfb..0a7612f77 100644 --- a/bin/copyright-check.bat +++ b/bin/copyright-check.bat @@ -3,7 +3,7 @@ @echo off SETLOCAL EnableDelayedExpansion -SET BLACKLIST_FILE=bin/blacklist.txt +SET BLOCKLIST_FILE=bin/blocklist.txt SET i=0 FOR /F %%x IN ('git ls-tree --full-tree -r --name-only HEAD') DO ( @@ -12,14 +12,14 @@ FOR /F %%x IN ('git ls-tree --full-tree -r --name-only HEAD') DO ( if "%%~xx"==".xml" set GOOD_EXT=1 if "%%~xx"==".xsd" set GOOD_EXT=1 IF DEFINED GOOD_EXT ( - SET BLACKLISTED= - FOR /F "tokens=* skip=5" %%f IN (%BLACKLIST_FILE%) DO ( + SET BLOCKLISTED= + FOR /F "tokens=* skip=5" %%f IN (%BLOCKLIST_FILE%) DO ( SET LINE=%%x IF NOT "!LINE!"=="!LINE:%%f=!" ( - SET BLACKLISTED=1 + SET BLOCKLISTED=1 ) ) - IF NOT DEFINED BLACKLISTED ( + IF NOT DEFINED BLOCKLISTED ( FIND "Copyright © Magento, Inc. All rights reserved." %%x >nul IF ERRORLEVEL 1 ( SET /A i+=1 diff --git a/bin/functional b/bin/functional new file mode 100755 index 000000000..97501e018 --- /dev/null +++ b/bin/functional @@ -0,0 +1,11 @@ +# Copyright © Magento, Inc. All rights reserved. +# See COPYING.txt for license details. + +set -e + +echo "===============================" +echo " EXECUTE Functional Tests " +echo "===============================" +bin/mftf build:project +bin/mftf run:test DevDocsTest -f +bin/mftf run:test FormatCurrencyTest -f \ No newline at end of file diff --git a/composer.json b/composer.json index 3b517567d..e1a04296f 100755 --- a/composer.json +++ b/composer.json @@ -2,53 +2,54 @@ "name": "magento/magento2-functional-testing-framework", "description": "Magento2 Functional Testing Framework", "type": "library", - "version": "2.6.4", + "version": "3.0.0", "license": "AGPL-3.0", "keywords": ["magento", "automation", "functional", "testing"], "config": { "sort-packages": true }, "require": { - "php": "~7.1.0||~7.2.0||~7.3.0", + "php": "^7.3", "ext-curl": "*", "ext-dom": "*", + "ext-intl": "*", "ext-json": "*", "ext-openssl": "*", - "allure-framework/allure-codeception": "~1.3.0", + "allure-framework/allure-codeception": "~1.4.0", "aws/aws-sdk-php": "^3.132", - "codeception/codeception": "~2.4.5", - "composer/composer": "^1.6", + "codeception/codeception": "~4.1.4", + "codeception/module-asserts": "^1.1", + "codeception/module-sequence": "^1.0", + "codeception/module-webdriver": "^1.0", + "composer/composer": "^1.9", "csharpru/vault-php": "~3.5.3", "csharpru/vault-php-guzzle6-transport": "^2.0", - "flow/jsonpath": ">0.2", - "fzaninotto/faker": "^1.6", - "monolog/monolog": "^1.0", + "monolog/monolog": "^1.17", "mustache/mustache": "~2.5", "php-webdriver/webdriver": "^1.8.0", + "spomky-labs/otphp": "^10.0", "symfony/console": "^4.4", - "symfony/finder": "^4.4", - "symfony/http-foundation": "^4.4", - "symfony/mime": "^4.4", + "symfony/finder": "^5.0", + "symfony/http-foundation": "^5.0", + "symfony/mime": "^5.0", "symfony/process": "^4.4", - "vlucas/phpdotenv": "^2.4" + "vlucas/phpdotenv": "^2.4", + "weew/helpers-array": "^1.3" }, "require-dev": { - "squizlabs/php_codesniffer": "~3.2", - "sebastian/phpcpd": "~3.0 || ~4.0", "brainmaestro/composer-git-hooks": "^2.3.1", - "doctrine/cache": "<1.7.0", - "codeception/aspect-mock": "^3.0", - "goaop/framework": "2.2.0", "codacy/coverage": "^1.4", - "phpmd/phpmd": "^2.6.0", - "phpunit/phpunit": "~6.5.0 || ~7.0.0", - "rregeer/phpunit-coverage-check": "^0.1.4", + "codeception/aspect-mock": "^3.0", + "doctrine/cache": "<1.7.0", + "goaop/framework": "~2.3.4", "php-coveralls/php-coveralls": "^1.0", + "phpmd/phpmd": "^2.8.0", + "phpunit/phpunit": "^9.0", + "rregeer/phpunit-coverage-check": "^0.1.4", + "sebastian/phpcpd": "~5.0.0", + "squizlabs/php_codesniffer": "~3.5.4", "symfony/stopwatch": "~3.4.6" }, - "suggest": { - "epfremme/swagger-php": "^2.0" - }, "replace": { "facebook/webdriver": "^1.7.1" }, diff --git a/composer.lock b/composer.lock index 7eb7a0d88..dff4f1006 100644 --- a/composer.lock +++ b/composer.lock @@ -4,26 +4,26 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "551059dcd56ad85b0ff76545e0ec6834", + "content-hash": "a0516f6072ced659bf4ed7a486756bb2", "packages": [ { "name": "allure-framework/allure-codeception", - "version": "1.3.0", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/allure-framework/allure-codeception.git", - "reference": "9d31d781b3622b028f1f6210bc76ba88438bd518" + "reference": "9e0e25f8960fa5ac17c65c932ea8153ce6700713" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/allure-framework/allure-codeception/zipball/9d31d781b3622b028f1f6210bc76ba88438bd518", - "reference": "9d31d781b3622b028f1f6210bc76ba88438bd518", + "url": "https://api.github.com/repos/allure-framework/allure-codeception/zipball/9e0e25f8960fa5ac17c65c932ea8153ce6700713", + "reference": "9e0e25f8960fa5ac17c65c932ea8153ce6700713", "shasum": "" }, "require": { - "allure-framework/allure-php-api": "~1.1.0", - "codeception/codeception": "~2.1", - "php": ">=5.4.0", + "allure-framework/allure-php-api": "~1.1.8", + "codeception/codeception": "^2.3|^3.0|^4.0", + "php": ">=5.6", "symfony/filesystem": ">=2.6", "symfony/finder": ">=2.6" }, @@ -55,7 +55,7 @@ "steps", "testing" ], - "time": "2018-12-18T19:47:23+00:00" + "time": "2020-03-13T11:07:13+00:00" }, { "name": "allure-framework/allure-php-api", @@ -112,16 +112,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.133.46", + "version": "3.135.3", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "98d359e61b365f3040ca61c66ae8883334cf5d74" + "reference": "0f6f6e8f4a44193908e18b8c7b8530b02f5bc428" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/98d359e61b365f3040ca61c66ae8883334cf5d74", - "reference": "98d359e61b365f3040ca61c66ae8883334cf5d74", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0f6f6e8f4a44193908e18b8c7b8530b02f5bc428", + "reference": "0f6f6e8f4a44193908e18b8c7b8530b02f5bc428", "shasum": "" }, "require": { @@ -192,7 +192,69 @@ "s3", "sdk" ], - "time": "2020-03-27T18:15:32+00:00" + "time": "2020-04-23T18:18:24+00:00" + }, + { + "name": "beberlei/assert", + "version": "v3.2.7", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/d63a6943fc4fd1a2aedb65994e3548715105abcf", + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "php": "^7" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan-shim": "*", + "phpunit/phpunit": ">=6.0.0 <8" + }, + "suggest": { + "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "time": "2019-12-19T17:51:41+00:00" }, { "name": "behat/gherkin", @@ -348,57 +410,51 @@ }, { "name": "codeception/codeception", - "version": "2.4.5", + "version": "4.1.4", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "5fee32d5c82791548931cbc34806b4de6aa1abfc" + "reference": "55d8d1d882fa0777e47de17b04c29b3c50fe29e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/5fee32d5c82791548931cbc34806b4de6aa1abfc", - "reference": "5fee32d5c82791548931cbc34806b4de6aa1abfc", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/55d8d1d882fa0777e47de17b04c29b3c50fe29e7", + "reference": "55d8d1d882fa0777e47de17b04c29b3c50fe29e7", "shasum": "" }, "require": { "behat/gherkin": "^4.4.0", - "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", - "codeception/stub": "^2.0", + "codeception/lib-asserts": "^1.0", + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.1.1 | ^9.0", + "codeception/stub": "^2.0 | ^3.0", + "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "facebook/webdriver": ">=1.1.3 <2.0", - "guzzlehttp/guzzle": ">=4.1.4 <7.0", - "guzzlehttp/psr7": "~1.0", + "guzzlehttp/psr7": "~1.4", "php": ">=5.6.0 <8.0", - "symfony/browser-kit": ">=2.7 <5.0", - "symfony/console": ">=2.7 <5.0", - "symfony/css-selector": ">=2.7 <5.0", - "symfony/dom-crawler": ">=2.7 <5.0", - "symfony/event-dispatcher": ">=2.7 <5.0", - "symfony/finder": ">=2.7 <5.0", - "symfony/yaml": ">=2.7 <5.0" + "symfony/console": ">=2.7 <6.0", + "symfony/css-selector": ">=2.7 <6.0", + "symfony/event-dispatcher": ">=2.7 <6.0", + "symfony/finder": ">=2.7 <6.0", + "symfony/yaml": ">=2.7 <6.0" }, "require-dev": { + "codeception/module-asserts": "*@dev", + "codeception/module-cli": "*@dev", + "codeception/module-db": "*@dev", + "codeception/module-filesystem": "*@dev", + "codeception/module-phpbrowser": "*@dev", "codeception/specify": "~0.3", - "facebook/graph-sdk": "~5.3", - "flow/jsonpath": "~0.2", + "codeception/util-universalframework": "*@dev", "monolog/monolog": "~1.8", - "pda/pheanstalk": "~3.0", - "php-amqplib/php-amqplib": "~2.4", - "predis/predis": "^1.0", "squizlabs/php_codesniffer": "~2.0", - "symfony/process": ">=2.7 <5.0", - "vlucas/phpdotenv": "^2.4.0" + "symfony/process": ">=2.7 <6.0", + "vlucas/phpdotenv": "^2.0 | ^3.0 | ^4.0" }, "suggest": { - "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", - "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", "codeception/specify": "BDD-style code blocks", "codeception/verify": "BDD-style assertions", - "flow/jsonpath": "For using JSONPath in REST module", - "league/factory-muffin": "For DataFactory module", - "league/factory-muffin-faker": "For Faker support in DataFactory module", - "phpseclib/phpseclib": "for SFTP option in FTP Module", + "hoa/console": "For interactive console functionality", "stecman/symfony-console-completion": "For BASH autocompletion", "symfony/phpunit-bridge": "For phpunit-bridge support" }, @@ -411,7 +467,7 @@ }, "autoload": { "psr-4": { - "Codeception\\": "src\\Codeception", + "Codeception\\": "src/Codeception", "Codeception\\Extension\\": "ext" } }, @@ -435,36 +491,229 @@ "functional testing", "unit testing" ], - "time": "2018-08-01T07:21:49+00:00" + "time": "2020-03-23T17:07:20+00:00" + }, + { + "name": "codeception/lib-asserts", + "version": "1.12.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/lib-asserts.git", + "reference": "acd0dc8b394595a74b58dcc889f72569ff7d8e71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/acd0dc8b394595a74b58dcc889f72569ff7d8e71", + "reference": "acd0dc8b394595a74b58dcc889f72569ff7d8e71", + "shasum": "" + }, + "require": { + "codeception/phpunit-wrapper": ">6.0.15 <6.1.0 | ^6.6.1 | ^7.7.1 | ^8.0.3 | ^9.0", + "php": ">=5.6.0 <8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Assertion methods used by Codeception core and Asserts module", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception" + ], + "time": "2020-04-17T18:20:46+00:00" + }, + { + "name": "codeception/module-asserts", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-asserts.git", + "reference": "79f13d05b63f2fceba4d0e78044bab668c9b2a6b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-asserts/zipball/79f13d05b63f2fceba4d0e78044bab668c9b2a6b", + "reference": "79f13d05b63f2fceba4d0e78044bab668c9b2a6b", + "shasum": "" + }, + "require": { + "codeception/codeception": "*@dev", + "codeception/lib-asserts": "^1.12.0", + "php": ">=5.6.0 <8.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "require-dev": { + "codeception/util-robohelpers": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "description": "Codeception module containing various assertions", + "homepage": "http://codeception.com/", + "keywords": [ + "assertions", + "asserts", + "codeception" + ], + "time": "2020-04-20T07:26:11+00:00" + }, + { + "name": "codeception/module-sequence", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-sequence.git", + "reference": "70563527b768194d6ab22e1ff943a5e69741c5dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-sequence/zipball/70563527b768194d6ab22e1ff943a5e69741c5dd", + "reference": "70563527b768194d6ab22e1ff943a5e69741c5dd", + "shasum": "" + }, + "require": { + "codeception/codeception": "4.0.x-dev | ^4.0", + "php": ">=5.6.0 <8.0" + }, + "require-dev": { + "codeception/util-robohelpers": "dev-master" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + } + ], + "description": "Sequence module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "codeception" + ], + "time": "2019-10-10T12:08:50+00:00" + }, + { + "name": "codeception/module-webdriver", + "version": "1.0.7", + "source": { + "type": "git", + "url": "https://github.com/Codeception/module-webdriver.git", + "reference": "f05c5c25e39d10fbfb2d508779e1537df019ff9b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/module-webdriver/zipball/f05c5c25e39d10fbfb2d508779e1537df019ff9b", + "reference": "f05c5c25e39d10fbfb2d508779e1537df019ff9b", + "shasum": "" + }, + "require": { + "codeception/codeception": "^4.0", + "php": ">=5.6.0 <8.0", + "php-webdriver/webdriver": "^1.6.0" + }, + "require-dev": { + "codeception/util-robohelpers": "dev-master" + }, + "suggest": { + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Zaahid Bateson" + } + ], + "description": "WebDriver module for Codeception", + "homepage": "http://codeception.com/", + "keywords": [ + "acceptance-testing", + "browser-testing", + "codeception" + ], + "time": "2020-04-01T10:18:18+00:00" }, { "name": "codeception/phpunit-wrapper", - "version": "7.0.6", + "version": "9.0.2", "source": { "type": "git", "url": "https://github.com/Codeception/phpunit-wrapper.git", - "reference": "e8528cb777cf5a5ccea1cf57a3522b142625d1b5" + "reference": "eb27243d8edde68593bf8d9ef5e9074734777931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/e8528cb777cf5a5ccea1cf57a3522b142625d1b5", - "reference": "e8528cb777cf5a5ccea1cf57a3522b142625d1b5", + "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/eb27243d8edde68593bf8d9ef5e9074734777931", + "reference": "eb27243d8edde68593bf8d9ef5e9074734777931", "shasum": "" }, "require": { - "phpunit/php-code-coverage": "^6.0", - "phpunit/phpunit": "^7.0", - "sebastian/comparator": "^2.0", - "sebastian/diff": "^3.0" + "php": ">=7.2", + "phpunit/phpunit": "^9.0" }, "require-dev": { "codeception/specify": "*", - "vlucas/phpdotenv": "^2.4" + "vlucas/phpdotenv": "^3.0" }, "type": "library", "autoload": { "psr-4": { - "Codeception\\PHPUnit\\": "src\\" + "Codeception\\PHPUnit\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -475,27 +724,30 @@ { "name": "Davert", "email": "davert.php@resend.cc" + }, + { + "name": "Naktibalda" } ], "description": "PHPUnit classes used by Codeception", - "time": "2018-03-31T18:49:51+00:00" + "time": "2020-04-17T18:16:31+00:00" }, { "name": "codeception/stub", - "version": "2.0.4", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/Codeception/Stub.git", - "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e" + "reference": "a3ba01414cbee76a1bced9f9b6b169cc8d203880" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/f50bc271f392a2836ff80690ce0c058efe1ae03e", - "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/a3ba01414cbee76a1bced9f9b6b169cc8d203880", + "reference": "a3ba01414cbee76a1bced9f9b6b169cc8d203880", "shasum": "" }, "require": { - "phpunit/phpunit": ">=4.8 <8.0" + "phpunit/phpunit": "^8.4 | ^9.0" }, "type": "library", "autoload": { @@ -508,20 +760,20 @@ "MIT" ], "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", - "time": "2018-07-26T11:55:37+00:00" + "time": "2020-02-07T18:42:28+00:00" }, { "name": "composer/ca-bundle", - "version": "1.2.6", + "version": "1.2.7", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e" + "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e", - "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/95c63ab2117a72f48f5a55da9740a3273d45b7fd", + "reference": "95c63ab2117a72f48f5a55da9740a3273d45b7fd", "shasum": "" }, "require": { @@ -564,20 +816,20 @@ "ssl", "tls" ], - "time": "2020-01-13T10:02:55+00:00" + "time": "2020-04-08T08:27:21+00:00" }, { "name": "composer/composer", - "version": "1.10.1", + "version": "1.10.5", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011" + "reference": "7a4d5b6aa30d2118af27c04f5e897b57156ccfa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/b912a45da3e2b22f5cb5a23e441b697a295ba011", - "reference": "b912a45da3e2b22f5cb5a23e441b697a295ba011", + "url": "https://api.github.com/repos/composer/composer/zipball/7a4d5b6aa30d2118af27c04f5e897b57156ccfa9", + "reference": "7a4d5b6aa30d2118af27c04f5e897b57156ccfa9", "shasum": "" }, "require": { @@ -644,7 +896,7 @@ "dependency", "package" ], - "time": "2020-03-13T19:34:27+00:00" + "time": "2020-04-10T09:44:22+00:00" }, { "name": "composer/semver", @@ -899,20 +1151,21 @@ }, { "name": "doctrine/annotations", - "version": "v1.8.0", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" + "reference": "b9d758e831c70751155c698c2f7df4665314a1cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", - "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/b9d758e831c70751155c698c2f7df4665314a1cb", + "reference": "b9d758e831c70751155c698c2f7df4665314a1cb", "shasum": "" }, "require": { "doctrine/lexer": "1.*", + "ext-tokenizer": "*", "php": "^7.1" }, "require-dev": { @@ -922,7 +1175,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.9.x-dev" } }, "autoload": { @@ -963,7 +1216,7 @@ "docblock", "parser" ], - "time": "2019-10-01T18:55:10+00:00" + "time": "2020-04-20T09:18:32+00:00" }, { "name": "doctrine/cache", @@ -1160,28 +1413,30 @@ }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1194,14 +1449,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -1216,118 +1471,28 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" - }, - { - "name": "flow/jsonpath", - "version": "0.5.0", - "source": { - "type": "git", - "url": "https://github.com/FlowCommunications/JSONPath.git", - "reference": "b9738858c75d008c1211612b973e9510f8b7f8ea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FlowCommunications/JSONPath/zipball/b9738858c75d008c1211612b973e9510f8b7f8ea", - "reference": "b9738858c75d008c1211612b973e9510f8b7f8ea", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "peekmo/jsonpath": "dev-master", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Flow\\JSONPath": "src/", - "Flow\\JSONPath\\Test": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stephen Frank", - "email": "stephen@flowsa.com" - } - ], - "description": "JSONPath implementation for parsing, searching and flattening arrays", - "time": "2019-07-15T17:23:22+00:00" - }, - { - "name": "fzaninotto/faker", - "version": "v1.9.1", - "source": { - "type": "git", - "url": "https://github.com/fzaninotto/Faker.git", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/fc10d778e4b84d5bd315dad194661e091d307c6f", - "reference": "fc10d778e4b84d5bd315dad194661e091d307c6f", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0" - }, - "require-dev": { - "ext-intl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7", - "squizlabs/php_codesniffer": "^2.9.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, - "autoload": { - "psr-4": { - "Faker\\": "src/Faker/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "François Zaninotto" - } - ], - "description": "Faker is a PHP library that generates fake data for you.", - "keywords": [ - "data", - "faker", - "fixtures" - ], - "time": "2019-12-12T13:22:17+00:00" + "time": "2019-10-30T14:39:59+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.5.2", + "version": "6.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "43ece0e75098b7ecd8d13918293029e555a50f82" + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", - "reference": "43ece0e75098b7ecd8d13918293029e555a50f82", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e", + "reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/promises": "^1.0", "guzzlehttp/psr7": "^1.6.1", - "php": ">=5.5" + "php": ">=5.5", + "symfony/polyfill-intl-idn": "^1.11" }, "require-dev": { "ext-curl": "*", @@ -1335,7 +1500,6 @@ "psr/log": "^1.1" }, "suggest": { - "ext-intl": "Required for Internationalized Domain Name (IDN) support", "psr/log": "Required for using the Log middleware" }, "type": "library", @@ -1374,7 +1538,7 @@ "rest", "web service" ], - "time": "2019-12-23T11:57:10+00:00" + "time": "2020-04-18T10:38:46+00:00" }, { "name": "guzzlehttp/promises", @@ -1740,16 +1904,16 @@ }, { "name": "league/flysystem", - "version": "1.0.66", + "version": "1.0.67", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21" + "reference": "5b1f36c75c4bdde981294c2a0ebdb437ee6f275e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/021569195e15f8209b1c4bebb78bd66aa4f08c21", - "reference": "021569195e15f8209b1c4bebb78bd66aa4f08c21", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5b1f36c75c4bdde981294c2a0ebdb437ee6f275e", + "reference": "5b1f36c75c4bdde981294c2a0ebdb437ee6f275e", "shasum": "" }, "require": { @@ -1820,7 +1984,7 @@ "sftp", "storage" ], - "time": "2020-03-17T18:58:12+00:00" + "time": "2020-04-16T13:21:26+00:00" }, { "name": "monolog/monolog", @@ -2051,6 +2215,68 @@ ], "time": "2020-01-17T21:11:47+00:00" }, + { + "name": "paragonie/constant_time_encoding", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2", + "reference": "47a1cedd2e4d52688eb8c96469c05ebc8fd28fa2", + "shasum": "" + }, + "require": { + "php": "^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^6|^7", + "vimeo/psalm": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "time": "2019-11-06T19:20:29+00:00" + }, { "name": "paragonie/random_compat", "version": "v9.99.99", @@ -2098,22 +2324,22 @@ }, { "name": "phar-io/manifest", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^1.0.1", + "phar-io/version": "^2.0", "php": "^5.6 || ^7.0" }, "type": "library", @@ -2149,20 +2375,20 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2018-07-08T19:23:20+00:00" }, { "name": "phar-io/version", - "version": "1.0.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", "shasum": "" }, "require": { @@ -2196,7 +2422,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "time": "2018-07-08T19:19:57+00:00" }, { "name": "php-webdriver/webdriver", @@ -2365,41 +2591,38 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.4", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpdocumentor/type-resolver": "0.4.*", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2410,33 +2633,36 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-12-28T18:55:12+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.2", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" + "ext-tokenizer": "^7.2", + "mockery/mockery": "~1" }, "type": "library", "extra": { @@ -2460,7 +2686,7 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" + "time": "2020-02-18T18:59:58+00:00" }, { "name": "phpoption/phpoption", @@ -2582,40 +2808,41 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.0.5", + "version": "8.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "4cab20a326d14de7575a8e235c70d879b569a57a" + "reference": "31e94ccc084025d6abee0585df533eb3a792b96a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4cab20a326d14de7575a8e235c70d879b569a57a", - "reference": "4cab20a326d14de7575a8e235c70d879b569a57a", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/31e94ccc084025d6abee0585df533eb3a792b96a", + "reference": "31e94ccc084025d6abee0585df533eb3a792b96a", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "php": "^7.3", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-token-stream": "^4.0", + "sebastian/code-unit-reverse-lookup": "^2.0", + "sebastian/environment": "^5.0", + "sebastian/version": "^3.0", + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.0" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.0-dev" + "dev-master": "8.0-dev" } }, "autoload": { @@ -2641,29 +2868,32 @@ "testing", "xunit" ], - "time": "2018-05-28T11:49:20+00:00" + "time": "2020-02-19T13:41:19+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4", + "reference": "4ac5b3e13df14829daa60a2eb4fdd2f2b7d33cf4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2678,7 +2908,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -2688,26 +2918,38 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "time": "2020-04-18T05:02:12+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/7579d5a1ba7f3ac11c80004d205877911315ae7a", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2724,37 +2966,34 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "template" + "process" ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2020-02-07T06:06:11+00:00" }, { - "name": "phpunit/php-timer", - "version": "2.1.2", + "name": "phpunit/php-text-template", + "version": "2.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", - "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/526dc996cc0ebdfa428cd2dfccd79b7b53fee346", + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346", "shasum": "" }, "require": { - "php": "^7.1" - }, - "require-dev": { - "phpunit/phpunit": "^7.0" + "php": "^7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2773,33 +3012,32 @@ "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "timer" + "template" ], - "time": "2019-06-07T04:22:29+00:00" + "time": "2020-02-01T07:43:44+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "3.1.1", + "name": "phpunit/php-timer", + "version": "3.1.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "dc9368fae6ef2ffa57eba80a7410bcef81df6258" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", - "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/dc9368fae6ef2ffa57eba80a7410bcef81df6258", + "reference": "dc9368fae6ef2ffa57eba80a7410bcef81df6258", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.1" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { @@ -2819,69 +3057,42 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "tokenizer" + "timer" ], - "time": "2019-09-17T06:23:10+00:00" + "time": "2020-04-20T06:00:37+00:00" }, { - "name": "phpunit/phpunit", - "version": "7.0.3", + "name": "phpunit/php-token-stream", + "version": "4.0.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "536f4d853c12d8189963435088e8ff7c0daeab2e" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "b2560a0c33f7710e4d7f8780964193e8e8f8effe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/536f4d853c12d8189963435088e8ff7c0daeab2e", - "reference": "536f4d853c12d8189963435088e8ff7c0daeab2e", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/b2560a0c33f7710e4d7f8780964193e8e8f8effe", + "reference": "b2560a0c33f7710e4d7f8780964193e8e8f8effe", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.1", - "phpunit/php-file-iterator": "^1.4.3", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.0", - "phpunit/phpunit-mock-objects": "^6.0", - "sebastian/comparator": "^2.1", - "sebastian/diff": "^3.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" + "ext-tokenizer": "*", + "php": "^7.3" }, "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "phpunit/phpunit": "^9.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "7.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2896,54 +3107,82 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ - "phpunit", - "testing", - "xunit" + "tokenizer" ], - "time": "2018-03-26T07:36:48+00:00" + "time": "2020-02-07T06:19:00+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "6.1.2", + "name": "phpunit/phpunit", + "version": "9.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a74780472172957a65cb5999a597e8c0878cf39c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", - "reference": "f9756fd4f43f014cb2dca98deeaaa8ce5500a36e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a74780472172957a65cb5999a597e8c0878cf39c", + "reference": "a74780472172957a65cb5999a597e8c0878cf39c", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.1", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" + "doctrine/instantiator": "^1.2.0", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.3", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^8.0.1", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-invoker": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-timer": "^3.1.4", + "sebastian/code-unit": "^1.0", + "sebastian/comparator": "^4.0", + "sebastian/diff": "^4.0", + "sebastian/environment": "^5.0.1", + "sebastian/exporter": "^4.0", + "sebastian/global-state": "^4.0", + "sebastian/object-enumerator": "^4.0", + "sebastian/resource-operations": "^3.0", + "sebastian/type": "^2.0", + "sebastian/version": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "ext-pdo": "*", + "phpspec/prophecy-phpunit": "^2.0" }, "suggest": { - "ext-soap": "*" + "ext-soap": "*", + "ext-xdebug": "*" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "9.1-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2957,14 +3196,14 @@ "role": "lead" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", "keywords": [ - "mock", + "phpunit", + "testing", "xunit" ], - "abandoned": true, - "time": "2018-05-29T13:54:20+00:00" + "time": "2020-04-23T04:42:05+00:00" }, { "name": "psr/cache", @@ -3324,39 +3563,85 @@ "email": "thibaud@aztech.io" } ], - "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", - "homepage": "https://github.com/ramsey/uuid", - "keywords": [ - "guid", - "identifier", - "uuid" - ], - "time": "2020-02-21T04:36:14+00:00" + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2020-02-21T04:36:14+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "8d8f09bd47c75159921e6e84fdef146343962866" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/8d8f09bd47c75159921e6e84fdef146343962866", + "reference": "8d8f09bd47c75159921e6e84fdef146343962866", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "time": "2020-03-30T11:59:20+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5b5dbe0044085ac41df47e79d34911a15b96d82e", + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3376,34 +3661,34 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "time": "2020-02-07T06:20:13+00:00" }, { "name": "sebastian/comparator", - "version": "2.1.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85b3435da967696ed618ff745f32be3ff4a2b8e8", + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", - "sebastian/exporter": "^3.1" + "php": "^7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3416,6 +3701,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -3427,10 +3716,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -3440,33 +3725,33 @@ "compare", "equality" ], - "time": "2018-02-01T13:46:46+00:00" + "time": "2020-02-07T06:08:51+00:00" }, { "name": "sebastian/diff", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" + "reference": "c0c26c9188b538bfa985ae10c9f05d278f12060d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", - "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c0c26c9188b538bfa985ae10c9f05d278f12060d", + "reference": "c0c26c9188b538bfa985ae10c9f05d278f12060d", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", - "symfony/process": "^2 || ^3.3 || ^4" + "phpunit/phpunit": "^9.0", + "symfony/process": "^4 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3479,13 +3764,13 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", @@ -3496,32 +3781,35 @@ "unidiff", "unified diff" ], - "time": "2019-02-04T06:01:07+00:00" + "time": "2020-02-07T06:09:38+00:00" }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "c753f04d68cd489b6973cf9b4e505e191af3b05c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/c753f04d68cd489b6973cf9b4e505e191af3b05c", + "reference": "c753f04d68cd489b6973cf9b4e505e191af3b05c", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3546,34 +3834,34 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "time": "2020-04-14T13:36:52+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" + "reference": "80c26562e964016538f832f305b2286e1ec29566" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", - "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/80c26562e964016538f832f305b2286e1ec29566", + "reference": "80c26562e964016538f832f305b2286e1ec29566", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3613,27 +3901,30 @@ "export", "exporter" ], - "time": "2019-09-14T09:02:43+00:00" + "time": "2020-02-07T06:10:52+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bdb1e7c79e592b8c82cb1699be3c8743119b8a72", + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.0" }, "suggest": { "ext-uopz": "*" @@ -3641,7 +3932,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3664,34 +3955,34 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2020-02-07T06:11:37+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "e67516b175550abad905dc952f43285957ef4363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67516b175550abad905dc952f43285957ef4363", + "reference": "e67516b175550abad905dc952f43285957ef4363", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3711,32 +4002,32 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "time": "2020-02-07T06:12:23+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3756,32 +4047,32 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "time": "2020-02-07T06:19:40+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "cdd86616411fc3062368b720b0425de10bd3d579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cdd86616411fc3062368b720b0425de10bd3d579", + "reference": "cdd86616411fc3062368b720b0425de10bd3d579", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3794,14 +4085,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -3809,29 +4100,32 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "time": "2020-02-07T06:18:20+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3851,29 +4145,75 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "time": "2020-02-07T06:13:02+00:00" + }, + { + "name": "sebastian/type", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "9e8f42f740afdea51f5f4e8cec2035580e797ee1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/9e8f42f740afdea51f5f4e8cec2035580e797ee1", + "reference": "9e8f42f740afdea51f5f4e8cec2035580e797ee1", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2020-02-07T06:13:43+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "0411bde656dce64202b39c2f4473993a9081d39e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/0411bde656dce64202b39c2f4473993a9081d39e", + "reference": "0411bde656dce64202b39c2f4473993a9081d39e", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3894,7 +4234,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "time": "2020-01-21T06:36:37+00:00" }, { "name": "seld/jsonlint", @@ -3990,45 +4330,48 @@ "time": "2020-02-14T15:25:33+00:00" }, { - "name": "symfony/browser-kit", - "version": "v4.4.6", + "name": "spomky-labs/otphp", + "version": "v10.0.1", "source": { "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "4e9a171559f5a9018c90ba9e85b4084d4e045186" + "url": "https://github.com/Spomky-Labs/otphp.git", + "reference": "f44cce5a9db4b8da410215d992110482c931232f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/4e9a171559f5a9018c90ba9e85b4084d4e045186", - "reference": "4e9a171559f5a9018c90ba9e85b4084d4e045186", + "url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/f44cce5a9db4b8da410215d992110482c931232f", + "reference": "f44cce5a9db4b8da410215d992110482c931232f", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/dom-crawler": "^3.4|^4.0|^5.0" + "beberlei/assert": "^3.0", + "ext-mbstring": "*", + "paragonie/constant_time_encoding": "^2.0", + "php": "^7.2|^8.0", + "thecodingmachine/safe": "^0.1.14|^1.0" }, "require-dev": { - "symfony/css-selector": "^3.4|^4.0|^5.0", - "symfony/http-client": "^4.3|^5.0", - "symfony/mime": "^4.3|^5.0", - "symfony/process": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/process": "" + "php-coveralls/php-coveralls": "^2.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-beberlei-assert": "^0.12", + "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan-phpunit": "^0.12", + "phpstan/phpstan-strict-rules": "^0.12", + "phpunit/phpunit": "^8.0", + "thecodingmachine/phpstan-safe-rule": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "v10.0": "10.0.x-dev", + "v9.0": "9.0.x-dev", + "v8.3": "8.3.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "OTPHP\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4036,30 +4379,39 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Florent Morselli", + "homepage": "https://github.com/Spomky" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "All contributors", + "homepage": "https://github.com/Spomky-Labs/otphp/contributors" } ], - "description": "Symfony BrowserKit Component", - "homepage": "https://symfony.com", - "time": "2020-03-15T10:05:03+00:00" + "description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", + "homepage": "https://github.com/Spomky-Labs/otphp", + "keywords": [ + "FreeOTP", + "RFC 4226", + "RFC 6238", + "google authenticator", + "hotp", + "otp", + "totp" + ], + "time": "2020-01-28T09:24:19+00:00" }, { "name": "symfony/console", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "20bc0c1068565103075359f5ce9e0639b36f92d1" + "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/20bc0c1068565103075359f5ce9e0639b36f92d1", - "reference": "20bc0c1068565103075359f5ce9e0639b36f92d1", + "url": "https://api.github.com/repos/symfony/console/zipball/10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", + "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7", "shasum": "" }, "require": { @@ -4122,29 +4474,29 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2020-03-16T08:56:54+00:00" + "time": "2020-03-30T11:41:10+00:00" }, { "name": "symfony/css-selector", - "version": "v4.4.6", + "version": "v5.0.7", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "402251c6fd69806a70a2b0e1426d16f8487f0f9a" + "reference": "5f8d5271303dad260692ba73dfa21777d38e124e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/402251c6fd69806a70a2b0e1426d16f8487f0f9a", - "reference": "402251c6fd69806a70a2b0e1426d16f8487f0f9a", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/5f8d5271303dad260692ba73dfa21777d38e124e", + "reference": "5f8d5271303dad260692ba73dfa21777d38e124e", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.2.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -4175,49 +4527,38 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2020-03-16T08:56:54+00:00" + "time": "2020-03-27T16:56:45+00:00" }, { - "name": "symfony/dom-crawler", - "version": "v4.4.6", + "name": "symfony/deprecation-contracts", + "version": "v2.1.3", "source": { "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "7e7c7957f6d53757d36b61a1f7408ef0b6683040" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5e20b83385a77593259c9f8beb2c43cd03b2ac14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7e7c7957f6d53757d36b61a1f7408ef0b6683040", - "reference": "7e7c7957f6d53757d36b61a1f7408ef0b6683040", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5e20b83385a77593259c9f8beb2c43cd03b2ac14", + "reference": "5e20b83385a77593259c9f8beb2c43cd03b2ac14", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "masterminds/html5": "<2.6" - }, - "require-dev": { - "masterminds/html5": "^2.6", - "symfony/css-selector": "^3.4|^4.0|^5.0" - }, - "suggest": { - "symfony/css-selector": "" + "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "2.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -4226,30 +4567,30 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony DomCrawler Component", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "time": "2020-03-16T11:24:17+00:00" + "time": "2020-06-06T08:49:21+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780" + "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/cf57788d1ca64ee7e689698dc0295d25c9fe3780", - "reference": "cf57788d1ca64ee7e689698dc0295d25c9fe3780", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/abc8e3618bfdb55e44c8c6a00abd333f831bbfed", + "reference": "abc8e3618bfdb55e44c8c6a00abd333f831bbfed", "shasum": "" }, "require": { @@ -4306,7 +4647,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2020-03-16T11:24:17+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4368,26 +4709,26 @@ }, { "name": "symfony/filesystem", - "version": "v4.4.6", + "version": "v5.0.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "6d4fdf28187250f671c1edc9cf921ebfb7fe3809" + "reference": "ca3b87dd09fff9b771731637f5379965fbfab420" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/6d4fdf28187250f671c1edc9cf921ebfb7fe3809", - "reference": "6d4fdf28187250f671c1edc9cf921ebfb7fe3809", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/ca3b87dd09fff9b771731637f5379965fbfab420", + "reference": "ca3b87dd09fff9b771731637f5379965fbfab420", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -4414,29 +4755,29 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2020-03-16T08:56:54+00:00" + "time": "2020-03-27T16:56:45+00:00" }, { "name": "symfony/finder", - "version": "v4.4.6", + "version": "v5.0.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "ea69c129aed9fdeca781d4b77eb20b62cf5d5357" + "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ea69c129aed9fdeca781d4b77eb20b62cf5d5357", - "reference": "ea69c129aed9fdeca781d4b77eb20b62cf5d5357", + "url": "https://api.github.com/repos/symfony/finder/zipball/600a52c29afc0d1caa74acbec8d3095ca7e9910d", + "reference": "600a52c29afc0d1caa74acbec8d3095ca7e9910d", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.2.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -4463,35 +4804,41 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2020-02-14T07:42:58+00:00" + "time": "2020-03-27T16:56:45+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.4.6", + "version": "v5.1.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719" + "reference": "f93055171b847915225bd5b0a5792888419d8d75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0a3b7711229f816a06fac805f4ed4a8f4641c719", - "reference": "0a3b7711229f816a06fac805f4ed4a8f4641c719", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f93055171b847915225bd5b0a5792888419d8d75", + "reference": "f93055171b847915225bd5b0a5792888419d8d75", "shasum": "" }, "require": { - "php": "^7.1.3", - "symfony/mime": "^4.3|^5.0", - "symfony/polyfill-mbstring": "~1.1" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.15" }, "require-dev": { "predis/predis": "~1.0", - "symfony/expression-language": "^3.4|^4.0|^5.0" + "symfony/cache": "^4.4|^5.0", + "symfony/expression-language": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -4518,24 +4865,24 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2020-03-23T12:37:11+00:00" + "time": "2020-06-15T06:52:54+00:00" }, { "name": "symfony/mime", - "version": "v4.4.6", + "version": "v5.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "f6be9d809d805ab5bdb12f2d5843ba2c78533c7e" + "reference": "481b7d6da88922fb1e0d86a943987722b08f3955" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/f6be9d809d805ab5bdb12f2d5843ba2c78533c7e", - "reference": "f6be9d809d805ab5bdb12f2d5843ba2c78533c7e", + "url": "https://api.github.com/repos/symfony/mime/zipball/481b7d6da88922fb1e0d86a943987722b08f3955", + "reference": "481b7d6da88922fb1e0d86a943987722b08f3955", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -4544,12 +4891,12 @@ }, "require-dev": { "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^3.4|^4.1|^5.0" + "symfony/dependency-injection": "^4.4|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -4580,7 +4927,7 @@ "mime", "mime-type" ], - "time": "2020-03-16T11:24:17+00:00" + "time": "2020-03-27T16:56:45+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4874,18 +5221,84 @@ ], "time": "2020-02-27T09:26:54+00:00" }, + { + "name": "symfony/polyfill-php80", + "version": "v1.17.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "4a5b6bba3259902e386eb80dd1956181ee90b5b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/4a5b6bba3259902e386eb80dd1956181ee90b5b2", + "reference": "4a5b6bba3259902e386eb80dd1956181ee90b5b2", + "shasum": "" + }, + "require": { + "php": ">=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2020-06-06T08:46:27+00:00" + }, { "name": "symfony/process", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "b9863d0f7b684d7c4c13e665325b5ff047de0aee" + "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b9863d0f7b684d7c4c13e665325b5ff047de0aee", - "reference": "b9863d0f7b684d7c4c13e665325b5ff047de0aee", + "url": "https://api.github.com/repos/symfony/process/zipball/3e40e87a20eaf83a1db825e1fa5097ae89042db3", + "reference": "3e40e87a20eaf83a1db825e1fa5097ae89042db3", "shasum": "" }, "require": { @@ -4921,24 +5334,24 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2020-03-23T12:37:11+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.8", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf" + "reference": "144c5e51266b281231e947b51223ba14acf1a749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffc7f5692092df31515df2a5ecf3b7302b3ddacf", - "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -4947,7 +5360,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -4979,20 +5392,20 @@ "interoperability", "standards" ], - "time": "2019-10-14T12:27:06+00:00" + "time": "2019-11-18T17:27:11+00:00" }, { "name": "symfony/yaml", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb" + "reference": "ef166890d821518106da3560086bfcbeb4fadfec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb", - "reference": "43d7a46b1f80b4fd2ecfac4a9a4cc1f22d029fbb", + "url": "https://api.github.com/repos/symfony/yaml/zipball/ef166890d821518106da3560086bfcbeb4fadfec", + "reference": "ef166890d821518106da3560086bfcbeb4fadfec", "shasum": "" }, "require": { @@ -5038,7 +5451,139 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2020-03-16T08:56:54+00:00" + "time": "2020-03-30T11:41:10+00:00" + }, + { + "name": "thecodingmachine/safe", + "version": "v1.1", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "f440677bad66c0ef42fa3f875bf05718028af5d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/f440677bad66c0ef42fa3f875bf05718028af5d3", + "reference": "f440677bad66c0ef42fa3f875bf05718028af5d3", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "squizlabs/php_codesniffer": "^3.2", + "thecodingmachine/phpstan-strict-rules": "^0.12" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.1-dev" + } + }, + "autoload": { + "psr-4": { + "Safe\\": [ + "lib/", + "generated/" + ] + }, + "files": [ + "generated/apache.php", + "generated/apc.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/ingres-ii.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libevent.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/msql.php", + "generated/mssql.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/mysqlndMs.php", + "generated/mysqlndQc.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/password.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pdf.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/simplexml.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stats.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php", + "lib/special_cases.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "time": "2020-03-24T13:59:42+00:00" }, { "name": "theseer/tokenizer", @@ -5082,16 +5627,16 @@ }, { "name": "vlucas/phpdotenv", - "version": "v2.6.1", + "version": "v2.6.3", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5" + "reference": "df4c4d08a639be4ef5d6d1322868f9e477553679" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/2a7dcf7e3e02dc5e701004e51a6f304b713107d5", - "reference": "2a7dcf7e3e02dc5e701004e51a6f304b713107d5", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/df4c4d08a639be4ef5d6d1322868f9e477553679", + "reference": "df4c4d08a639be4ef5d6d1322868f9e477553679", "shasum": "" }, "require": { @@ -5099,8 +5644,14 @@ "symfony/polyfill-ctype": "^1.9" }, "require-dev": { + "ext-filter": "*", + "ext-pcre": "*", "phpunit/phpunit": "^4.8.35 || ^5.0" }, + "suggest": { + "ext-filter": "Required to use the boolean validator.", + "ext-pcre": "Required to use most of the library." + }, "type": "library", "extra": { "branch-alias": { @@ -5129,20 +5680,20 @@ "env", "environment" ], - "time": "2019-01-29T11:11:52+00:00" + "time": "2020-04-12T15:11:38+00:00" }, { "name": "webmozart/assert", - "version": "1.7.0", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", + "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", + "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", "shasum": "" }, "require": { @@ -5150,7 +5701,7 @@ "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "vimeo/psalm": "<3.6.0" + "vimeo/psalm": "<3.9.1" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" @@ -5177,7 +5728,7 @@ "check", "validate" ], - "time": "2020-02-14T12:15:55+00:00" + "time": "2020-04-18T12:12:48+00:00" }, { "name": "weew/helpers-array", @@ -5444,24 +5995,25 @@ }, { "name": "goaop/framework", - "version": "2.2.0", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/goaop/framework.git", - "reference": "152abbffffcba72d2d159b892deb40b0829d0f28" + "reference": "f980f249c55637acba0d5fdcfd2b5182c419f3d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/goaop/framework/zipball/152abbffffcba72d2d159b892deb40b0829d0f28", - "reference": "152abbffffcba72d2d159b892deb40b0829d0f28", + "url": "https://api.github.com/repos/goaop/framework/zipball/f980f249c55637acba0d5fdcfd2b5182c419f3d1", + "reference": "f980f249c55637acba0d5fdcfd2b5182c419f3d1", "shasum": "" }, "require": { "doctrine/annotations": "^1.2.3", "doctrine/cache": "^1.5", - "goaop/parser-reflection": "~1.4", + "goaop/parser-reflection": "~2.0", "jakubledl/dissect": "~1.0", - "php": ">=5.6.0" + "php": "~7.0", + "symfony/finder": "^3.4|^4.2|^5.0" }, "require-dev": { "adlawson/vfs": "^0.12", @@ -5469,7 +6021,8 @@ "phpunit/phpunit": "^5.7", "symfony/console": "^2.7|^3.0", "symfony/filesystem": "^3.3", - "symfony/process": "^3.3" + "symfony/process": "^3.3", + "webmozart/glob": "^4.1" }, "suggest": { "symfony/console": "Enables the usage of the command-line tool." @@ -5506,25 +6059,25 @@ "library", "php" ], - "time": "2018-01-05T23:07:51+00:00" + "time": "2020-04-06T09:46:21+00:00" }, { "name": "goaop/parser-reflection", - "version": "1.4.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/goaop/parser-reflection.git", - "reference": "d9c1dcc7ce4a5284fe3530e011faf9c9c10e1166" + "reference": "e9628006b321c8a62a8ad22085bc61eec0c21558" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/goaop/parser-reflection/zipball/d9c1dcc7ce4a5284fe3530e011faf9c9c10e1166", - "reference": "d9c1dcc7ce4a5284fe3530e011faf9c9c10e1166", + "url": "https://api.github.com/repos/goaop/parser-reflection/zipball/e9628006b321c8a62a8ad22085bc61eec0c21558", + "reference": "e9628006b321c8a62a8ad22085bc61eec0c21558", "shasum": "" }, "require": { - "nikic/php-parser": "^1.2|^2.0|^3.0", - "php": ">=5.6.0" + "nikic/php-parser": "^4.0", + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "~4.0" @@ -5532,7 +6085,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -5557,7 +6110,7 @@ } ], "description": "Provides reflection information, based on raw source", - "time": "2018-03-19T15:57:41+00:00" + "time": "2020-02-21T19:52:39+00:00" }, { "name": "guzzle/guzzle", @@ -5709,24 +6262,25 @@ }, { "name": "nikic/php-parser", - "version": "v3.1.5", + "version": "v4.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + "reference": "bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120", + "reference": "bd43ec7152eaaab3bd8c6d0aa95ceeb1df8ee120", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.5" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "ircmaxell/php-yacc": "0.0.5", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" }, "bin": [ "bin/php-parse" @@ -5734,7 +6288,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -5756,7 +6310,7 @@ "parser", "php" ], - "time": "2018-02-28T20:30:58+00:00" + "time": "2020-04-10T16:34:50+00:00" }, { "name": "pdepend/pdepend", @@ -5980,26 +6534,29 @@ }, { "name": "sebastian/finder-facade", - "version": "1.2.3", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "167c45d131f7fc3d159f56f191a0a22228765e16" + "reference": "9d3e74b845a2ce50e19b25b5f0c2718e153bee6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/167c45d131f7fc3d159f56f191a0a22228765e16", - "reference": "167c45d131f7fc3d159f56f191a0a22228765e16", + "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/9d3e74b845a2ce50e19b25b5f0c2718e153bee6c", + "reference": "9d3e74b845a2ce50e19b25b5f0c2718e153bee6c", "shasum": "" }, "require": { - "php": "^7.1", - "symfony/finder": "^2.3|^3.0|^4.0|^5.0", + "ext-ctype": "*", + "php": "^7.3", + "symfony/finder": "^4.1|^5.0", "theseer/fdomdocument": "^1.6" }, "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-master": "2.0-dev" + } }, "autoload": { "classmap": [ @@ -6019,29 +6576,29 @@ ], "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", "homepage": "https://github.com/sebastianbergmann/finder-facade", - "time": "2020-01-16T08:08:45+00:00" + "time": "2020-02-08T06:07:58+00:00" }, { "name": "sebastian/phpcpd", - "version": "4.1.0", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpcpd.git", - "reference": "0d9afa762f2400de077b2192f4a9d127de0bb78e" + "reference": "8724382966b1861df4e12db915eaed2165e10bf3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/0d9afa762f2400de077b2192f4a9d127de0bb78e", - "reference": "0d9afa762f2400de077b2192f4a9d127de0bb78e", + "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/8724382966b1861df4e12db915eaed2165e10bf3", + "reference": "8724382966b1861df4e12db915eaed2165e10bf3", "shasum": "" }, "require": { "ext-dom": "*", - "php": "^7.1", - "phpunit/php-timer": "^2.0", - "sebastian/finder-facade": "^1.1", - "sebastian/version": "^1.0|^2.0", - "symfony/console": "^2.7|^3.0|^4.0" + "php": "^7.3", + "phpunit/php-timer": "^3.0", + "sebastian/finder-facade": "^2.0", + "sebastian/version": "^3.0", + "symfony/console": "^4.0|^5.0" }, "bin": [ "phpcpd" @@ -6049,7 +6606,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -6070,20 +6627,20 @@ ], "description": "Copy/Paste Detector (CPD) for PHP code.", "homepage": "https://github.com/sebastianbergmann/phpcpd", - "time": "2018-09-17T17:17:27+00:00" + "time": "2020-02-22T06:03:17+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.4", + "version": "3.5.5", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dceec07328401de6211037abbb18bda423677e26" + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dceec07328401de6211037abbb18bda423677e26", - "reference": "dceec07328401de6211037abbb18bda423677e26", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6", + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6", "shasum": "" }, "require": { @@ -6121,20 +6678,20 @@ "phpcs", "standards" ], - "time": "2020-01-30T22:20:29+00:00" + "time": "2020-04-17T01:09:41+00:00" }, { "name": "symfony/config", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "235e5afffd3a1a1b0dd0221973cbf670bc3be1d4" + "reference": "3f4a3de1af498ed0ea653d4dc2317794144e6ca4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/235e5afffd3a1a1b0dd0221973cbf670bc3be1d4", - "reference": "235e5afffd3a1a1b0dd0221973cbf670bc3be1d4", + "url": "https://api.github.com/repos/symfony/config/zipball/3f4a3de1af498ed0ea653d4dc2317794144e6ca4", + "reference": "3f4a3de1af498ed0ea653d4dc2317794144e6ca4", "shasum": "" }, "require": { @@ -6185,20 +6742,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2020-03-16T11:24:17+00:00" + "time": "2020-03-27T16:54:36+00:00" }, { "name": "symfony/dependency-injection", - "version": "v4.4.6", + "version": "v4.4.7", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b4242fc7f18c8bf5427f84d5afe2131c9b323a04" + "reference": "755b18859be26b90f4bf63753432d3387458bf31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b4242fc7f18c8bf5427f84d5afe2131c9b323a04", - "reference": "b4242fc7f18c8bf5427f84d5afe2131c9b323a04", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/755b18859be26b90f4bf63753432d3387458bf31", + "reference": "755b18859be26b90f4bf63753432d3387458bf31", "shasum": "" }, "require": { @@ -6258,20 +6815,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2020-03-18T07:51:32+00:00" + "time": "2020-03-30T10:09:30+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.4.38", + "version": "v3.4.39", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "e2d954156d4817c9a5c79f519a71516693a4a9c8" + "reference": "a7a98f40dcc382a332c3729a6d04b298ffbb8f1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e2d954156d4817c9a5c79f519a71516693a4a9c8", - "reference": "e2d954156d4817c9a5c79f519a71516693a4a9c8", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/a7a98f40dcc382a332c3729a6d04b298ffbb8f1f", + "reference": "a7a98f40dcc382a332c3729a6d04b298ffbb8f1f", "shasum": "" }, "require": { @@ -6307,7 +6864,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2020-01-01T11:03:25+00:00" + "time": "2020-03-15T09:38:08+00:00" }, { "name": "theseer/fdomdocument", @@ -6356,9 +6913,10 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~7.1.0||~7.2.0||~7.3.0", + "php": "^7.3", "ext-curl": "*", "ext-dom": "*", + "ext-intl": "*", "ext-json": "*", "ext-openssl": "*" }, diff --git a/dev/tests/_bootstrap.php b/dev/tests/_bootstrap.php index 3f57ad139..059441721 100644 --- a/dev/tests/_bootstrap.php +++ b/dev/tests/_bootstrap.php @@ -35,7 +35,7 @@ true, \Magento\FunctionalTestingFramework\Config\MftfApplicationConfig::UNIT_TEST_PHASE, true, - \Magento\FunctionalTestingFramework\Config\MftfApplicationConfig::LEVEL_NONE, + \Magento\FunctionalTestingFramework\Config\MftfApplicationConfig::LEVEL_DEFAULT, false ); @@ -54,8 +54,8 @@ putenv("{$key}=${value}"); } -// Add our test module to the whitelist -putenv('MODULE_WHITELIST=Magento_TestModule'); +// Add our test module to the allowlist +putenv('MODULE_ALLOWLIST=Magento_TestModule'); // Define our own set of paths for the tests defined('FW_BP') || define('FW_BP', PROJECT_ROOT); @@ -102,28 +102,6 @@ require($unitUtilFile); } - -// Mocks suite files location getter return to get files in verification/_suite Directory -// This mocks the paths of the suite files but still parses the xml files -$suiteDirectory = TESTS_BP . DIRECTORY_SEPARATOR . "verification" . DIRECTORY_SEPARATOR . "_suite"; - -$paths = [ - $suiteDirectory . DIRECTORY_SEPARATOR . 'functionalSuite.xml', - $suiteDirectory . DIRECTORY_SEPARATOR . 'functionalSuiteHooks.xml', - $suiteDirectory . DIRECTORY_SEPARATOR . 'functionalSuiteExtends.xml' -]; - -// create and return the iterator for these file paths -$iterator = new Magento\FunctionalTestingFramework\Util\Iterator\File($paths); -try { - AspectMock\Test::double( - Magento\FunctionalTestingFramework\Config\FileResolver\Root::class, - ['get' => $iterator] - )->make(); -} catch (Exception $e) { - echo "Suite directory not mocked."; -} - function sortInterfaces($files) { $bottom = []; diff --git a/dev/tests/functional/standalone_bootstrap.php b/dev/tests/functional/standalone_bootstrap.php index 486c7566b..58030231d 100755 --- a/dev/tests/functional/standalone_bootstrap.php +++ b/dev/tests/functional/standalone_bootstrap.php @@ -51,7 +51,10 @@ $env->setEnvironmentVariable('DEFAULT_TIMEZONE', DEFAULT_TIMEZONE); defined('WAIT_TIMEOUT') || define('WAIT_TIMEOUT', 30); - $env->setEnvironmentVariable('WAIT_TIMEOUT', 30); + $env->setEnvironmentVariable('WAIT_TIMEOUT', WAIT_TIMEOUT); + + defined('VERBOSE_ARTIFACTS') || define('VERBOSE_ARTIFACTS', false); + $env->setEnvironmentVariable('VERBOSE_ARTIFACTS', VERBOSE_ARTIFACTS); try { new DateTimeZone(DEFAULT_TIMEZONE); diff --git a/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml index 908808a8c..6c27627d5 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml @@ -6,7 +6,7 @@ */ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> diff --git a/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/HelperActionGroup.xml b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/HelperActionGroup.xml new file mode 100644 index 000000000..42159fc66 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/HelperActionGroup.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + {{contentSection.parametrizedSelector(entityTest.entityField)}} + ['{{entityTest.entityField}}', 'Bla'] + {{test}} + true + 4.400000000234234 + 42 + + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml index 5835a78af..ba1460a60 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml @@ -7,8 +7,11 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> Introduction to the Magento Functional Testing Framework + + Some data + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/ExtendMessageData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/ExtendMessageData.xml new file mode 100644 index 000000000..040b80597 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/ExtendMessageData.xml @@ -0,0 +1,16 @@ + + + + + + + Something New + + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/HelperData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/HelperData.xml new file mode 100644 index 000000000..bc84a5fb2 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/HelperData.xml @@ -0,0 +1,14 @@ + + + + + + Some kind of data for testing purposes + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml index eb77e73bc..f35812e54 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml @@ -7,8 +7,20 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> Introduction to the Magento Functional Testing Framework + + 0 + 1 + 2 + 3 + + + + + + TESTING CASE + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php b/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php new file mode 100644 index 000000000..46fba18d9 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Helper/CustomHelper.php @@ -0,0 +1,49 @@ + 'value', 'test'] + ) { + print('Hello, this is custom helper which provides an ability to write custom solutions.' . PHP_EOL); + print('string $url = ' . $url . PHP_EOL); + print('$test = ' . $test . PHP_EOL); + print('$bool = ' . $bool . PHP_EOL); + print('$int = ' . $int . PHP_EOL); + print('$float = ' . $float . PHP_EOL); + print('array $module = [' . implode(', ', $module) . ']' . PHP_EOL); + print('$superBla = ' . $superBla . PHP_EOL); + print('$bla = ' . $bla . PHP_EOL); + print('array $arraysomething = [' . implode(', ', $arraysomething) . ']' . PHP_EOL); + } +} diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml b/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml index ee47fe954..8be64e9ca 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml b/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml index 88c577aef..9783fb0b3 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml b/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml index 15af0fa39..e0a133d51 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml @@ -7,9 +7,10 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
+
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Section/DeprecatedContentSection.xml b/dev/tests/functional/tests/MFTF/DevDocs/Section/DeprecatedContentSection.xml index cc316d6ed..8ed018146 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Section/DeprecatedContentSection.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Section/DeprecatedContentSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml index c93dc8011..6aae104ed 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> @@ -22,6 +22,6 @@ - + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml index c6b2575b9..bda1cfb57 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> @@ -22,5 +22,34 @@ + + {{contentSection.pageIntro}} + ['Test', 'Bla'] + {{MFTFDocPage.url}} + true + 1.2 + 123 + + + + {{contentSection.pageIntro}} + [] + {{DeprecatedMFTFDocPage.url}} + 1.2 + + false + 4.223 + 987 + + + + + + + + + {{ExtendedMessageData.numbers}} + ["Something New", "0", "1", "2", "3", "TESTING CASE"] + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/FormatCurrencyTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/FormatCurrencyTest.xml new file mode 100644 index 000000000..ab3d36c4e --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/FormatCurrencyTest.xml @@ -0,0 +1,52 @@ + + + + + + + + + 1.234,57 € + $eurInDE + + + + 1.234,00 € + $eurInDEPos + + + + -1.234,56 € + $eurInDENeg + + + + + 1.234,57 $ + $usdInDE + + + + 1.234,00 $ + $usdInDEPos + + + + -1.234,56 $ + $usdInDENeg + + + + + + 10,50 € + $usingVariable + + + diff --git a/dev/tests/phpunit.xml b/dev/tests/phpunit.xml index 9648ab3fd..1014ec7c3 100644 --- a/dev/tests/phpunit.xml +++ b/dev/tests/phpunit.xml @@ -7,7 +7,7 @@ diff --git a/dev/tests/static/Magento/Sniffs/Commenting/FunctionCommentSniff.php b/dev/tests/static/Magento/Sniffs/Commenting/FunctionCommentSniff.php index 5050d5f03..8985f2407 100644 --- a/dev/tests/static/Magento/Sniffs/Commenting/FunctionCommentSniff.php +++ b/dev/tests/static/Magento/Sniffs/Commenting/FunctionCommentSniff.php @@ -214,7 +214,7 @@ protected function processThrows(File $phpcsFile, $stackPtr, $commentStart) } // Starts with a capital letter and ends with a fullstop. - $firstChar = $comment{0}; + $firstChar = $comment[0]; if (strtoupper($firstChar) !== $firstChar) { $error = '@throws tag comment must start with a capital letter'; $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); @@ -437,7 +437,7 @@ protected function processParams(File $phpcsFile, $stackPtr, $commentStart) }//end if }//end foreach - $suggestedType = implode($suggestedTypeNames, '|'); + $suggestedType = implode('|', $suggestedTypeNames); if ($param['type'] !== $suggestedType) { $error = 'Expected "%s" but found "%s" for parameter type'; $data = array( diff --git a/dev/tests/static/Magento/Sniffs/MicroOptimizations/IsNullSniff.php b/dev/tests/static/Magento/Sniffs/MicroOptimizations/IsNullSniff.php index 928fc3a0d..9ec74cb4f 100644 --- a/dev/tests/static/Magento/Sniffs/MicroOptimizations/IsNullSniff.php +++ b/dev/tests/static/Magento/Sniffs/MicroOptimizations/IsNullSniff.php @@ -13,7 +13,7 @@ class IsNullSniff implements Sniff /** * @var string */ - protected $blacklist = 'is_null'; + protected $blocklist = 'is_null'; /** * @inheritdoc @@ -29,7 +29,7 @@ public function register() public function process(File $sourceFile, $stackPtr) { $tokens = $sourceFile->getTokens(); - if ($tokens[$stackPtr]['content'] === $this->blacklist) { + if ($tokens[$stackPtr]['content'] === $this->blocklist) { $sourceFile->addError( "is_null must be avoided. Use strict comparison instead.", $stackPtr, diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Allure/AllureHelperTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Allure/AllureHelperTest.php index b7eafaead..b009af5ff 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Allure/AllureHelperTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Allure/AllureHelperTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestingFramework\Allure; +namespace tests\unit\Magento\FunctionalTestFramework\Allure; use Magento\FunctionalTestingFramework\Allure\AllureHelper; use Magento\FunctionalTestingFramework\Allure\Event\AddUniqueAttachmentEvent; @@ -22,7 +22,7 @@ class AllureHelperTest extends TestCase /** * Clear Allure Lifecycle */ - public function tearDown() + public function tearDown(): void { Allure::setDefaultLifecycle(); AspectMock::clean(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerInstallTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerInstallTest.php index e4977184f..9b8327bd4 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerInstallTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerInstallTest.php @@ -4,10 +4,10 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Composer; use Magento\FunctionalTestingFramework\Composer\ComposerInstall; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class ComposerInstallTest extends MagentoTestCase { @@ -18,7 +18,7 @@ class ComposerInstallTest extends MagentoTestCase */ private $composer; - public function setUp() + public function setUp(): void { $composerJson = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Composer' . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'dir1' . DIRECTORY_SEPARATOR . 'dir2' . DIRECTORY_SEPARATOR . 'composer.json'; diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerPackageTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerPackageTest.php index 4802f0c33..7620f9c1c 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerPackageTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Composer/ComposerPackageTest.php @@ -4,10 +4,10 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Composer; use Magento\FunctionalTestingFramework\Composer\ComposerPackage; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Composer\Package\RootPackage; class ComposerPackageTest extends MagentoTestCase @@ -19,7 +19,7 @@ class ComposerPackageTest extends MagentoTestCase */ private $composer; - public function setUp() + public function setUp(): void { $composerJson = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Composer' . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR . 'dir1' . DIRECTORY_SEPARATOR . 'dir2' . DIRECTORY_SEPARATOR . 'composer.json'; diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php index b59858e7f..f91f071f0 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Config\Reader; +namespace tests\unit\Magento\FunctionalTestFramework\Config\Reader; use Magento\FunctionalTestingFramework\Config\FileResolver\Module; use Magento\FunctionalTestingFramework\Config\Reader\Filesystem; @@ -19,7 +19,7 @@ class FilesystemTest extends TestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -100,7 +100,7 @@ public function createPseudoFileSystem($fileList) * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); parent::tearDownAfterClass(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php index 234f677e8..d2a58c0ff 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestingFramework\Console; +namespace tests\unit\Magento\FunctionalTestFramework\Console; use AspectMock\Test as AspectMock; use PHPUnit\Framework\TestCase; @@ -15,7 +15,7 @@ class BaseGenerateCommandTest extends TestCase { - public function tearDown() + public function tearDown(): void { AspectMock::clean(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/DataObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/DataObjectHandlerTest.php index d55f35247..c9ec92ba8 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/DataObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/DataObjectHandlerTest.php @@ -12,7 +12,7 @@ use Magento\FunctionalTestingFramework\DataGenerator\Parsers\DataProfileSchemaParser; use Magento\FunctionalTestingFramework\ObjectManager; use Magento\FunctionalTestingFramework\ObjectManagerFactory; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class DataObjectHandlerTest diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/OperationDefinitionObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/OperationDefinitionObjectHandlerTest.php index b54980314..9ca10c7f2 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/OperationDefinitionObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/OperationDefinitionObjectHandlerTest.php @@ -13,7 +13,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Parsers\OperationDefinitionParser; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class OperationDefinitionObjectHandlerTest diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php index 592b87f4e..870e75dcd 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php @@ -15,7 +15,7 @@ use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; use Magento\FunctionalTestingFramework\ObjectManager; use Magento\FunctionalTestingFramework\ObjectManagerFactory; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\TestLoggingUtil; /** @@ -27,7 +27,7 @@ class PersistedObjectHandlerTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -510,7 +510,7 @@ public function mockCurlHandler($response) ]); } - public function tearDown() + public function tearDown(): void { // Clear out Singleton between tests $property = new \ReflectionProperty(PersistedObjectHandler::class, "INSTANCE"); @@ -524,7 +524,7 @@ public function tearDown() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); parent::tearDownAfterClass(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php index e1f4e4879..3112529c2 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php @@ -9,7 +9,7 @@ use Aws\SecretsManager\SecretsManagerClient; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\AwsSecretsManagerStorage; use Aws\Result; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use ReflectionClass; class AwsSecretsManagerStorageTest extends MagentoTestCase diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php index 7e5824c8e..62cb9798e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php @@ -7,7 +7,7 @@ namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers\SecretStorage; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use AspectMock\Test as AspectMock; class FileStorageTest extends MagentoTestCase diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Objects/EntityDataObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Objects/EntityDataObjectTest.php index 802a6c108..3fc2aaacb 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Objects/EntityDataObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Objects/EntityDataObjectTest.php @@ -6,7 +6,7 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Objects; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use tests\unit\Util\TestLoggingUtil; @@ -40,7 +40,7 @@ class EntityDataObjectTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -141,7 +141,7 @@ public function testGetCamelCaseKeys() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php index fb6dcd865..3596edd98 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php @@ -10,7 +10,7 @@ use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Persist\OperationDataArrayResolver; use Magento\FunctionalTestingFramework\Util\Iterator\AbstractIterator; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\EntityDataObjectBuilder; use tests\unit\Util\OperationDefinitionBuilder; use tests\unit\Util\OperationElementBuilder; @@ -41,7 +41,7 @@ class OperationDataArrayResolverTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -481,7 +481,7 @@ public function testNestedMetadataArrayOfDiverseObjects() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Util/DataExtensionUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Util/DataExtensionUtilTest.php index e72c15b31..3b79ffec3 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Util/DataExtensionUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Util/DataExtensionUtilTest.php @@ -4,25 +4,25 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Objects; +namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Util; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Parsers\DataProfileSchemaParser; use Magento\FunctionalTestingFramework\ObjectManager\ObjectManager; use Magento\FunctionalTestingFramework\ObjectManagerFactory; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use AspectMock\Test as AspectMock; /** - * Class EntityDataObjectTest + * Class DataExtensionUtilTest */ -class EntityDataExtensionTest extends MagentoTestCase +class DataExtensionUtilTest extends MagentoTestCase { /** * Before method functionality * @return void */ - protected function setUp() + protected function setUp(): void { AspectMock::clean(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Extension/BrowserLogUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Extension/BrowserLogUtilTest.php index 32cac698e..45d14ae99 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Extension/BrowserLogUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Extension/BrowserLogUtilTest.php @@ -6,7 +6,7 @@ namespace tests\unit\Magento\FunctionalTestFramework\Extension; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Extension\BrowserLogUtil; class BrowserLogUtilTest extends MagentoTestCase diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/PageObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/PageObjectHandlerTest.php index 28ffcd9e1..1a0ba5fc2 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/PageObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/PageObjectHandlerTest.php @@ -11,7 +11,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Page\Handlers\PageObjectHandler; use Magento\FunctionalTestingFramework\XmlParser\PageParser; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class PageObjectHandlerTest extends MagentoTestCase { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/SectionObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/SectionObjectHandlerTest.php index 4a939dbad..b8bcf3dfb 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/SectionObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Handlers/SectionObjectHandlerTest.php @@ -11,7 +11,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Page\Handlers\SectionObjectHandler; use Magento\FunctionalTestingFramework\XmlParser\SectionParser; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class SectionObjectHandlerTest extends MagentoTestCase { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/ElementObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/ElementObjectTest.php index d585f4085..eacafbc68 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/ElementObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/ElementObjectTest.php @@ -8,7 +8,7 @@ use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class ElementObjectTest @@ -32,7 +32,7 @@ public function testTimeoutNotNull() $element = new ElementObject('name', 'type', 'selector', null, '15', false); $timeout = $element->getTimeout(); $this->assertEquals(15, $timeout); - $this->assertInternalType('int', $timeout); + $this->assertIsInt($timeout); } /** @@ -43,7 +43,7 @@ public function testTimeoutCastFromString() $element = new ElementObject('name', 'type', 'selector', null, 'helloString', true); $timeout = $element->getTimeout(); $this->assertEquals(0, $timeout); - $this->assertInternalType('int', $timeout); + $this->assertIsInt($timeout); } /** diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/PageObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/PageObjectTest.php index 7f8053e77..29ec5366d 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/PageObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/PageObjectTest.php @@ -7,7 +7,7 @@ namespace tests\unit\Magento\FunctionalTestFramework\Page\Objects; use Magento\FunctionalTestingFramework\Page\Objects\PageObject; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class PageObjectTest diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/SectionObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/SectionObjectTest.php index 5ed1f557f..4305c0101 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/SectionObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Page/Objects/SectionObjectTest.php @@ -8,7 +8,7 @@ use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class SectionObjectTest diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php index e45127f4c..6f337b05c 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/Handlers/SuiteObjectHandlerTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Suite\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\Suite\Handlers; use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\ObjectManager\ObjectManager; @@ -12,14 +12,14 @@ use Magento\FunctionalTestingFramework\Suite\Parsers\SuiteDataParser; use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\SuiteDataArrayBuilder; use tests\unit\Util\TestDataArrayBuilder; use tests\unit\Util\MockModuleResolverBuilder; class SuiteObjectHandlerTest extends MagentoTestCase { - public function setUp() + public function setUp(): void { $resolverMock = new MockModuleResolverBuilder(); $resolverMock->setup(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php index 842be4f88..8ac8fae37 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Suite; +namespace tests\unit\Magento\FunctionalTestFramework\Suite; use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; @@ -17,7 +17,7 @@ use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser; use Magento\FunctionalTestingFramework\Util\Manifest\DefaultTestManifest; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Util\Manifest\TestManifestFactory; use tests\unit\Util\SuiteDataArrayBuilder; use tests\unit\Util\TestDataArrayBuilder; @@ -29,7 +29,7 @@ class SuiteGeneratorTest extends MagentoTestCase /** * Setup entry append and clear for Suite Generator */ - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { AspectMock::double(SuiteGenerator::class, [ 'clearPreviousSessionConfigEntries' => null, @@ -41,7 +41,7 @@ public static function setUpBeforeClass() * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); $resolverMock = new MockModuleResolverBuilder(); @@ -181,7 +181,7 @@ public function testInvalidSuiteTestPair() // Set up Expected Exception $this->expectException(TestReferenceException::class); - $this->expectExceptionMessageRegExp('(Suite: "Suite2" Tests: "Test1")'); + $this->expectExceptionMessageMatches('(Suite: "Suite2" Tests: "Test1")'); // parse and generate suite object with mocked data and manifest $mockSuiteGenerator = SuiteGenerator::getInstance(); @@ -205,7 +205,7 @@ public function testNonExistentSuiteTestPair() // Set up Expected Exception $this->expectException(TestReferenceException::class); - $this->expectExceptionMessageRegExp('#Suite3 is not defined#'); + $this->expectExceptionMessageMatches('#Suite3 is not defined#'); // parse and generate suite object with mocked data and manifest $mockSuiteGenerator = SuiteGenerator::getInstance(); @@ -274,7 +274,7 @@ private function setMockTestAndSuiteParserOutput($testData, $suiteData) /** * clean up function runs after all tests */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); parent::tearDownAfterClass(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/ActionGroupDomTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/ActionGroupDomTest.php index 6a0c926be..cf29b62b5 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/ActionGroupDomTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/ActionGroupDomTest.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Config; +namespace tests\unit\Magento\FunctionalTestFramework\Test\Config; use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; use Magento\FunctionalTestingFramework\Config\Dom\ValidationException; use Magento\FunctionalTestingFramework\Test\Config\ActionGroupDom; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class ActionGroupDomTest extends MagentoTestCase { @@ -65,7 +65,7 @@ public function testActionGroupDomDuplicateActionGroupsValidation() $exceptionCollector = new ExceptionCollector(); new ActionGroupDom($sampleXml, 'dupeNameActionGroup.xml', $exceptionCollector); $this->expectException(\Exception::class); - $this->expectExceptionMessageRegExp("/name: actionGroupName is used more than once./"); + $this->expectExceptionMessageMatches("/name: actionGroupName is used more than once./"); $exceptionCollector->throwException(); } } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/DomTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/DomTest.php index e00926978..5601dce10 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/DomTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Config/DomTest.php @@ -3,12 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Config; +namespace tests\unit\Magento\FunctionalTestFramework\Test\Config; use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; use Magento\FunctionalTestingFramework\Config\Dom\ValidationException; use Magento\FunctionalTestingFramework\Test\Config\ActionGroupDom; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class DomTest extends MagentoTestCase { @@ -28,7 +28,7 @@ public function testTestStepKeyDuplicateValidation() new ActionGroupDom($sampleXml, 'dupeStepKeyTest.xml', $exceptionCollector); $this->expectException(\Exception::class); - $this->expectExceptionMessageRegExp("/stepKey: key1 is used more than once. \(Parent: testName\)/"); + $this->expectExceptionMessageMatches("/stepKey: key1 is used more than once. \(Parent: testName\)/"); $exceptionCollector->throwException(); } @@ -49,7 +49,7 @@ public function testTestNameDuplicateValidation() $exceptionCollector = new ExceptionCollector(); new ActionGroupDom($sampleXml, 'dupeTestsTest.xml', $exceptionCollector); $this->expectException(\Exception::class); - $this->expectExceptionMessageRegExp("/name: testName is used more than once./"); + $this->expectExceptionMessageMatches("/name: testName is used more than once./"); $exceptionCollector->throwException(); } } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/ActionGroupObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/ActionGroupObjectHandlerTest.php index 4a7c6101e..deb08d783 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/ActionGroupObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/ActionGroupObjectHandlerTest.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\Test\Handlers; use AspectMock\Test as AspectMock; @@ -12,7 +12,7 @@ use Magento\FunctionalTestingFramework\ObjectManager; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\ActionGroupArrayBuilder; use Magento\FunctionalTestingFramework\Test\Parsers\ActionGroupDataParser; diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php index a4504ab07..4db2f21a4 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\Test\Handlers; use AspectMock\Test as AspectMock; @@ -16,7 +16,7 @@ use Magento\FunctionalTestingFramework\Test\Objects\TestObject; use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser; use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\TestDataArrayBuilder; use tests\unit\Util\MockModuleResolverBuilder; @@ -283,7 +283,7 @@ private function setMockParserOutput($data) * * @return void */ - public function tearDown() + public function tearDown(): void { AspectMock::clean(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php index 796e8a28b..4424989f8 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionGroupObjectTest.php @@ -15,7 +15,7 @@ use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Objects\ArgumentObject; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\ActionGroupObjectBuilder; use tests\unit\Util\EntityDataObjectBuilder; use tests\unit\Util\TestLoggingUtil; @@ -28,7 +28,7 @@ class ActionGroupObjectTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -243,7 +243,7 @@ public function testExceptionOnMissingActions() ->build(); $this->expectException(TestReferenceException::class); - $this->expectExceptionMessageRegExp('/Arguments missed .* for actionGroup/'); + $this->expectExceptionMessageMatches('/Arguments missed .* for actionGroup/'); $actionGroupUnderTest->getSteps(['arg2' => 'data1'], self::ACTION_GROUP_MERGE_KEY); } @@ -257,7 +257,7 @@ public function testExceptionOnMissingArguments() ->build(); $this->expectException(TestReferenceException::class); - $this->expectExceptionMessageRegExp('/Arguments missed .* for actionGroup/'); + $this->expectExceptionMessageMatches('/Arguments missed .* for actionGroup/'); $actionGroupUnderTest->getSteps(null, self::ACTION_GROUP_MERGE_KEY); } @@ -355,7 +355,7 @@ private function assertOnMergeKeyAndActionValue($actions, $expectedValue, $expec * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionObjectTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionObjectTest.php index 511c9748f..8bf71d542 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionObjectTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Objects/ActionObjectTest.php @@ -17,7 +17,7 @@ use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; use tests\unit\Util\TestLoggingUtil; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; /** * Class ActionObjectTest @@ -28,7 +28,7 @@ class ActionObjectTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -233,6 +233,8 @@ public function testResolveUrl() */ public function testResolveUrlWithNoAttribute() { + $this->expectException(TestReferenceException::class); + // Set up mocks $actionObject = new ActionObject('merge123', 'amOnPage', [ 'url' => '{{PageObject}}' @@ -247,19 +249,6 @@ public function testResolveUrlWithNoAttribute() // Call the method under test $actionObject->resolveReferences(); - - // Expect this warning to get generated - TestLoggingUtil::getInstance()->validateMockLogStatement( - "warning", - "page url attribute not found and is required", - ['action' => $actionObject->getType(), 'url' => '{{PageObject}}', 'stepKey' => $actionObject->getStepKey()] - ); - - // Verify - $expected = [ - 'url' => '{{PageObject}}' - ]; - $this->assertEquals($expected, $actionObject->getCustomActionAttributes()); } /** @@ -404,7 +393,7 @@ private function mockDataHandlerWithData($dataObject) * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php index af39298b1..a3d2cca86 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php @@ -16,7 +16,7 @@ class ActionGroupAnnotationExtractorTest extends TestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -44,54 +44,11 @@ public function testActionGroupExtractAnnotations() $this->assertEquals("someDescription", $returnedAnnotations['description']); } - /** - * Annotation extractor should throw warning when required annotations are missing - * - * @throws \Exception - */ - public function testActionGroupMissingAnnotations() - { - // Action Group Data, missing description - $testAnnotations = []; - // Perform Test - $extractor = new ActionGroupAnnotationExtractor(); - AspectMock::double($extractor, ['isCommandDefined' => true]); - $extractor->extractAnnotations($testAnnotations, "fileName"); - - // Asserts - TestLoggingUtil::getInstance()->validateMockLogStatement( - 'warning', - 'DEPRECATION: Action Group File fileName is missing required annotations.', - [ - 'actionGroup' => 'fileName', - 'missingAnnotations' => "description" - ] - ); - } - - /** - * Annotation extractor should not throw warning when required - * annotations are missing if command is not generate:docs - * - * @throws \Exception - */ - public function testActionGroupMissingAnnotationsNoWarning() - { - // Action Group Data, missing description - $testAnnotations = []; - // Perform Test - $extractor = new ActionGroupAnnotationExtractor(); - $extractor->extractAnnotations($testAnnotations, "fileName"); - - // Asserts - TestLoggingUtil::getInstance()->validateMockLogEmpty(); - } - /** * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupObjectExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupObjectExtractorTest.php index 47b797c1c..2c9e171d5 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupObjectExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupObjectExtractorTest.php @@ -6,7 +6,7 @@ namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; use Magento\FunctionalTestingFramework\Test\Util\ActionGroupObjectExtractor; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\TestLoggingUtil; class ActionGroupObjectExtractorTest extends MagentoTestCase @@ -17,7 +17,7 @@ class ActionGroupObjectExtractorTest extends MagentoTestCase /** * Setup method */ - public function setUp() + public function setUp(): void { $this->testActionGroupObjectExtractor = new ActionGroupObjectExtractor(); TestLoggingUtil::getInstance()->setMockLoggingUtil(); @@ -63,7 +63,7 @@ private function createBasicActionObjectArray( /** * clean up function runs after all tests */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php index 7917d663b..8c55210a4 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php @@ -13,8 +13,7 @@ use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; -use tests\unit\Util\DataObjectHandlerReflectionUtil; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\TestLoggingUtil; class ActionMergeUtilTest extends MagentoTestCase @@ -23,7 +22,7 @@ class ActionMergeUtilTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -292,7 +291,7 @@ public function testInvalidSecretFunctions() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionObjectExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionObjectExtractorTest.php index f584adea9..6f464b41e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionObjectExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionObjectExtractorTest.php @@ -7,7 +7,7 @@ use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\TestLoggingUtil; class ActionObjectExtractorTest extends MagentoTestCase @@ -18,7 +18,7 @@ class ActionObjectExtractorTest extends MagentoTestCase /** * Setup method */ - public function setUp() + public function setUp(): void { $this->testActionObjectExtractor = new ActionObjectExtractor(); TestLoggingUtil::getInstance()->setMockLoggingUtil(); @@ -130,7 +130,7 @@ private function createBasicActionObjectArray($stepKey = 'testAction1', $before /** * clean up function runs after all tests */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/AnnotationExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/AnnotationExtractorTest.php index fb93cbb88..bfb108ce8 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/AnnotationExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/AnnotationExtractorTest.php @@ -19,7 +19,7 @@ class AnnotationExtractorTest extends TestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -209,7 +209,7 @@ public function testTestCaseIdUniqueness() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php index 9982b8040..4b9830a59 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ObjectExtensionUtilTest.php @@ -28,7 +28,7 @@ class ObjectExtensionUtilTest extends TestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); $resolverMock = new MockModuleResolverBuilder(); @@ -39,7 +39,7 @@ public function setUp() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ActionMergeUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ActionMergeUtilTest.php index 913b106a7..864149b2f 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ActionMergeUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ActionMergeUtilTest.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\Util; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class ActionMergeUtilTest extends MagentoTestCase { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ComposerModuleResolverTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ComposerModuleResolverTest.php index 3173730b3..cec5f097e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ComposerModuleResolverTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ComposerModuleResolverTest.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Util; use ReflectionClass; use Magento\FunctionalTestingFramework\Util\ComposerModuleResolver; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class ComposerModuleResolverTest extends MagentoTestCase { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php deleted file mode 100644 index 0fb73e53f..000000000 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php +++ /dev/null @@ -1,127 +0,0 @@ - "someDescription" - ]; - $actionGroupUnderTest = (new ActionGroupObjectBuilder()) - ->withAnnotations($annotations) - ->withFilename("filename") - ->build(); - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation( - [$actionGroupUnderTest->getName() => $actionGroupUnderTest], - DOCS_OUTPUT_DIR, - true - ); - - $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; - - $this->assertTrue(file_exists($docFile)); - - $this->assertFileEquals( - RESOURCE_DIR . DIRECTORY_SEPARATOR . "basicDocumentation.txt", - $docFile - ); - } - - /** - * Test to check creation of documentation when overwriting previous - * - * @throws \Exception - */ - public function testCreateDocumentationWithOverwrite() - { - $annotations = [ - "description" => "someDescription" - ]; - $actionGroupUnderTest = (new ActionGroupObjectBuilder()) - ->withAnnotations($annotations) - ->withFilename("filename") - ->build(); - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation( - [$actionGroupUnderTest->getName() => $actionGroupUnderTest], - DOCS_OUTPUT_DIR, - true - ); - - $annotations = [ - "description" => "alteredDescription" - ]; - $actionGroupUnderTest = (new ActionGroupObjectBuilder()) - ->withAnnotations($annotations) - ->withFilename("filename") - ->build(); - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation( - [$actionGroupUnderTest->getName() => $actionGroupUnderTest], - DOCS_OUTPUT_DIR, - true - ); - - $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; - - $this->assertTrue(file_exists($docFile)); - - $this->assertFileEquals( - RESOURCE_DIR . DIRECTORY_SEPARATOR . "alteredDocumentation.txt", - $docFile - ); - } - - /** - * Test for existing documentation without clean - * - * @throws \Exception - */ - public function testCreateDocumentationNotCleanException() - { - $annotations = [ - "description" => "someDescription" - ]; - $actionGroupUnderTest = (new ActionGroupObjectBuilder()) - ->withAnnotations($annotations) - ->withFilename("filename") - ->build(); - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation( - [$actionGroupUnderTest->getName() => $actionGroupUnderTest], - DOCS_OUTPUT_DIR, - true - ); - - $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; - - $this->expectException(TestFrameworkException::class); - $this->expectExceptionMessage("$docFile already exists, please add --clean if you want to overwrite it."); - - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation( - [$actionGroupUnderTest->getName() => $actionGroupUnderTest], - DOCS_OUTPUT_DIR, - false - ); - } -} diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php index 05bc99b89..3f2ba1962 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModulePathExtractorTest.php @@ -4,10 +4,10 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Util; use Magento\FunctionalTestingFramework\Util\ModulePathExtractor; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use tests\unit\Util\MockModuleResolverBuilder; class ModulePathExtractorTest extends MagentoTestCase diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php index 07e1ee7fa..c554062fd 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Util; use AspectMock\Proxy\Verifier; use AspectMock\Test as AspectMock; @@ -15,7 +15,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\Util\ModuleResolver; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use PHPUnit\Runner\Exception; use tests\unit\Util\TestLoggingUtil; @@ -25,7 +25,7 @@ class ModuleResolverTest extends MagentoTestCase * Before test functionality * @return void */ - public function setUp() + public function setUp(): void { TestLoggingUtil::getInstance()->setMockLoggingUtil(); } @@ -34,7 +34,7 @@ public function setUp() * After class functionality * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } @@ -57,7 +57,6 @@ public function testGetModulePathsAlreadySet() */ public function testGetModulePathsAggregate() { - $this->mockForceGenerate(false); $this->setMockResolverClass( false, @@ -89,6 +88,50 @@ public function testGetModulePathsAggregate() ); } + /** + * Validate aggregateTestModulePaths() when module path part of DEV_TESTS + * + * @throws \Exception + */ + public function testAggregateTestModulePathsDevTests() + { + $origin = TESTS_MODULE_PATH; + $modulePath = ModuleResolver::DEV_TESTS . DIRECTORY_SEPARATOR . "Magento"; + putenv("TESTS_MODULE_PATH=$modulePath"); + + $this->mockForceGenerate(false); + $mockResolver = $this->setMockResolverClass( + true, + [], + null, + null, + [], + [], + [], + null, + null, + [], + [], + null, + function ($arg) { + return $arg; + }, + function ($arg) { + return $arg; + } + ); + $resolver = ModuleResolver::getInstance(); + $this->setMockResolverProperties($resolver, null, null); + $this->assertEquals( + [], + $resolver->getModulesPath() + ); + + $mockResolver->verifyNeverInvoked('globRelevantPaths', [$modulePath, '']); + + putenv("TESTS_MODULE_PATH=$origin"); + } + /** * Validate correct path locations are fed into globRelevantPaths * @throws \Exception @@ -146,20 +189,6 @@ function ($arg) { 'Test' . DIRECTORY_SEPARATOR .'Mftf' ] ); - $mockResolver->verifyInvoked( - 'globRelevantPaths', - [ - $magentoBaseCodePath - . DIRECTORY_SEPARATOR . "dev" - . DIRECTORY_SEPARATOR . "tests" - . DIRECTORY_SEPARATOR . "acceptance" - . DIRECTORY_SEPARATOR . "tests" - . DIRECTORY_SEPARATOR . "functional" - . DIRECTORY_SEPARATOR . "Magento" - . DIRECTORY_SEPARATOR . "FunctionalTest" - , '' - ] - ); } /** @@ -423,6 +452,81 @@ public function testMergeFlipAndFilterModulePathsNoForceGenerate() ); } + /** + * Validate mergeModulePaths() and flipAndSortModulePathsArray() + * + * @throws \Exception + */ + public function testMergeFlipNoSortModulePathsNoForceGenerate() + { + $this->mockForceGenerate(false); + $this->setMockResolverClass( + false, + null, + null, + null, + null, + null, + null, + null, + null, + [ + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleA' => + [ + 'Magento_ModuleA' + ], + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleBC' => + [ + 'Magento_ModuleB', + 'Magento_ModuleC', + ], + ], + [ + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleCD' => + [ + 'Magento_ModuleC', + 'Magento_ModuleD' + ], + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleE' => + [ + 'Magento_ModuleE' + ], + ], + [ + 'some' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'example' => ['Magento_Example'], + 'other' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'sample' => ['Magento_Sample'], + ] + ); + + $resolver = ModuleResolver::getInstance(); + $this->setMockResolverProperties( + $resolver, + null, + [ + 0 => 'Magento_ModuleB', + 1 => 'Magento_ModuleC', + 2 => 'Magento_ModuleE', + 3 => 'Magento_Example', + 4 => 'Magento_Otherexample' + ] + ); + + $this->assertEquals( + [ + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleE', + 'some' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'example', + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleBC' + ], + $resolver->getModulesPath() + ); + } + /** * Validate mergeModulePaths() and flipAndSortModulePathsArray() * @@ -442,23 +546,27 @@ public function testMergeFlipAndSortModulePathsForceGenerate() null, null, [ - 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'pathA' => + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleA' => [ 'Magento_ModuleA' ], - 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'pathB' => + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleBC' => [ 'Magento_ModuleB', 'Magento_ModuleC', ], ], [ - 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'pathA' => + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleCD' => [ 'Magento_ModuleC', 'Magento_ModuleD' ], - 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'pathB' => + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR + . 'Magento' . DIRECTORY_SEPARATOR . 'ModuleD' => [ 'Magento_ModuleD' ], @@ -481,14 +589,19 @@ public function testMergeFlipAndSortModulePathsForceGenerate() 4 => 'Magento_Otherexample' ] ); + $this->assertEquals( [ 'some' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'example', - 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'pathA', - 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'pathB', - 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'pathA', - 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'pathB', - 'other' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'sample' + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleA', + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleD', + 'other' . DIRECTORY_SEPARATOR . 'path' . DIRECTORY_SEPARATOR . 'sample', + 'composer' . DIRECTORY_SEPARATOR . 'json' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleBC', + 'composer' . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'Magento' . DIRECTORY_SEPARATOR + . 'ModuleCD' ], $resolver->getModulesPath() ); @@ -592,12 +705,12 @@ public function testApplyCustomModuleMethods() } /** - * Validate blacklisted modules are removed + * Validate blocklisted modules are removed * Module paths are sorted according to module name in alphabetically ascending order * * @throws \Exception */ - public function testGetModulePathsBlacklist() + public function testGetModulePathsBlocklist() { $this->setMockResolverClass( false, @@ -833,10 +946,10 @@ private function setMockResolverClass( * @param ModuleResolver $instance * @param array $mockPaths * @param array $mockModules - * @param array $mockBlacklist + * @param array $mockBlocklist * @throws \Exception */ - private function setMockResolverProperties($instance, $mockPaths = null, $mockModules = null, $mockBlacklist = []) + private function setMockResolverProperties($instance, $mockPaths = null, $mockModules = null, $mockBlocklist = []) { $property = new \ReflectionProperty(ModuleResolver::class, 'enabledModulePaths'); $property->setAccessible(true); @@ -846,9 +959,9 @@ private function setMockResolverProperties($instance, $mockPaths = null, $mockMo $property->setAccessible(true); $property->setValue($instance, $mockModules); - $property = new \ReflectionProperty(ModuleResolver::class, 'moduleBlacklist'); + $property = new \ReflectionProperty(ModuleResolver::class, 'moduleBlocklist'); $property->setAccessible(true); - $property->setValue($instance, $mockBlacklist); + $property->setValue($instance, $mockBlocklist); } /** @@ -874,7 +987,7 @@ private function mockForceGenerate($forceGenerate) * After method functionality * @return void */ - protected function tearDown() + protected function tearDown(): void { // re set env if (!isset($_ENV['MAGENTO_ADMIN_USERNAME'])) { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/FilePathFormatterTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/FilePathFormatterTest.php index bac14113d..1bad633e2 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/FilePathFormatterTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/FilePathFormatterTest.php @@ -3,10 +3,10 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Util\Path; +namespace tests\unit\Magento\FunctionalTestFramework\Util\Path; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; class FilePathFormatterTest extends MagentoTestCase diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/UrlFormatterTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/UrlFormatterTest.php index c66c9558c..48fc9f337 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/UrlFormatterTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Path/UrlFormatterTest.php @@ -3,9 +3,9 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Util\Path; +namespace tests\unit\Magento\FunctionalTestFramework\Util\Path; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Sorter/ParallelGroupSorterTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Sorter/ParallelGroupSorterTest.php index 997bf0c3e..0b274f87e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Sorter/ParallelGroupSorterTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Sorter/ParallelGroupSorterTest.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Util\Sorter; +namespace tests\unit\Magento\FunctionalTestFramework\Util\Sorter; use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler; @@ -11,7 +11,7 @@ use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; use Magento\FunctionalTestingFramework\Util\Sorter\ParallelGroupSorter; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class ParallelGroupSorterTest extends MagentoTestCase { @@ -101,8 +101,8 @@ public function testSortWithSuites() $this->assertCount(5, $actualResult); $expectedResults = [ - 1 => ['mockSuite1_0'], - 2 => ['mockSuite1_1'], + 1 => ['mockSuite1_0_G'], + 2 => ['mockSuite1_1_G'], 3 => ['test3'], 4 => ['test2','test5', 'test4'], 5 => ['test1'], diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php index e11b0f9b2..46bc6e346 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Tests\unit\Magento\FunctionalTestFramework\Test\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\Util; use AspectMock\Test as AspectMock; @@ -12,7 +12,7 @@ use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Objects\TestHookObject; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Util\TestGenerator; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; @@ -23,7 +23,7 @@ class TestGeneratorTest extends MagentoTestCase * * @return void */ - public function tearDown() + public function tearDown(): void { AspectMock::clean(); } @@ -70,8 +70,8 @@ public function testSkippedNoGeneration() $testGeneratorObject = TestGenerator::getInstance("", ["sampleTest" => $testObject]); $output = $testGeneratorObject->assembleTestPhp($testObject); - $this->assertContains('This test is skipped', $output); - $this->assertNotContains($actionInput, $output); + $this->assertStringContainsString('This test is skipped', $output); + $this->assertStringNotContainsString($actionInput, $output); } /** @@ -106,9 +106,9 @@ public function testAllowSkipped() $testGeneratorObject = TestGenerator::getInstance("", ["sampleTest" => $testObject]); $output = $testGeneratorObject->assembleTestPhp($testObject); - $this->assertNotContains('This test is skipped', $output); - $this->assertContains($actionInput, $output); - $this->assertContains($beforeActionInput, $output); + $this->assertStringNotContainsString('This test is skipped', $output); + $this->assertStringContainsString($actionInput, $output); + $this->assertStringContainsString($beforeActionInput, $output); } /** diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/DuplicateNodeValidationUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/DuplicateNodeValidationUtilTest.php index 5dba1cb8b..db117c6b6 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/DuplicateNodeValidationUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/DuplicateNodeValidationUtilTest.php @@ -4,13 +4,11 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Util\Validation; use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; -use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Util\Validation\DuplicateNodeValidationUtil; -use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class DuplicateNodeValidationUtilTest extends MagentoTestCase { diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/NameValidationUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/NameValidationUtilTest.php index 28d75b1ad..d43eb5282 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/NameValidationUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/Validation/NameValidationUtilTest.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\Test\Util; +namespace tests\unit\Magento\FunctionalTestFramework\Util\Validation; use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; -use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use tests\unit\Util\MagentoTestCase; class NameValidationUtilTest extends MagentoTestCase { @@ -17,7 +17,7 @@ class NameValidationUtilTest extends MagentoTestCase */ public function testCurlyBracesInTestName() { - $this->validateBlacklistedTestName("{{curlyBraces}}"); + $this->validateBlocklistedTestName("{{curlyBraces}}"); } /** @@ -25,7 +25,7 @@ public function testCurlyBracesInTestName() */ public function testQuotesInTestName() { - $this->validateBlacklistedTestName("\"quotes\""); + $this->validateBlocklistedTestName("\"quotes\""); } /** @@ -33,7 +33,7 @@ public function testQuotesInTestName() */ public function testSingleQuotesInTestName() { - $this->validateBlacklistedTestName("'singleQuotes'"); + $this->validateBlocklistedTestName("'singleQuotes'"); } /** @@ -41,7 +41,7 @@ public function testSingleQuotesInTestName() */ public function testParenthesesInTestName() { - $this->validateBlacklistedTestName("(parenthesis)"); + $this->validateBlocklistedTestName("(parenthesis)"); } /** @@ -49,7 +49,7 @@ public function testParenthesesInTestName() */ public function testDollarSignInTestName() { - $this->validateBlacklistedTestName("\$dollarSign\$"); + $this->validateBlocklistedTestName("\$dollarSign\$"); } /** @@ -57,7 +57,7 @@ public function testDollarSignInTestName() */ public function testSpacesInTestName() { - $this->validateBlacklistedTestName("Test Name With Spaces"); + $this->validateBlocklistedTestName("Test Name With Spaces"); } /** @@ -66,7 +66,7 @@ public function testSpacesInTestName() * @param string $testName * @return void */ - private function validateBlacklistedTestName($testName) + private function validateBlocklistedTestName($testName) { $this->expectException(XmlException::class); NameValidationUtil::validateName($testName, "Test"); diff --git a/dev/tests/unit/Util/MagentoTestCase.php b/dev/tests/unit/Util/MagentoTestCase.php index 6a4e5d35b..7760acfc6 100644 --- a/dev/tests/unit/Util/MagentoTestCase.php +++ b/dev/tests/unit/Util/MagentoTestCase.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\Util; +namespace tests\unit\Util; use AspectMock\Test as AspectMock; use PHPUnit\Framework\TestCase; @@ -14,7 +14,7 @@ */ class MagentoTestCase extends TestCase { - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { if (!self::fileExists(DOCS_OUTPUT_DIR)) { mkdir(DOCS_OUTPUT_DIR, 0755, true); @@ -26,7 +26,7 @@ public static function setUpBeforeClass() * Teardown for removing AspectMock Double References * @return void */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { AspectMock::clean(); array_map('unlink', glob(DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . "*")); diff --git a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt index 23e0f0b69..d6640846f 100644 --- a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt +++ b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupContainsStepKeyInArgText.xml
") */ class ActionGroupContainsStepKeyInArgTextCest { diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt index da3d84daf..352af3a2b 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertAfter.xml
") */ class ActionGroupMergedViaInsertAfterCest { diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt index 22e8148d9..009109146 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertBefore.xml
") */ class ActionGroupMergedViaInsertBeforeCest { diff --git a/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt b/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt deleted file mode 100644 index efd5a8cb5..000000000 --- a/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt +++ /dev/null @@ -1,35 +0,0 @@ -Test filesverification/TestModule/Test/ActionGroupTest.xml
") - */ -class ActionGroupSkipReadinessCest -{ - /** - * @Features({"TestModule"}) - * @Parameter(name = "AcceptanceTester", value="$I") - * @param AcceptanceTester $I - * @return void - * @throws \Exception - */ - public function ActionGroupSkipReadiness(AcceptanceTester $I) - { - $I->comment("Entering Action Group actionGroupWithSkipReadinessActions (skipReadinessActionGroup)"); - $I->skipReadinessCheck(true); - $I->comment("ActionGroupSkipReadiness"); - $I->skipReadinessCheck(false); - $I->comment("Exiting Action Group actionGroupWithSkipReadinessActions (skipReadinessActionGroup)"); - } -} diff --git a/dev/tests/verification/Resources/ActionGroupToExtend.txt b/dev/tests/verification/Resources/ActionGroupToExtend.txt index 29d08c0b6..bbb9efa0f 100644 --- a/dev/tests/verification/Resources/ActionGroupToExtend.txt +++ b/dev/tests/verification/Resources/ActionGroupToExtend.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupToExtend.xml
") */ class ActionGroupToExtendCest { diff --git a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt index b64822cf6..cbddc5f4d 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupUsingCreateData.xml
") */ class ActionGroupUsingCreateDataCest { diff --git a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt index 5eb67f577..0cfd7f84d 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupUsingNestedArgument.xml
") */ class ActionGroupUsingNestedArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt index bb6404315..b60a4da5f 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataOverrideTest.xml
") */ class ActionGroupWithDataOverrideTestCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt index 6b22f83e0..5f19cdc37 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataTest.xml
") */ class ActionGroupWithDataTestCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt index ca5f72cc0..65339e970 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Default Argument Value and Hardcoded Value in Param") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithDefaultArgumentAndStringSelectorParam.xml
") */ class ActionGroupWithDefaultArgumentAndStringSelectorParamCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt index f3ad492b0..e8cedee97 100644 --- a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Passed Argument Value and Multiple Argument Values in Param") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.xml
") */ class ActionGroupWithMultipleParameterSelectorsFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt index 0f69c40e8..e5b9717c2 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With No Argument") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithNoArguments.xml
") */ class ActionGroupWithNoArgumentsCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt index 533e14b9d..c0bde006d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithNoDefaultTest.xml
") */ class ActionGroupWithNoDefaultTestCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt index acc6aa58a..812285111 100644 --- a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt +++ b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementWithHyphen.xml
") */ class ActionGroupWithParameterizedElementWithHyphenCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt index ac20299a8..6c0c3fd0f 100644 --- a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementsWithStepKeyReferences.xml
") */ class ActionGroupWithParameterizedElementsWithStepKeyReferencesCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt index e816da90b..6614a320d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Passed Argument Value and Hardcoded Value in Param") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithPassedArgumentAndStringSelectorParam.xml
") */ class ActionGroupWithPassedArgumentAndStringSelectorParamCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt index 7d0bb58e9..c1905ff39 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithPersistedData.xml
") */ class ActionGroupWithPersistedDataCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt index f629f32f1..b3dcc585f 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithSectionAndDataAsArguments.xml
") */ class ActionGroupWithSectionAndDataAsArgumentsCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt index 10206867a..6d540cb95 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Simple Data Usage From Default Argument") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromDefaultArgument.xml
") */ class ActionGroupWithSimpleDataUsageFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt index 54aec35a7..826671a63 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Simple Data Usage From Passed Argument") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromPassedArgument.xml
") */ class ActionGroupWithSimpleDataUsageFromPassedArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt index c23b99cab..5e64aded3 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Default Argument Value and Argument Value in Param") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromDefaultArgument.xml
") */ class ActionGroupWithSingleParameterSelectorFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt index 4a0932b99..e71a8a716 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Passed Argument Value and Argument Value in Param") - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromPassedArgument.xml
") */ class ActionGroupWithSingleParameterSelectorFromPassedArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index 8098142fd..7d8fae946 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ActionGroupWithStepKeyReferences.xml
") */ class ActionGroupWithStepKeyReferencesCest { @@ -42,7 +42,7 @@ class ActionGroupWithStepKeyReferencesCest $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); $action5ActionGroup = $date->format("H:i:s"); - $action6ActionGroup = $I->formatMoney($action6ActionGroup); // stepKey: action6ActionGroup + $action6ActionGroup = $I->formatCurrency($action6ActionGroup, "en_CA", "USD"); // stepKey: action6ActionGroup $I->deleteEntity("{$action7ActionGroupActionGroup}", "test"); // stepKey: action7ActionGroup $I->getEntity("action8ActionGroup", "test", "{$action8}", [], null); // stepKey: action8ActionGroup $I->updateEntity("1", "test", "{$action9}",[]); // stepKey: action9ActionGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt index a8f80eae6..18a205544 100644 --- a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithTopLevelPersistedData.xml
") */ class ActionGroupWithTopLevelPersistedDataCest { diff --git a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt index e45207249..4bf9332b7 100644 --- a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt +++ b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/ArgumentWithSameNameAsElement.xml
") */ class ArgumentWithSameNameAsElementCest { diff --git a/dev/tests/verification/Resources/AssertTest.txt b/dev/tests/verification/Resources/AssertTest.txt index c0cf932ae..d2d470139 100644 --- a/dev/tests/verification/Resources/AssertTest.txt +++ b/dev/tests/verification/Resources/AssertTest.txt @@ -43,8 +43,9 @@ class AssertTestCest $I->comment("asserts without variable replacement"); $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKey $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKey - $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubset $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertContains + $I->assertStringContainsString("apple", "apple", "pass"); // stepKey: assertStringContainsString + $I->assertStringContainsStringIgnoringCase("Banana", "banana", "pass"); // stepKey: assertStringContainsStringIgnoringCase $I->assertCount(2, ['a', 'b'], "pass"); // stepKey: assertCount $I->assertEmpty([], "pass"); // stepKey: assertEmpty $I->assertEquals($text, "Copyright © 2013-2017 Magento, Inc. All rights reserved.", "pass"); // stepKey: assertEquals1 @@ -56,17 +57,15 @@ class AssertTestCest $I->assertGreaterOrEquals(2, 5, "pass"); // stepKey: assertGreaterOrEquals $I->assertGreaterThan(2, 5, "pass"); // stepKey: assertGreaterthan $I->assertGreaterThanOrEqual(2, 5, "pass"); // stepKey: assertGreaterThanOrEqual - $I->assertInternalType("string", "xyz", "pass"); // stepKey: assertInternalType1 - $I->assertInternalType("int", 21, "pass"); // stepKey: assertInternalType2 - $I->assertInternalType("string", $text, "pass"); // stepKey: assertInternalType3 $I->assertLessOrEquals(5, 2, "pass"); // stepKey: assertLessOrEquals $I->assertLessThan(5, 2, "pass"); // stepKey: assertLessThan $I->assertLessThanOrEqual(5, 2, "pass"); // stepKey: assertLessThanOrEquals - $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertNotContains1 - $I->assertNotContains("bc", $text, "pass"); // stepKey: assertNotContains2 + $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertNotContains + $I->assertStringNotContainsString("apple", "banana", "pass"); // stepKey: assertStringNotContainsString + $I->assertStringNotContainsStringIgnoringCase("apple", "banana", "pass"); // stepKey: assertStringNotContainsStringIgnoringCase $I->assertNotEmpty([1, 2], "pass"); // stepKey: assertNotEmpty1 $I->assertNotEmpty($text, "pass"); // stepKey: assertNotEmpty2 - $I->assertNotEquals(2, 5, "pass", 0); // stepKey: assertNotEquals + $I->assertNotEquals(2, 5, "pass"); // stepKey: assertNotEquals $I->assertNotNull("abc", "pass"); // stepKey: assertNotNull1 $I->assertNotNull($text, "pass"); // stepKey: assertNotNull2 $I->assertNotRegExp("/foo/", "bar", "pass"); // stepKey: assertNotRegExp @@ -80,7 +79,6 @@ class AssertTestCest $I->comment("asserts backward compatible"); $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKeyBackwardCompatible $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKeyBackwardCompatible - $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubsetBackwardCompatible $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertContainsBackwardCompatible $I->assertCount(2, ['a', 'b'], "pass"); // stepKey: assertCountBackwardCompatible $I->assertEmpty([], "pass"); // stepKey: assertEmptyBackwardCompatible @@ -92,9 +90,6 @@ class AssertTestCest $I->assertGreaterOrEquals(2, 5, "pass"); // stepKey: assertGreaterOrEqualsBackwardCompatible $I->assertGreaterThan(2, 5, "pass"); // stepKey: assertGreaterThanBackwardCompatible $I->assertGreaterThanOrEqual(2, 5, "pass"); // stepKey: assertGreaterThanOrEqualBackwardCompatible - $I->assertInternalType("string", "xyz", "pass"); // stepKey: assertInternalType1BackwardCompatible - $I->assertInternalType("int", 21, "pass"); // stepKey: assertInternalType2BackwardCompatible - $I->assertInternalType("string", $text, "pass"); // stepKey: assertInternalType3BackwardCompatible $I->assertLessOrEquals(5, 2, "pass"); // stepKey: assertLessOrEqualBackwardCompatibles $I->assertLessThan(5, 2, "pass"); // stepKey: assertLessThanBackwardCompatible $I->assertLessThanOrEqual(5, 2, "pass"); // stepKey: assertLessThanOrEqualBackwardCompatible @@ -102,7 +97,7 @@ class AssertTestCest $I->assertNotContains("bc", $text, "pass"); // stepKey: assertNotContains2BackwardCompatible $I->assertNotEmpty([1, 2], "pass"); // stepKey: assertNotEmpty1BackwardCompatible $I->assertNotEmpty($text, "pass"); // stepKey: assertNotEmpty2BackwardCompatible - $I->assertNotEquals(2, 5, "pass", 0); // stepKey: assertNotEqualsBackwardCompatible + $I->assertNotEquals(2, 5, "pass"); // stepKey: assertNotEqualsBackwardCompatible $I->assertNotNull("abc", "pass"); // stepKey: assertNotNull1BackwardCompatible $I->assertNotNull($text, "pass"); // stepKey: assertNotNull2BackwardCompatible $I->assertNotRegExp("/foo/", "bar", "pass"); // stepKey: assertNotRegExpBackwardCompatible @@ -126,8 +121,6 @@ class AssertTestCest $I->assertEquals($I->retrieveEntityField('createData1', 'lastname', 'test'), $I->retrieveEntityField('createData1', 'lastname', 'test'), "pass"); // stepKey: assert5 $I->comment("array type that use created data"); $I->comment("array type that use created data"); - $I->assertArraySubset([$I->retrieveEntityField('createData1', 'lastname', 'test'), $I->retrieveEntityField('createData1', 'firstname', 'test')], [$I->retrieveEntityField('createData1', 'lastname', 'test'), $I->retrieveEntityField('createData1', 'firstname', 'test'), "1"], "pass"); // stepKey: assert9 - $I->assertArraySubset([$I->retrieveEntityField('createData2', 'firstname', 'test'), $I->retrieveEntityField('createData2', 'lastname', 'test')], [$I->retrieveEntityField('createData2', 'firstname', 'test'), $I->retrieveEntityField('createData2', 'lastname', 'test'), "1"], "pass"); // stepKey: assert10 $I->assertArrayHasKey("lastname", ['lastname' => $I->retrieveEntityField('createData1', 'lastname', 'test'), 'firstname' => $I->retrieveEntityField('createData1', 'firstname', 'test')], "pass"); // stepKey: assert3 $I->assertArrayHasKey("lastname", ['lastname' => $I->retrieveEntityField('createData2', 'lastname', 'test'), 'firstname' => $I->retrieveEntityField('createData2', 'firstname', 'test')], "pass"); // stepKey: assert4 $I->comment("this section can only be generated and cannot run"); @@ -152,5 +145,11 @@ class AssertTestCest $I->assertElementContainsAttribute("#username", "value", $I->retrieveEntityField('createData1', 'firstname', 'test')); // stepKey: assertElementContainsAttribute8 $I->comment("assert entity resolution"); $I->assertEquals("John", "Doe", "pass"); // stepKey: assertEqualsEntity + $I->assertEqualsWithDelta(10.0000, 10.0000, 1, "pass"); // stepKey: a1 + $I->assertNotEqualsWithDelta(10.0000, 12.0000, 1, "pass"); // stepKey: a2 + $I->assertEqualsCanonicalizing(["4", "2", "1", "3"], ["1", "2", "3", "4"], "pass"); // stepKey: a3 + $I->assertNotEqualsCanonicalizing(["5", "8", "7", "9"], ["1", "2", "3", "4"], "pass"); // stepKey: a4 + $I->assertEqualsIgnoringCase("Cat", "cat", "pass"); // stepKey: a5 + $I->assertNotEqualsIgnoringCase("Cat", "Dog", "pass"); // stepKey: a6 } } diff --git a/dev/tests/verification/Resources/BasicActionGroupTest.txt b/dev/tests/verification/Resources/BasicActionGroupTest.txt index 7d8c40f0b..95c31b813 100644 --- a/dev/tests/verification/Resources/BasicActionGroupTest.txt +++ b/dev/tests/verification/Resources/BasicActionGroupTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/BasicActionGroupTest.xml
") */ class BasicActionGroupTestCest { diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index 072b58261..2a67888f6 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: A Functional Cest") * @group functional - * @Description("

Deprecated Notice(s):

  • DEPRECATED ACTION in Test: at step performOnKey1 'performOn' is DEPRECATED and will be removed in MFTF 3.0.0.

Test files

verification/TestModule/Test/BasicFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml
") */ class BasicFunctionalTestCest { @@ -112,6 +112,7 @@ class BasicFunctionalTestCest $date->setTimezone(new \DateTimeZone("UTC")); $generateDateKey2 = $date->format("H:i:s"); + $getOtp = $I->getOTP(); // stepKey: getOtp $grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput"); // stepKey: grabAttributeFromKey1 $grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']); // stepKey: grabCookieKey1 $grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl"); // stepKey: grabFromCurrentUrlKey1 @@ -138,8 +139,7 @@ class BasicFunctionalTestCest $I->moveForward(); // stepKey: moveForwardKey1 $I->moveMouseOver(".functionalTestSelector"); // stepKey: moveMouseOverKey1 $I->openNewTab(); // stepKey: openNewTabKey1 - $I->pauseExecution(); // stepKey: pauseExecutionKey1 - $I->performOn("#selector", function(\WebDriverElement $el) {return $el->isDisplayed();}, 10); // stepKey: performOnKey1 + $I->pause(); // stepKey: pauseKey1 $I->pressKey("#page", "a"); // stepKey: pressKey1 $I->pressKey("#page", ['ctrl', 'a'],'new'); // stepKey: pressKey2 $I->pressKey("#page", ['shift', '111'],'1','x'); // stepKey: pressKey3 diff --git a/dev/tests/verification/Resources/BasicMergeTest.txt b/dev/tests/verification/Resources/BasicMergeTest.txt index 8171cd892..8842d3d99 100644 --- a/dev/tests/verification/Resources/BasicMergeTest.txt +++ b/dev/tests/verification/Resources/BasicMergeTest.txt @@ -16,7 +16,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; * @Title("[NO TESTCASEID]: BasicMergeTest") * @group functional * @group mergeTest - * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest.xml
verification/TestModuleMerged/Test/MergeFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest/BasicMergeTest.xml
verification/TestModuleMerged/Test/MergeFunctionalTest/BasicMergeTest.xml
") */ class BasicMergeTestCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt index 86d81f848..72e924954 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestAddHooks") * @group Parent - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestAddHooks.xml
") */ class ChildExtendedTestAddHooksCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt index 08345bd86..7900ca9a0 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestMerging") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestMerging.xml
") */ class ChildExtendedTestMergingCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt b/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt index 4cca6ec06..be775aba9 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestNoParent") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestNoParent.xml
") * @group skip */ class ChildExtendedTestNoParentCest diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt index 370ffe404..d3017e010 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestRemoveAction") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveAction.xml
") */ class ChildExtendedTestRemoveActionCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt index 50b6e030d..0988e5d71 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestRemoveHookAction") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveHookAction.xml
") */ class ChildExtendedTestRemoveHookActionCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt index ce32f6af1..9d0a65a3b 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestReplace") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplace.xml
") */ class ChildExtendedTestReplaceCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt index bbb6c5ef9..c40b46fa0 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestReplaceHook") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplaceHook.xml
") */ class ChildExtendedTestReplaceHookCest { diff --git a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt index 5afd1a6ea..e69de29bb 100644 --- a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt +++ b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt @@ -1,31 +0,0 @@ -Deprecated Notice(s):
  • DEPRECATED ACTION in Test: at step executeInSeleniumStep 'executeInSelenium' is DEPRECATED and will be removed in MFTF 3.0.0.

Test files

verification/TestModule/Test/ExecuteInSeleniumTest.xml
") - */ -class ExecuteInSeleniumTestCest -{ - /** - * @Features({"TestModule"}) - * @Parameter(name = "AcceptanceTester", value="$I") - * @param AcceptanceTester $I - * @return void - * @throws \Exception - */ - public function ExecuteInSeleniumTest(AcceptanceTester $I) - { - $I->executeInSelenium(function ($webdriver) { return "Hello, World!"}); // stepKey: executeInSeleniumStep - } -} diff --git a/dev/tests/verification/Resources/ExtendedActionGroup.txt b/dev/tests/verification/Resources/ExtendedActionGroup.txt index 8996526ba..9ed588df4 100644 --- a/dev/tests/verification/Resources/ExtendedActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedActionGroup.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ExtendedActionGroup.xml
") */ class ExtendedActionGroupCest { diff --git a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt index e4a006c8f..d1f74abe1 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ExtendedChildTestInSuite") * @group ExtendedTestInSuite - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestInSuite.xml
") */ class ExtendedChildTestInSuiteCest { diff --git a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt index 1d5af7d3e..d9f8a72e6 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ExtendedChildTestNotInSuite") - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestNotInSuite.xml
") */ class ExtendedChildTestNotInSuiteCest { diff --git a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt index fde8842e7..b593a9231 100644 --- a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupTest/ExtendedRemoveActionGroup.xml
") */ class ExtendedRemoveActionGroupCest { diff --git a/dev/tests/verification/Resources/ExtendingSkippedTest.txt b/dev/tests/verification/Resources/ExtendingSkippedTest.txt index 93e9b6a60..553131988 100644 --- a/dev/tests/verification/Resources/ExtendingSkippedTest.txt +++ b/dev/tests/verification/Resources/ExtendingSkippedTest.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestSkippedParent") * @group Child - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ExtendingSkippedTest.xml
") */ class ExtendingSkippedTestCest { diff --git a/dev/tests/verification/Resources/SkippedTestNoIssues.txt b/dev/tests/verification/Resources/GroupSkipGenerationTest.txt similarity index 66% rename from dev/tests/verification/Resources/SkippedTestNoIssues.txt rename to dev/tests/verification/Resources/GroupSkipGenerationTest.txt index e8f4726d9..89884df82 100644 --- a/dev/tests/verification/Resources/SkippedTestNoIssues.txt +++ b/dev/tests/verification/Resources/GroupSkipGenerationTest.txt @@ -13,14 +13,14 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Title("[NO TESTCASEID]: skippedNoIssuesTest") - * @Description("

Test files

verification/TestModule/Test/SkippedTest.xml
") + * @Title("[NO TESTCASEID]: GroupSkipGenerationTestTitle") + * @Description("GroupSkipGenerationTestDescription

Test files

verification/TestModule/Test/GroupSkipGenerationTest.xml
") * @group skip */ -class SkippedTestNoIssuesCest +class GroupSkipGenerationTestCest { /** - * @Stories({"skippedNo"}) + * @Stories({"GroupSkipGenerationTestStory"}) * @Severity(level = SeverityLevel::MINOR) * @Features({"TestModule"}) * @Parameter(name = "AcceptanceTester", value="$I") @@ -28,8 +28,7 @@ class SkippedTestNoIssuesCest * @return void * @throws \Exception */ - public function SkippedTestNoIssues(AcceptanceTester $I, \Codeception\Scenario $scenario) + public function GroupSkipGenerationTest(AcceptanceTester $I) { - $scenario->skip("This test is skipped due to the following issues:\nNo issues have been specified."); } } diff --git a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt index a57ca4471..1a94b90a6 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/BasicFunctionalTest.xml
verification/TestModule/Test/MergeFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertAfter.xml
verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertAfter.xml
") */ class MergeMassViaInsertAfterCest { diff --git a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt index 7c6fdc906..12b073bfb 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/BasicFunctionalTest.xml
verification/TestModule/Test/MergeFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertBefore.xml
verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertBefore.xml
") */ class MergeMassViaInsertBeforeCest { diff --git a/dev/tests/verification/Resources/MergeSkip.txt b/dev/tests/verification/Resources/MergeSkip.txt index b2a1b8918..d08f52b56 100644 --- a/dev/tests/verification/Resources/MergeSkip.txt +++ b/dev/tests/verification/Resources/MergeSkip.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest.xml
verification/TestModuleMerged/Test/MergeFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest/MergeSkip.xml
verification/TestModuleMerged/Test/MergeFunctionalTest/MergeSkip.xml
") */ class MergeSkipCest { diff --git a/dev/tests/verification/Resources/MergedActionGroupTest.txt b/dev/tests/verification/Resources/MergedActionGroupTest.txt index a9c740127..c8401874d 100644 --- a/dev/tests/verification/Resources/MergedActionGroupTest.txt +++ b/dev/tests/verification/Resources/MergedActionGroupTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/MergedActionGroupTest.xml
") */ class MergedActionGroupTestCest { diff --git a/dev/tests/verification/Resources/MergedReferencesTest.txt b/dev/tests/verification/Resources/MergedReferencesTest.txt index b3fc29966..74f780aac 100644 --- a/dev/tests/verification/Resources/MergedReferencesTest.txt +++ b/dev/tests/verification/Resources/MergedReferencesTest.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: MergedReferencesTest") * @group functional - * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/MergeFunctionalTest/MergedReferencesTest.xml
") */ class MergedReferencesTestCest { diff --git a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt index 5f1db5081..46673f473 100644 --- a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt +++ b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/MultipleActionGroupsTest.xml
") */ class MultipleActionGroupsTestCest { diff --git a/dev/tests/verification/Resources/ParentExtendedTest.txt b/dev/tests/verification/Resources/ParentExtendedTest.txt index 8c756f010..5606b2ac3 100644 --- a/dev/tests/verification/Resources/ParentExtendedTest.txt +++ b/dev/tests/verification/Resources/ParentExtendedTest.txt @@ -15,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ParentExtendedTest") * @group Parent - * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTest.xml
") */ class ParentExtendedTestCest { diff --git a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt index f6956f5d9..d49b99306 100644 --- a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt +++ b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt @@ -13,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest.xml
") + * @Description("

Test files

verification/TestModule/Test/ActionGroupFunctionalTest/PersistedAndXmlEntityArguments.xml
") */ class PersistedAndXmlEntityArgumentsCest { diff --git a/dev/tests/verification/Resources/SkippedTest.txt b/dev/tests/verification/Resources/SkippedTest.txt index 95783ca66..7dd9ba280 100644 --- a/dev/tests/verification/Resources/SkippedTest.txt +++ b/dev/tests/verification/Resources/SkippedTest.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedTest") - * @Description("

Test files

verification/TestModule/Test/SkippedTest.xml
") + * @Description("

Test files

verification/TestModule/Test/SkippedTest/SkippedTest.xml
") */ class SkippedTestCest { diff --git a/dev/tests/verification/Resources/SkippedTestTwoIssues.txt b/dev/tests/verification/Resources/SkippedTestTwoIssues.txt index 4a801856e..0087ba92d 100644 --- a/dev/tests/verification/Resources/SkippedTestTwoIssues.txt +++ b/dev/tests/verification/Resources/SkippedTestTwoIssues.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedMultipleIssuesTest") - * @Description("

Test files

verification/TestModule/Test/SkippedTest.xml
") + * @Description("

Test files

verification/TestModule/Test/SkippedTest/SkippedTestTwoIssues.xml
") */ class SkippedTestTwoIssuesCest { diff --git a/dev/tests/verification/Resources/SkippedTestWithHooks.txt b/dev/tests/verification/Resources/SkippedTestWithHooks.txt index ad59d48c3..6b2682c49 100644 --- a/dev/tests/verification/Resources/SkippedTestWithHooks.txt +++ b/dev/tests/verification/Resources/SkippedTestWithHooks.txt @@ -14,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedTestWithHooks") - * @Description("

Test files

verification/TestModule/Test/SkippedTest.xml
") + * @Description("

Test files

verification/TestModule/Test/SkippedTest/SkippedTestWithHooks.xml
") */ class SkippedTestWithHooksCest { diff --git a/dev/tests/verification/Resources/functionalSuiteHooks.txt b/dev/tests/verification/Resources/functionalSuiteHooks.txt index 908cff8aa..3b5f6bae0 100644 --- a/dev/tests/verification/Resources/functionalSuiteHooks.txt +++ b/dev/tests/verification/Resources/functionalSuiteHooks.txt @@ -2,8 +2,10 @@ namespace Group; +use Facebook\WebDriver\Remote\RemoteWebDriver; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; /** * Group class is Codeception Extension which is allowed to handle to all internal events. @@ -41,17 +43,15 @@ class functionalSuiteHooks extends \Codeception\GroupObject if ($this->currentTestRun == 1) { print sprintf(self::$HOOK_EXECUTION_INIT, "before"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { - $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - - // close any open sessions if ($webDriver->webDriver != null) { - $webDriver->webDriver->close(); - $webDriver->webDriver = null; + $webDriver->_restart(); + } else { + $webDriver->_initializeSession(); } - - // initialize the webdriver session - $webDriver->_initializeSession(); $webDriver->amOnPage("some.url"); // stepKey: before $createFields['someKey'] = "dataHere"; PersistedObjectHandler::getInstance()->createEntity( @@ -64,16 +64,15 @@ class functionalSuiteHooks extends \Codeception\GroupObject print("Entering Action Group [AC] actionGroupWithTwoArguments"); $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC print("Exiting Action Group [AC] actionGroupWithTwoArguments"); - - // reset configuration and close session - $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig(); - $webDriver->webDriver->close(); - $webDriver->webDriver = null; - } catch (\Exception $exception) { $this->preconditionFailure = $exception->getMessage(); } + // reset configuration and close session + $webDriver->_resetConfig(); + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + print sprintf(self::$HOOK_EXECUTION_END, "before"); } } @@ -89,6 +88,9 @@ class functionalSuiteHooks extends \Codeception\GroupObject if ($this->currentTestRun == $this->testCount) { print sprintf(self::$HOOK_EXECUTION_INIT, "after"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { // Find out if Test in Suite failed, will cause potential failures in suite after $cest = $e->getTest(); @@ -111,16 +113,11 @@ class functionalSuiteHooks extends \Codeception\GroupObject } } } - $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - - // close any open sessions if ($webDriver->webDriver != null) { - $webDriver->webDriver->close(); - $webDriver->webDriver = null; + $webDriver->_restart(); + } else { + $webDriver->_initializeSession(); } - - // initialize the webdriver session - $webDriver->_initializeSession(); $webDriver->amOnPage("some.url"); // stepKey: after $webDriver->deleteEntityByUrl("deleteThis"); // stepKey: delete print("Entering Action Group [AC] actionGroupWithTwoArguments"); @@ -131,7 +128,37 @@ class functionalSuiteHooks extends \Codeception\GroupObject } PersistedObjectHandler::getInstance()->clearSuiteObjects(); + + $this->closeSession($webDriver); + print sprintf(self::$HOOK_EXECUTION_END, "after"); } } + + /** + * Close session method closes current session. + * If config 'close_all_sessions' is set to 'true' all sessions will be closed. + * + * @param MagentoWebDriver $webDriver + * return void + */ + private function closeSession(MagentoWebDriver $webDriver): void + { + $webDriverConfig = $webDriver->_getConfig(); + $webDriver->_closeSession(); + if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") { + $wdHost = sprintf( + '%s://%s:%s%s', + $webDriverConfig['protocol'], + $webDriverConfig['host'], + $webDriverConfig['port'], + $webDriverConfig['path'] + ); + $availableSessions = RemoteWebDriver::getAllSessions($wdHost); + foreach ($availableSessions as $session) { + $remoteWebDriver = RemoteWebDriver::createBySessionID($session['id'], $wdHost); + $remoteWebDriver->quit(); + } + } + } } diff --git a/dev/tests/verification/Resources/functionalSuiteWithComments.txt b/dev/tests/verification/Resources/functionalSuiteWithComments.txt index 0e15b7909..c8523d0c1 100644 --- a/dev/tests/verification/Resources/functionalSuiteWithComments.txt +++ b/dev/tests/verification/Resources/functionalSuiteWithComments.txt @@ -2,8 +2,10 @@ namespace Group; +use Facebook\WebDriver\Remote\RemoteWebDriver; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; /** * Group class is Codeception Extension which is allowed to handle to all internal events. @@ -41,17 +43,15 @@ class functionalSuiteWithComments extends \Codeception\GroupObject if ($this->currentTestRun == 1) { print sprintf(self::$HOOK_EXECUTION_INIT, "before"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { - $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - - // close any open sessions if ($webDriver->webDriver != null) { - $webDriver->webDriver->close(); - $webDriver->webDriver = null; + $webDriver->_restart(); + } else { + $webDriver->_initializeSession(); } - - // initialize the webdriver session - $webDriver->_initializeSession(); print("Comment in Before"); $webDriver->amOnPage("some.url"); // stepKey: before $createFields['someKey'] = "dataHere"; @@ -66,16 +66,15 @@ class functionalSuiteWithComments extends \Codeception\GroupObject print("Entering Action Group [AC] actionGroupWithTwoArguments"); $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC print("Exiting Action Group [AC] actionGroupWithTwoArguments"); - - // reset configuration and close session - $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig(); - $webDriver->webDriver->close(); - $webDriver->webDriver = null; - } catch (\Exception $exception) { $this->preconditionFailure = $exception->getMessage(); } + // reset configuration and close session + $webDriver->_resetConfig(); + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + print sprintf(self::$HOOK_EXECUTION_END, "before"); } } @@ -91,6 +90,9 @@ class functionalSuiteWithComments extends \Codeception\GroupObject if ($this->currentTestRun == $this->testCount) { print sprintf(self::$HOOK_EXECUTION_INIT, "after"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { // Find out if Test in Suite failed, will cause potential failures in suite after $cest = $e->getTest(); @@ -113,23 +115,48 @@ class functionalSuiteWithComments extends \Codeception\GroupObject } } } - $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - - // close any open sessions if ($webDriver->webDriver != null) { - $webDriver->webDriver->close(); - $webDriver->webDriver = null; + $webDriver->_restart(); + } else { + $webDriver->_initializeSession(); } - - // initialize the webdriver session - $webDriver->_initializeSession(); print("afterBlock"); } catch (\Exception $exception) { print $exception->getMessage(); } PersistedObjectHandler::getInstance()->clearSuiteObjects(); + + $this->closeSession($webDriver); + print sprintf(self::$HOOK_EXECUTION_END, "after"); } } + + /** + * Close session method closes current session. + * If config 'close_all_sessions' is set to 'true' all sessions will be closed. + * + * @param MagentoWebDriver $webDriver + * return void + */ + private function closeSession(MagentoWebDriver $webDriver): void + { + $webDriverConfig = $webDriver->_getConfig(); + $webDriver->_closeSession(); + if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") { + $wdHost = sprintf( + '%s://%s:%s%s', + $webDriverConfig['protocol'], + $webDriverConfig['host'], + $webDriverConfig['port'], + $webDriverConfig['path'] + ); + $availableSessions = RemoteWebDriver::getAllSessions($wdHost); + foreach ($availableSessions as $session) { + $remoteWebDriver = RemoteWebDriver::createBySessionID($session['id'], $wdHost); + $remoteWebDriver->quit(); + } + } + } } diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml deleted file mode 100644 index 45ccdbd24..000000000 --- a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{count}} - grabProducts - - - - - - - - - - {{count}} - grabProducts - - - - - - - - - - - - {{otherCount}} - grabProducts - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupContainsStepKeyInArgValueActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupContainsStepKeyInArgValueActionGroup.xml new file mode 100644 index 000000000..afc7f0e04 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupContainsStepKeyInArgValueActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupToExtendActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupToExtendActionGroup.xml new file mode 100644 index 000000000..8e87f46c5 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupToExtendActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + + + + {{count}} + grabProducts + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithCreateDataActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithCreateDataActionGroup.xml new file mode 100644 index 000000000..9f3a11a4f --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithCreateDataActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithDefaultArgumentAndStringSelectorParamActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithDefaultArgumentAndStringSelectorParamActionGroup.xml new file mode 100644 index 000000000..6a397120c --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithDefaultArgumentAndStringSelectorParamActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithEntityUsageActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithEntityUsageActionGroup.xml new file mode 100644 index 000000000..d85c5f661 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithEntityUsageActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithMultipleParameterSelectorsFromArgumentActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithMultipleParameterSelectorsFromArgumentActionGroup.xml new file mode 100644 index 000000000..44561f91d --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithMultipleParameterSelectorsFromArgumentActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithNestedArgumentActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithNestedArgumentActionGroup.xml new file mode 100644 index 000000000..2e767481d --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithNestedArgumentActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + + + + {{count}} + grabProducts + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSectionAndDataActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSectionAndDataActionGroup.xml new file mode 100644 index 000000000..4917a4545 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSectionAndDataActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSingleParameterSelectorFromArgumentActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSingleParameterSelectorFromArgumentActionGroup.xml new file mode 100644 index 000000000..1e6c2de78 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithSingleParameterSelectorFromArgumentActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithStringUsageActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithStringUsageActionGroup.xml new file mode 100644 index 000000000..0ee47f9f2 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithStringUsageActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithTwoArgumentsActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithTwoArgumentsActionGroup.xml new file mode 100644 index 000000000..d54143e4c --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithTwoArgumentsActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithoutArgumentsActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithoutArgumentsActionGroup.xml new file mode 100644 index 000000000..428ca1a40 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ActionGroupWithoutArgumentsActionGroup.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendBasicActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendBasicActionGroup.xml new file mode 100644 index 000000000..bda82ebad --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendBasicActionGroup.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendRemoveTestActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendRemoveTestActionGroup.xml new file mode 100644 index 000000000..f4f8e5647 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendRemoveTestActionGroup.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendTestActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendTestActionGroup.xml new file mode 100644 index 000000000..0b9bf6041 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup/ExtendTestActionGroup.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + {{otherCount}} + grabProducts + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml index 8f0341c09..f447ce76e 100644 --- a/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml @@ -6,7 +6,7 @@ */ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml deleted file mode 100644 index 30cba3848..000000000 --- a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/ActionGroupWithParametrizedSelectorsActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/ActionGroupWithParametrizedSelectorsActionGroup.xml new file mode 100644 index 000000000..cfa4e1343 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/ActionGroupWithParametrizedSelectorsActionGroup.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionActionGroupWithStepKeyReferencesActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionActionGroupWithStepKeyReferencesActionGroup.xml new file mode 100644 index 000000000..516c2895b --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionActionGroupWithStepKeyReferencesActionGroup.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroup.xml new file mode 100644 index 000000000..1da276f10 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroup.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml new file mode 100644 index 000000000..0868a28e2 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml new file mode 100644 index 000000000..e9b7f52c2 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml new file mode 100644 index 000000000..f3fabe074 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupNoDefaultActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupNoDefaultActionGroup.xml new file mode 100644 index 000000000..5313178f9 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupNoDefaultActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithDataActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithDataActionGroup.xml new file mode 100644 index 000000000..6948f8ffd --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithDataActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithTrickyArgumentActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithTrickyArgumentActionGroup.xml new file mode 100644 index 000000000..cad553151 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithTrickyArgumentActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithXmlAndPersistedDataActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithXmlAndPersistedDataActionGroup.xml new file mode 100644 index 000000000..949d5b95d --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/FunctionalActionGroupWithXmlAndPersistedDataActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/SectionArgumentWithParameterizedSelectorActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/SectionArgumentWithParameterizedSelectorActionGroup.xml new file mode 100644 index 000000000..d82b6d64a --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/FunctionalActionGroup/SectionArgumentWithParameterizedSelectorActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml deleted file mode 100644 index 7d8585772..000000000 --- a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml new file mode 100644 index 000000000..cca3c1b24 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeAfterActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml new file mode 100644 index 000000000..d9a5c3f55 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMassMergeBeforeActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml new file mode 100644 index 000000000..dd451f511 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/MergeFunctionalActionGroup/FunctionalActionGroupForMergeActionGroup.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup.xml deleted file mode 100644 index f98fd2406..000000000 --- a/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - {{arg1}} - - - {{arg2}} - - - {{arg3}} - - - - - - - - - - - - - - $createData1.field$ - $createData2.field$ - - - \ No newline at end of file diff --git a/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceAppendingActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceAppendingActionGroup.xml new file mode 100644 index 000000000..e5ee7ce4f --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceAppendingActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceSelfReferenceActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceSelfReferenceActionGroup.xml new file mode 100644 index 000000000..091a7a6e3 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/DataPersistenceSelfReferenceActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + + $createData1.field$ + $createData2.field$ + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/PersistenceActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/PersistenceActionGroup.xml new file mode 100644 index 000000000..c164e13c8 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/PersistenceActionGroup/PersistenceActionGroup.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + {{arg1}} + + + {{arg2}} + + + {{arg3}} + + + diff --git a/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml index a46dab939..9f1a429f7 100644 --- a/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml @@ -6,7 +6,7 @@ */ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> diff --git a/dev/tests/verification/TestModule/ActionGroup/XmlDuplicateActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/XmlDuplicateActionGroup.xml index fcc22acca..6eefdaf51 100644 --- a/dev/tests/verification/TestModule/ActionGroup/XmlDuplicateActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/XmlDuplicateActionGroup.xml @@ -6,7 +6,7 @@ */ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> @@ -78,14 +78,12 @@ - - - - + + @@ -124,10 +122,8 @@ - - - - + + diff --git a/dev/tests/verification/TestModule/Data/DeprecatedData.xml b/dev/tests/verification/TestModule/Data/DeprecatedData.xml index 060752419..7d5f1e200 100644 --- a/dev/tests/verification/TestModule/Data/DeprecatedData.xml +++ b/dev/tests/verification/TestModule/Data/DeprecatedData.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> deprecated diff --git a/dev/tests/verification/TestModule/Data/ExtendedData.xml b/dev/tests/verification/TestModule/Data/ExtendedData.xml index 74fa921d0..c26715eec 100644 --- a/dev/tests/verification/TestModule/Data/ExtendedData.xml +++ b/dev/tests/verification/TestModule/Data/ExtendedData.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> name prename diff --git a/dev/tests/verification/TestModule/Data/ParameterArrayData.xml b/dev/tests/verification/TestModule/Data/ParameterArrayData.xml index 3b45aedf7..38f6a2439 100644 --- a/dev/tests/verification/TestModule/Data/ParameterArrayData.xml +++ b/dev/tests/verification/TestModule/Data/ParameterArrayData.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> name prename diff --git a/dev/tests/verification/TestModule/Data/PersistedReplacementData.xml b/dev/tests/verification/TestModule/Data/PersistedReplacementData.xml index a8a747857..514b5eec6 100644 --- a/dev/tests/verification/TestModule/Data/PersistedReplacementData.xml +++ b/dev/tests/verification/TestModule/Data/PersistedReplacementData.xml @@ -8,7 +8,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> John Doe diff --git a/dev/tests/verification/TestModule/Data/ReplacementData.xml b/dev/tests/verification/TestModule/Data/ReplacementData.xml index 4d91fa84e..133fe8f6e 100644 --- a/dev/tests/verification/TestModule/Data/ReplacementData.xml +++ b/dev/tests/verification/TestModule/Data/ReplacementData.xml @@ -8,7 +8,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> John Doe diff --git a/dev/tests/verification/TestModule/Page/DeprecatedPage.xml b/dev/tests/verification/TestModule/Page/DeprecatedPage.xml index 316b8b1d7..e758c3f07 100644 --- a/dev/tests/verification/TestModule/Page/DeprecatedPage.xml +++ b/dev/tests/verification/TestModule/Page/DeprecatedPage.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
diff --git a/dev/tests/verification/TestModule/Page/SamplePage.xml b/dev/tests/verification/TestModule/Page/SamplePage.xml deleted file mode 100644 index 59efded6e..000000000 --- a/dev/tests/verification/TestModule/Page/SamplePage.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - -
- - -
- - -
- - -
- - -
- - -
- - -
- - diff --git a/dev/tests/verification/TestModule/Page/SamplePage/AdminOneParamPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/AdminOneParamPage.xml new file mode 100644 index 000000000..de51a11fa --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/AdminOneParamPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/AdminPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/AdminPage.xml new file mode 100644 index 000000000..12f554da6 --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/AdminPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/ExternalPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/ExternalPage.xml new file mode 100644 index 000000000..5c3e131e4 --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/ExternalPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/NoParamPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/NoParamPage.xml new file mode 100644 index 000000000..2a9b0efc5 --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/NoParamPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/OneParamPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/OneParamPage.xml new file mode 100644 index 000000000..2986ebed9 --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/OneParamPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/SamplePage.xml b/dev/tests/verification/TestModule/Page/SamplePage/SamplePage.xml new file mode 100644 index 000000000..7baa9858e --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/SamplePage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Page/SamplePage/TwoParamPage.xml b/dev/tests/verification/TestModule/Page/SamplePage/TwoParamPage.xml new file mode 100644 index 000000000..4ab1f632a --- /dev/null +++ b/dev/tests/verification/TestModule/Page/SamplePage/TwoParamPage.xml @@ -0,0 +1,13 @@ + + + + +
+ + diff --git a/dev/tests/verification/TestModule/Section/DeprecatedSection.xml b/dev/tests/verification/TestModule/Section/DeprecatedSection.xml index a9ed20d98..954889786 100644 --- a/dev/tests/verification/TestModule/Section/DeprecatedSection.xml +++ b/dev/tests/verification/TestModule/Section/DeprecatedSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/dev/tests/verification/TestModule/Section/LocatorFunctionSection.xml b/dev/tests/verification/TestModule/Section/LocatorFunctionSection.xml index 28612e1b3..cc986d969 100644 --- a/dev/tests/verification/TestModule/Section/LocatorFunctionSection.xml +++ b/dev/tests/verification/TestModule/Section/LocatorFunctionSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/dev/tests/verification/TestModule/Section/SampleSection.xml b/dev/tests/verification/TestModule/Section/SampleSection.xml index 920ee6e1b..088d3e344 100644 --- a/dev/tests/verification/TestModule/Section/SampleSection.xml +++ b/dev/tests/verification/TestModule/Section/SampleSection.xml @@ -7,7 +7,7 @@ --> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite1.xml b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite1.xml new file mode 100644 index 000000000..5f78e043e --- /dev/null +++ b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite1.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite2.xml b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite2.xml new file mode 100644 index 000000000..c65cf6cfc --- /dev/null +++ b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuite2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/_suite/functionalSuite.xml b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuiteWithComments.xml similarity index 61% rename from dev/tests/verification/_suite/functionalSuite.xml rename to dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuiteWithComments.xml index cfdaa3557..ffc0e15db 100644 --- a/dev/tests/verification/_suite/functionalSuite.xml +++ b/dev/tests/verification/TestModule/Suite/functionalSuite/functionalSuiteWithComments.xml @@ -6,29 +6,7 @@ */ --> - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/dev/tests/verification/_suite/functionalSuiteExtends.xml b/dev/tests/verification/TestModule/Suite/functionalSuiteExtends.xml similarity index 76% rename from dev/tests/verification/_suite/functionalSuiteExtends.xml rename to dev/tests/verification/TestModule/Suite/functionalSuiteExtends.xml index aac3b51e5..44af78d20 100644 --- a/dev/tests/verification/_suite/functionalSuiteExtends.xml +++ b/dev/tests/verification/TestModule/Suite/functionalSuiteExtends.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/dev/tests/verification/_suite/functionalSuiteHooks.xml b/dev/tests/verification/TestModule/Suite/functionalSuiteHooks.xml similarity index 92% rename from dev/tests/verification/_suite/functionalSuiteHooks.xml rename to dev/tests/verification/TestModule/Suite/functionalSuiteHooks.xml index f86f8c43c..4fc459e7d 100644 --- a/dev/tests/verification/_suite/functionalSuiteHooks.xml +++ b/dev/tests/verification/TestModule/Suite/functionalSuiteHooks.xml @@ -6,7 +6,7 @@ */ --> - + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml deleted file mode 100644 index 8c24794e1..000000000 --- a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest.xml +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertAfter.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertAfter.xml new file mode 100644 index 000000000..0bca36759 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertAfter.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertBefore.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertBefore.xml new file mode 100644 index 000000000..06d9c965d --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupMergedViaInsertBefore.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataOverrideTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataOverrideTest.xml new file mode 100644 index 000000000..e1b72784d --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataOverrideTest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataTest.xml new file mode 100644 index 000000000..379d79a48 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithDataTest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithNoDefaultTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithNoDefaultTest.xml new file mode 100644 index 000000000..d5e77c7e7 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithNoDefaultTest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithPersistedData.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithPersistedData.xml new file mode 100644 index 000000000..bfb8a7cc2 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithPersistedData.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithTopLevelPersistedData.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithTopLevelPersistedData.xml new file mode 100644 index 000000000..a7f2a558b --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ActionGroupWithTopLevelPersistedData.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ArgumentWithSameNameAsElement.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ArgumentWithSameNameAsElement.xml new file mode 100644 index 000000000..e8e994d46 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/ArgumentWithSameNameAsElement.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/BasicActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/BasicActionGroupTest.xml new file mode 100644 index 000000000..0c72b0f19 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/BasicActionGroupTest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MergedActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MergedActionGroupTest.xml new file mode 100644 index 000000000..a5a3a0685 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MergedActionGroupTest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MultipleActionGroupsTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MultipleActionGroupsTest.xml new file mode 100644 index 000000000..c5473b789 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/MultipleActionGroupsTest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/PersistedAndXmlEntityArguments.xml b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/PersistedAndXmlEntityArguments.xml new file mode 100644 index 000000000..defd72174 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupFunctionalTest/PersistedAndXmlEntityArguments.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml deleted file mode 100644 index 5dce96934..000000000 --- a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - </annotations> - <actionGroup ref="actionGroupWithoutArguments" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupWithDefaultArgumentAndStringSelectorParam"> - <annotations> - <severity value="BLOCKER"/> - <title value="Action Group With Default Argument Value and Hardcoded Value in Param"/> - </annotations> - - <actionGroup ref="actionGroupWithDefaultArgumentAndStringSelectorParam" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupWithPassedArgumentAndStringSelectorParam"> - <annotations> - <severity value="BLOCKER"/> - <title value="Action Group With Passed Argument Value and Hardcoded Value in Param"/> - </annotations> - - <actionGroup ref="actionGroupWithDefaultArgumentAndStringSelectorParam" stepKey="actionGroup"> - <argument name="someArgument" value="UniquePerson"/> - </actionGroup> - </test> - - <test name="ActionGroupWithSingleParameterSelectorFromDefaultArgument"> - <annotations> - <severity value="BLOCKER"/> - <title value="Action Group With Default Argument Value and Argument Value in Param"/> - </annotations> - - <actionGroup ref="actionGroupWithSingleParameterSelectorFromArgument" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupWithSingleParameterSelectorFromPassedArgument"> - <annotations> - <severity value="BLOCKER"/> - <title value="Action Group With Passed Argument Value and Argument Value in Param"/> - </annotations> - - <actionGroup ref="actionGroupWithSingleParameterSelectorFromArgument" stepKey="actionGroup"> - <argument name="someArgument" value="UniquePerson"/> - </actionGroup> - </test> - - <test name="ActionGroupWithMultipleParameterSelectorsFromDefaultArgument"> - <annotations> - <severity value="BLOCKER"/> - <title value="Action Group With Passed Argument Value and Multiple Argument Values in Param"/> - </annotations> - - <actionGroup ref="actionGroupWithMultipleParameterSelectorsFromArgument" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupWithSimpleDataUsageFromPassedArgument"> - <annotations> - <severity value="CRITICAL"/> - <title value="Action Group With Simple Data Usage From Passed Argument"/> - </annotations> - - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup1"> - <argument name="someArgument" value="overrideString"/> - </actionGroup> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup11"> - <argument name="someArgument" value="1"/> - </actionGroup> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup12"> - <argument name="someArgument" value="1.5"/> - </actionGroup> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup13"> - <argument name="someArgument" value="true"/> - </actionGroup> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup2"> - <argument name="someArgument" value="simpleData.firstname"/> - </actionGroup> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup3"> - <argument name="someArgument" value="$persisted.data$"/> - </actionGroup> - - <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup4"> - <argument name="someArgument" value="simpleData.firstname"/> - </actionGroup> - <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup5"> - <argument name="someArgument" value="$simpleData.firstname$"/> - </actionGroup> - <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup6"> - <argument name="someArgument" value="$simpleData.firstname[0]$"/> - </actionGroup> - <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup7"> - <argument name="someArgument" value="$simpleData.firstname[data_index]$"/> - </actionGroup> - </test> - - <test name="ActionGroupWithSimpleDataUsageFromDefaultArgument"> - <annotations> - <severity value="CRITICAL"/> - <title value="Action Group With Simple Data Usage From Default Argument"/> - </annotations> - <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupWithStepKeyReferences"> - <actionGroup ref="FunctionActionGroupWithStepKeyReferences" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupUsingNestedArgument"> - <actionGroup ref="ActionGroupToExtend" stepKey="actionGroup"> - <argument name="count" value="99"/> - </actionGroup> - </test> - - <test name="ActionGroupToExtend"> - <actionGroup ref="ActionGroupToExtend" stepKey="actionGroup"> - <argument name="count" value="99"/> - </actionGroup> - </test> - - <test name="ExtendedActionGroup"> - <actionGroup ref="extendTestActionGroup" stepKey="actionGroup"> - <argument name="count" value="99"/> - <argument name="otherCount" value="8000"/> - </actionGroup> - </test> - - <test name="ExtendedRemoveActionGroup"> - <actionGroup ref="extendRemoveTestActionGroup" stepKey="actionGroup"/> - </test> - - <test name="ActionGroupUsingCreateData"> - <before> - <actionGroup ref="actionGroupWithCreateData" stepKey="Key1"/> - </before> - </test> - - <test name="ActionGroupSkipReadiness"> - <actionGroup ref="actionGroupWithSkipReadinessActions" stepKey="skipReadinessActionGroup"/> - </test> - - <test name="ActionGroupContainsStepKeyInArgText"> - <before> - <actionGroup ref="actionGroupContainsStepKeyInArgValue" stepKey="actionGroup"> - <argument name="sameStepKeyAsArg" value="arg1"/> - </actionGroup> - </before> - <actionGroup ref="actionGroupContainsStepKeyInArgValue" stepKey="actionGroup"> - <argument name="sameStepKeyAsArg" value="arg1"/> - </actionGroup> - </test> - - <test name="ActionGroupWithSectionAndDataAsArguments"> - <actionGroup ref="actionGroupWithSectionAndData" stepKey="actionGroup"> - <argument name="content" value="{{simpleData.firstname}}"/> - <argument name="section" value="SampleSection"/> - </actionGroup> - </test> - - <test name="ActionGroupWithParameterizedElementWithHyphen"> - <actionGroup ref="SectionArgumentWithParameterizedSelector" stepKey="actionGroup"> - <argument name="section" value="SampleSection"/> - </actionGroup> - </test> - - <test name="ActionGroupWithParameterizedElementsWithStepKeyReferences"> - <actionGroup ref="actionGroupWithParametrizedSelectors" stepKey="actionGroup"> - <argument name="param" value="simpleData"/> - <argument name="param2" value="simpleParamData"/> - </actionGroup> - </test> -</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupContainsStepKeyInArgText.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupContainsStepKeyInArgText.xml new file mode 100644 index 000000000..bdea3c163 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupContainsStepKeyInArgText.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupContainsStepKeyInArgText"> + <before> + <actionGroup ref="actionGroupContainsStepKeyInArgValue" stepKey="actionGroup"> + <argument name="sameStepKeyAsArg" value="arg1"/> + </actionGroup> + </before> + <actionGroup ref="actionGroupContainsStepKeyInArgValue" stepKey="actionGroup"> + <argument name="sameStepKeyAsArg" value="arg1"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupToExtend.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupToExtend.xml new file mode 100644 index 000000000..a08122fdb --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupToExtend.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupToExtend"> + <actionGroup ref="ActionGroupToExtend" stepKey="actionGroup"> + <argument name="count" value="99"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingCreateData.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingCreateData.xml new file mode 100644 index 000000000..92d142700 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingCreateData.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupUsingCreateData"> + <before> + <actionGroup ref="actionGroupWithCreateData" stepKey="Key1"/> + </before> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingNestedArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingNestedArgument.xml new file mode 100644 index 000000000..100c498b6 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupUsingNestedArgument.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupUsingNestedArgument"> + <actionGroup ref="ActionGroupToExtend" stepKey="actionGroup"> + <argument name="count" value="99"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithDefaultArgumentAndStringSelectorParam.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithDefaultArgumentAndStringSelectorParam.xml new file mode 100644 index 000000000..7d780ef11 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithDefaultArgumentAndStringSelectorParam.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithDefaultArgumentAndStringSelectorParam"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With Default Argument Value and Hardcoded Value in Param"/> + </annotations> + + <actionGroup ref="actionGroupWithDefaultArgumentAndStringSelectorParam" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.xml new file mode 100644 index 000000000..2607a9fd0 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithMultipleParameterSelectorsFromDefaultArgument"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With Passed Argument Value and Multiple Argument Values in Param"/> + </annotations> + + <actionGroup ref="actionGroupWithMultipleParameterSelectorsFromArgument" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithNoArguments.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithNoArguments.xml new file mode 100644 index 000000000..36c8b53b2 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithNoArguments.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithNoArguments"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With No Argument"/> + </annotations> + <actionGroup ref="actionGroupWithoutArguments" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementWithHyphen.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementWithHyphen.xml new file mode 100644 index 000000000..261c493f1 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementWithHyphen.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithParameterizedElementWithHyphen"> + <actionGroup ref="SectionArgumentWithParameterizedSelector" stepKey="actionGroup"> + <argument name="section" value="SampleSection"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementsWithStepKeyReferences.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementsWithStepKeyReferences.xml new file mode 100644 index 000000000..f99004311 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithParameterizedElementsWithStepKeyReferences.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithParameterizedElementsWithStepKeyReferences"> + <actionGroup ref="actionGroupWithParametrizedSelectors" stepKey="actionGroup"> + <argument name="param" value="simpleData"/> + <argument name="param2" value="simpleParamData"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithPassedArgumentAndStringSelectorParam.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithPassedArgumentAndStringSelectorParam.xml new file mode 100644 index 000000000..ea8e98b8a --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithPassedArgumentAndStringSelectorParam.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithPassedArgumentAndStringSelectorParam"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With Passed Argument Value and Hardcoded Value in Param"/> + </annotations> + + <actionGroup ref="actionGroupWithDefaultArgumentAndStringSelectorParam" stepKey="actionGroup"> + <argument name="someArgument" value="UniquePerson"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSectionAndDataAsArguments.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSectionAndDataAsArguments.xml new file mode 100644 index 000000000..dacb2ed18 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSectionAndDataAsArguments.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithSectionAndDataAsArguments"> + <actionGroup ref="actionGroupWithSectionAndData" stepKey="actionGroup"> + <argument name="content" value="{{simpleData.firstname}}"/> + <argument name="section" value="SampleSection"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromDefaultArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromDefaultArgument.xml new file mode 100644 index 000000000..a33603c07 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromDefaultArgument.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithSimpleDataUsageFromDefaultArgument"> + <annotations> + <severity value="CRITICAL"/> + <title value="Action Group With Simple Data Usage From Default Argument"/> + </annotations> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromPassedArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromPassedArgument.xml new file mode 100644 index 000000000..61aa66f9b --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSimpleDataUsageFromPassedArgument.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithSimpleDataUsageFromPassedArgument"> + <annotations> + <severity value="CRITICAL"/> + <title value="Action Group With Simple Data Usage From Passed Argument"/> + </annotations> + + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup1"> + <argument name="someArgument" value="overrideString"/> + </actionGroup> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup11"> + <argument name="someArgument" value="1"/> + </actionGroup> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup12"> + <argument name="someArgument" value="1.5"/> + </actionGroup> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup13"> + <argument name="someArgument" value="true"/> + </actionGroup> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup2"> + <argument name="someArgument" value="simpleData.firstname"/> + </actionGroup> + <actionGroup ref="actionGroupWithStringUsage" stepKey="actionGroup3"> + <argument name="someArgument" value="$persisted.data$"/> + </actionGroup> + + <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup4"> + <argument name="someArgument" value="simpleData.firstname"/> + </actionGroup> + <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup5"> + <argument name="someArgument" value="$simpleData.firstname$"/> + </actionGroup> + <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup6"> + <argument name="someArgument" value="$simpleData.firstname[0]$"/> + </actionGroup> + <actionGroup ref="actionGroupWithEntityUsage" stepKey="actionGroup7"> + <argument name="someArgument" value="$simpleData.firstname[data_index]$"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromDefaultArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromDefaultArgument.xml new file mode 100644 index 000000000..f76e45acf --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromDefaultArgument.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithSingleParameterSelectorFromDefaultArgument"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With Default Argument Value and Argument Value in Param"/> + </annotations> + + <actionGroup ref="actionGroupWithSingleParameterSelectorFromArgument" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromPassedArgument.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromPassedArgument.xml new file mode 100644 index 000000000..d9bfbe656 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithSingleParameterSelectorFromPassedArgument.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithSingleParameterSelectorFromPassedArgument"> + <annotations> + <severity value="BLOCKER"/> + <title value="Action Group With Passed Argument Value and Argument Value in Param"/> + </annotations> + + <actionGroup ref="actionGroupWithSingleParameterSelectorFromArgument" stepKey="actionGroup"> + <argument name="someArgument" value="UniquePerson"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithStepKeyReferences.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithStepKeyReferences.xml new file mode 100644 index 000000000..d68190f83 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ActionGroupWithStepKeyReferences.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ActionGroupWithStepKeyReferences"> + <actionGroup ref="FunctionActionGroupWithStepKeyReferences" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedActionGroup.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedActionGroup.xml new file mode 100644 index 000000000..c7bb24c4f --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedActionGroup.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendedActionGroup"> + <actionGroup ref="extendTestActionGroup" stepKey="actionGroup"> + <argument name="count" value="99"/> + <argument name="otherCount" value="8000"/> + </actionGroup> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedRemoveActionGroup.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedRemoveActionGroup.xml new file mode 100644 index 000000000..bcbed8f23 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest/ExtendedRemoveActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendedRemoveActionGroup"> + <actionGroup ref="extendRemoveTestActionGroup" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/AssertTest.xml b/dev/tests/verification/TestModule/Test/AssertTest.xml index 8cdc724cc..4000c3897 100644 --- a/dev/tests/verification/TestModule/Test/AssertTest.xml +++ b/dev/tests/verification/TestModule/Test/AssertTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AssertTest"> <before> <createData entity="ReplacementPerson" stepKey="createData1"/> @@ -31,14 +31,18 @@ <expectedResult type="string">kiwi</expectedResult> <actualResult type="const">['orange' => 2, 'apple' => 1]</actualResult> </assertArrayNotHasKey> - <assertArraySubset stepKey="assertArraySubset" message="pass"> - <expectedResult type="const">[1, 2]</expectedResult> - <actualResult type="const">[1, 2, 3, 5]</actualResult> - </assertArraySubset> <assertContains stepKey="assertContains" message="pass"> <expectedResult type="string">ab</expectedResult> <actualResult type="const">['item1' => 'a', 'item2' => 'ab']</actualResult> </assertContains> + <assertStringContainsString stepKey="assertStringContainsString" message="pass"> + <expectedResult type="string">apple</expectedResult> + <actualResult type="string">apple</actualResult> + </assertStringContainsString> + <assertStringContainsStringIgnoringCase stepKey="assertStringContainsStringIgnoringCase" message="pass"> + <expectedResult type="string">Banana</expectedResult> + <actualResult type="string">banana</actualResult> + </assertStringContainsStringIgnoringCase> <assertCount stepKey="assertCount" message="pass"> <expectedResult type="int">2</expectedResult> <actualResult type="const">['a', 'b']</actualResult> @@ -79,18 +83,6 @@ <expectedResult type="int">2</expectedResult> <actualResult type="int">5</actualResult> </assertGreaterThanOrEqual> - <assertInternalType stepKey="assertInternalType1" message="pass"> - <expectedResult type="string">string</expectedResult> - <actualResult type="string">xyz</actualResult> - </assertInternalType> - <assertInternalType stepKey="assertInternalType2" message="pass"> - <expectedResult type="string">int</expectedResult> - <actualResult type="int">21</actualResult> - </assertInternalType> - <assertInternalType stepKey="assertInternalType3" message="pass"> - <expectedResult type="string">string</expectedResult> - <actualResult type="variable">text</actualResult> - </assertInternalType> <assertLessOrEquals stepKey="assertLessOrEquals" message="pass"> <expectedResult type="int">5</expectedResult> <actualResult type="int">2</actualResult> @@ -103,21 +95,25 @@ <expectedResult type="int">5</expectedResult> <actualResult type="int">2</actualResult> </assertLessThanOrEqual> - <assertNotContains stepKey="assertNotContains1" message="pass"> + <assertNotContains stepKey="assertNotContains" message="pass"> <expectedResult type="string">bc</expectedResult> <actualResult type="const">['item1' => 'a', 'item2' => 'ab']</actualResult> </assertNotContains> - <assertNotContains stepKey="assertNotContains2" message="pass"> - <expectedResult type="string">bc</expectedResult> - <actualResult type="variable">text</actualResult> - </assertNotContains> + <assertStringNotContainsString stepKey="assertStringNotContainsString" message="pass"> + <expectedResult type="string">apple</expectedResult> + <actualResult type="string">banana</actualResult> + </assertStringNotContainsString> + <assertStringNotContainsStringIgnoringCase stepKey="assertStringNotContainsStringIgnoringCase" message="pass"> + <expectedResult type="string">apple</expectedResult> + <actualResult type="string">banana</actualResult> + </assertStringNotContainsStringIgnoringCase> <assertNotEmpty stepKey="assertNotEmpty1" message="pass"> <actualResult type="const">[1, 2]</actualResult> </assertNotEmpty> <assertNotEmpty stepKey="assertNotEmpty2" message="pass"> <actualResult type="variable">text</actualResult> </assertNotEmpty> - <assertNotEquals stepKey="assertNotEquals" message="pass" delta=""> + <assertNotEquals stepKey="assertNotEquals" message="pass"> <expectedResult type="int">2</expectedResult> <actualResult type="int">5</actualResult> </assertNotEquals> @@ -157,47 +153,141 @@ <!-- asserts backward compatible --> <comment stepKey="commentBackwardCompatible" userInput="asserts backward compatible"/> - <assertArrayHasKey stepKey="assertArrayHasKeyBackwardCompatible" expected="apple" expectedType="string" actual="['orange' => 2, 'apple' => 1]" actualType="const" message="pass"/> - <assertArrayNotHasKey stepKey="assertArrayNotHasKeyBackwardCompatible" expected="kiwi" expectedType="string" actual="['orange' => 2, 'apple' => 1]" message="pass"/> - <assertArraySubset stepKey="assertArraySubsetBackwardCompatible" expected="[1, 2]" actual="[1, 2, 3, 5]" message="pass"/> - <assertContains stepKey="assertContainsBackwardCompatible" expected="ab" expectedType="string" actual="['item1' => 'a', 'item2' => 'ab']" message="pass"/> - <assertCount stepKey="assertCountBackwardCompatible" expected="2" expectedType="int" actual="['a', 'b']" message="pass"/> - <assertEmpty stepKey="assertEmptyBackwardCompatible" actual="[]" message="pass"/> - <assertEquals stepKey="assertEquals1BackwardCompatible" expected="text" expectedType="variable" actual="Copyright © 2013-2017 Magento, Inc. All rights reserved." actualType="string" message="pass"/> - <assertEquals stepKey="assertEquals2BackwardCompatible" expected="Copyright © 2013-2017 Magento, Inc. All rights reserved." expectedType="string" actual="text" actualType="variable" message="pass"/> - <assertFalse stepKey="assertFalse1BackwardCompatible" actual="0" actualType="bool" message="pass"/> - <assertFileNotExists stepKey="assertFileNotExists1BackwardCompatible" actual="/out.txt" actualType="string" message="pass"/> - <assertFileNotExists stepKey="assertFileNotExists2BackwardCompatible" actual="$text" actualType="variable" message="pass"/> - <assertGreaterOrEquals stepKey="assertGreaterOrEqualsBackwardCompatible" expected="2" expectedType="int" actual="5" actualType="int" message="pass"/> - <assertGreaterThan stepKey="assertGreaterThanBackwardCompatible" expected="2" expectedType="int" actual="5" actualType="int" message="pass"/> - <assertGreaterThanOrEqual stepKey="assertGreaterThanOrEqualBackwardCompatible" expected="2" expectedType="int" actual="5" actualType="int" message="pass"/> - <assertInternalType stepKey="assertInternalType1BackwardCompatible" expected="string" expectedType="string" actual="xyz" actualType="string" message="pass"/> - <assertInternalType stepKey="assertInternalType2BackwardCompatible" expected="int" expectedType="string" actual="21" actualType="int" message="pass"/> - <assertInternalType stepKey="assertInternalType3BackwardCompatible" expected="string" expectedType="string" actual="$text" actualType="variable" message="pass"/> - <assertLessOrEquals stepKey="assertLessOrEqualBackwardCompatibles" expected="5" expectedType="int" actual="2" actualType="int" message="pass"/> - <assertLessThan stepKey="assertLessThanBackwardCompatible" expected="5" expectedType="int" actual="2" actualType="int" message="pass"/> - <assertLessThanOrEqual stepKey="assertLessThanOrEqualBackwardCompatible" expected="5" expectedType="int" actual="2" actualType="int" message="pass"/> - <assertNotContains stepKey="assertNotContains1BackwardCompatible" expected="bc" expectedType="string" actual="['item1' => 'a', 'item2' => 'ab']" message="pass"/> - <assertNotContains stepKey="assertNotContains2BackwardCompatible" expected="bc" expectedType="string" actual="text" actualType="variable" message="pass"/> - <assertNotEmpty stepKey="assertNotEmpty1BackwardCompatible" actual="[1, 2]" message="pass"/> - <assertNotEmpty stepKey="assertNotEmpty2BackwardCompatible" actual="text" actualType="variable" message="pass"/> - <assertNotEquals stepKey="assertNotEqualsBackwardCompatible" expected="2" expectedType="int" actual="5" actualType="int" message="pass" delta=""/> - <assertNotNull stepKey="assertNotNull1BackwardCompatible" actual="abc" actualType="string" message="pass"/> - <assertNotNull stepKey="assertNotNull2BackwardCompatible" actual="text" actualType="variable" message="pass"/> - <assertNotRegExp stepKey="assertNotRegExpBackwardCompatible" expected="/foo/" expectedType="string" actual="bar" actualType="string" message="pass"/> - <assertNotSame stepKey="assertNotSameBackwardCompatible" expected="log" expectedType="string" actual="tag" actualType="string" message="pass"/> - <assertRegExp stepKey="assertRegExpBackwardCompatible" expected="/foo/" expectedType="string" actual="foo" actualType="string" message="pass"/> - <assertSame stepKey="assertSameBackwardCompatible" expected="bar" expectedType="string" actual="bar" actualType="string" message="pass"/> - <assertStringStartsNotWith stepKey="assertStringStartsNotWithBackwardCompatible" expected="a" expectedType="string" actual="banana" actualType="string" message="pass"/> - <assertStringStartsWith stepKey="assertStringStartsWithBackwardCompatible" expected="a" expectedType="string" actual="apple" actualType="string" message="pass"/> - <assertTrue stepKey="assertTrueBackwardCompatible" actual="1" actualType="bool" message="pass"/> - <assertElementContainsAttribute selector="#username" attribute="class" expectedValue="admin__control-text" stepKey="assertElementContainsAttributeBackwardCompatible"/> - <assertInstanceOf stepKey="assertInstanceOfBackwardCompatible" expected="User::class" actual="text" actualType="variable" message="pass"/> - <assertNotInstanceOf stepKey="assertNotInstanceOfBackwardCompatible" expected="User::class" actual="21" actualType="int" message="pass"/> - <assertFileExists stepKey="assertFileExistsBackwardCompatible" actual="text" actualType="variable" message="pass"/> - <assertIsEmpty stepKey="assertIsEmptyBackwardCompatible" actual="text" actualType="variable" message="pass"/> - <assertNull stepKey="assertNullBackwardCompatible" actual="text" actualType="variable" message="pass"/> - <expectException stepKey="expectExceptionBackwardCompatible" expected="new MyException('exception msg')" actual="function() {$this->doSomethingBad();}"/> + <assertArrayHasKey stepKey="assertArrayHasKeyBackwardCompatible" message="pass"> + <expectedResult type="string">apple</expectedResult> + <actualResult type="const">['orange' => 2, 'apple' => 1]</actualResult> + </assertArrayHasKey> + <assertArrayNotHasKey stepKey="assertArrayNotHasKeyBackwardCompatible" message="pass"> + <expectedResult type="string">kiwi</expectedResult> + <actualResult type="const">['orange' => 2, 'apple' => 1]</actualResult> + </assertArrayNotHasKey> + <assertContains stepKey="assertContainsBackwardCompatible" message="pass"> + <expectedResult type="string">ab</expectedResult> + <actualResult type="const">['item1' => 'a', 'item2' => 'ab']</actualResult> + </assertContains> + <assertCount stepKey="assertCountBackwardCompatible" message="pass"> + <actualResult type="const">['a', 'b']</actualResult> + <expectedResult type="int">2</expectedResult> + </assertCount> + <assertEmpty stepKey="assertEmptyBackwardCompatible" message="pass"> + <actualResult type="const">[]</actualResult> + </assertEmpty> + <assertEquals stepKey="assertEquals1BackwardCompatible" message="pass"> + <actualResult type="string">Copyright © 2013-2017 Magento, Inc. All rights reserved.</actualResult> + <expectedResult type="variable">text</expectedResult> + </assertEquals> + <assertEquals stepKey="assertEquals2BackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + <expectedResult type="string">Copyright © 2013-2017 Magento, Inc. All rights reserved.</expectedResult> + </assertEquals> + <assertFalse stepKey="assertFalse1BackwardCompatible" message="pass"> + <actualResult type="bool">0</actualResult> + </assertFalse> + <assertFileNotExists stepKey="assertFileNotExists1BackwardCompatible" message="pass"> + <actualResult type="string">/out.txt</actualResult> + </assertFileNotExists> + <assertFileNotExists stepKey="assertFileNotExists2BackwardCompatible" message="pass"> + <actualResult type="variable">$text</actualResult> + </assertFileNotExists> + <assertGreaterOrEquals stepKey="assertGreaterOrEqualsBackwardCompatible" message="pass"> + <actualResult type="int">5</actualResult> + <expectedResult type="int">2</expectedResult> + </assertGreaterOrEquals> + <assertGreaterThan stepKey="assertGreaterThanBackwardCompatible" message="pass"> + <actualResult type="int">5</actualResult> + <expectedResult type="int">2</expectedResult> + </assertGreaterThan> + <assertGreaterThanOrEqual stepKey="assertGreaterThanOrEqualBackwardCompatible" message="pass"> + <actualResult type="int">5</actualResult> + <expectedResult type="int">2</expectedResult> + </assertGreaterThanOrEqual> + <assertLessOrEquals stepKey="assertLessOrEqualBackwardCompatibles" message="pass"> + <actualResult type="int">2</actualResult> + <expectedResult type="int">5</expectedResult> + </assertLessOrEquals> + <assertLessThan stepKey="assertLessThanBackwardCompatible" message="pass"> + <actualResult type="int">2</actualResult> + <expectedResult type="int">5</expectedResult> + </assertLessThan> + <assertLessThanOrEqual stepKey="assertLessThanOrEqualBackwardCompatible" message="pass"> + <actualResult type="int">2</actualResult> + <expectedResult type="int">5</expectedResult> + </assertLessThanOrEqual> + <assertNotContains stepKey="assertNotContains1BackwardCompatible" message="pass"> + <expectedResult type="string">bc</expectedResult> + <actualResult type="const">['item1' => 'a', 'item2' => 'ab']</actualResult> + </assertNotContains> + <assertNotContains stepKey="assertNotContains2BackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + <expectedResult type="string">bc</expectedResult> + </assertNotContains> + <assertNotEmpty stepKey="assertNotEmpty1BackwardCompatible" message="pass"> + <actualResult type="const">[1, 2]</actualResult> + </assertNotEmpty> + <assertNotEmpty stepKey="assertNotEmpty2BackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + </assertNotEmpty> + <assertNotEquals stepKey="assertNotEqualsBackwardCompatible" message="pass"> + <actualResult type="int">5</actualResult> + <expectedResult type="int">2</expectedResult> + </assertNotEquals> + <assertNotNull stepKey="assertNotNull1BackwardCompatible" message="pass"> + <actualResult type="string">abc</actualResult> + </assertNotNull> + <assertNotNull stepKey="assertNotNull2BackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + </assertNotNull> + <assertNotRegExp stepKey="assertNotRegExpBackwardCompatible" message="pass"> + <actualResult type="string">bar</actualResult> + <expectedResult type="string">/foo/</expectedResult> + </assertNotRegExp> + <assertNotSame stepKey="assertNotSameBackwardCompatible" message="pass"> + <actualResult type="string">tag</actualResult> + <expectedResult type="string">log</expectedResult> + </assertNotSame> + <assertRegExp stepKey="assertRegExpBackwardCompatible" message="pass"> + <actualResult type="string">foo</actualResult> + <expectedResult type="string">/foo/</expectedResult> + </assertRegExp> + <assertSame stepKey="assertSameBackwardCompatible" message="pass"> + <actualResult type="string">bar</actualResult> + <expectedResult type="string">bar</expectedResult> + </assertSame> + <assertStringStartsNotWith stepKey="assertStringStartsNotWithBackwardCompatible" message="pass"> + <actualResult type="string">banana</actualResult> + <expectedResult type="string">a</expectedResult> + </assertStringStartsNotWith> + <assertStringStartsWith stepKey="assertStringStartsWithBackwardCompatible" message="pass"> + <actualResult type="string">apple</actualResult> + <expectedResult type="string">a</expectedResult> + </assertStringStartsWith> + <assertTrue stepKey="assertTrueBackwardCompatible" message="pass"> + <actualResult type="bool">1</actualResult> + </assertTrue> + <assertElementContainsAttribute stepKey="assertElementContainsAttributeBackwardCompatible"> + <expectedResult selector="#username" attribute="class" type="string">admin__control-text</expectedResult> + </assertElementContainsAttribute> + <assertInstanceOf stepKey="assertInstanceOfBackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + <expectedResult type="const">User::class</expectedResult> + </assertInstanceOf> + <assertNotInstanceOf stepKey="assertNotInstanceOfBackwardCompatible" message="pass"> + <actualResult type="int">21</actualResult> + <expectedResult type="const">User::class</expectedResult> + </assertNotInstanceOf> + <assertFileExists stepKey="assertFileExistsBackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + </assertFileExists> + <assertIsEmpty stepKey="assertIsEmptyBackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + </assertIsEmpty> + <assertNull stepKey="assertNullBackwardCompatible" message="pass"> + <actualResult type="variable">text</actualResult> + </assertNull> + <expectException stepKey="expectExceptionBackwardCompatible"> + <expectedResult type="const">new MyException('exception msg')</expectedResult> + <actualResult type="const">function() {$this->doSomethingBad();}</actualResult> + </expectException> <!-- string type that use created data --> <comment stepKey="c2" userInput="string type that use created data"/> @@ -216,14 +306,6 @@ <!-- array type that use created data --> <comment stepKey="c3" userInput="array type that use created data"/> - <assertArraySubset stepKey="assert9" message="pass"> - <expectedResult type="array">[$$createData1.lastname$$, $$createData1.firstname$$]</expectedResult> - <actualResult type="array">[$$createData1.lastname$$, $$createData1.firstname$$, 1]</actualResult> - </assertArraySubset> - <assertArraySubset stepKey="assert10" message="pass"> - <expectedResult type="array">[$createData2.firstname$, $createData2.lastname$]</expectedResult> - <actualResult type="array">[$createData2.firstname$, $createData2.lastname$, 1]</actualResult> - </assertArraySubset> <assertArrayHasKey stepKey="assert3" message="pass"> <expectedResult type="string">lastname</expectedResult> <actualResult type="array">['lastname' => $$createData1.lastname$$, 'firstname' => $$createData1.firstname$$]</actualResult> @@ -263,29 +345,29 @@ <fail stepKey="assert8" message="$$createData1.firstname$$ $$createData1.lastname$$"/> <!-- assertElementContainsAttribute examples --> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute1" selector="#username" attribute="class"> - <expectedResult type="string">admin__control-text</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute1"> + <expectedResult selector="#username" attribute="class" type="string">admin__control-text</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute2" selector="#username" attribute="name"> - <expectedResult type="string">login[username]</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute2"> + <expectedResult selector="#username" attribute="name" type="string">login[username]</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute3" selector="#username" attribute="autofocus"> - <expectedResult type="string">true</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute3"> + <expectedResult selector="#username" attribute="autofocus" type="string">true</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute4" selector="#username" attribute="data-validate"> - <expectedResult type="string">{required:true}</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute4"> + <expectedResult selector="#username" attribute="data-validate" type="string">{required:true}</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute5" selector=".admin__menu-overlay" attribute="style"> - <expectedResult type="string">display: none;</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute5"> + <expectedResult selector=".admin__menu-overlay" attribute="style" type="string">display: none;</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute6" selector=".admin__menu-overlay" attribute="border"> - <expectedResult type="string">0</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute6"> + <expectedResult selector=".admin__menu-overlay" attribute="border" type="string">0</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute7" selector="#username" attribute="value"> - <expectedResult type="const">$createData2.firstname$</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute7"> + <expectedResult selector="#username" attribute="value" type="const">$createData2.firstname$</expectedResult> </assertElementContainsAttribute> - <assertElementContainsAttribute stepKey="assertElementContainsAttribute8" selector="#username" attribute="value"> - <expectedResult type="const">$$createData1.firstname$$</expectedResult> + <assertElementContainsAttribute stepKey="assertElementContainsAttribute8"> + <expectedResult selector="#username" attribute="value" type="const">$$createData1.firstname$$</expectedResult> </assertElementContainsAttribute> <!-- assert entity resolution --> @@ -293,5 +375,30 @@ <expectedResult type="string">{{simpleData.firstname}}</expectedResult> <actualResult type="string">{{simpleData.lastname}}</actualResult> </assertEquals> + + <assertEqualsWithDelta stepKey="a1" message="pass" delta="1"> + <expectedResult type="const">10.0000</expectedResult> + <actualResult type="const">10.0000</actualResult> + </assertEqualsWithDelta> + <assertNotEqualsWithDelta stepKey="a2" message="pass" delta="1"> + <expectedResult type="const">10.0000</expectedResult> + <actualResult type="const">12.0000</actualResult> + </assertNotEqualsWithDelta> + <assertEqualsCanonicalizing stepKey="a3" message="pass"> + <expectedResult type="array">[4, 2, 1, 3]</expectedResult> + <actualResult type="array">[1, 2, 3, 4]</actualResult> + </assertEqualsCanonicalizing> + <assertNotEqualsCanonicalizing stepKey="a4" message="pass"> + <expectedResult type="array">[5, 8, 7, 9]</expectedResult> + <actualResult type="array">[1, 2, 3, 4]</actualResult> + </assertNotEqualsCanonicalizing> + <assertEqualsIgnoringCase stepKey="a5" message="pass"> + <expectedResult type="string">Cat</expectedResult> + <actualResult type="string">cat</actualResult> + </assertEqualsIgnoringCase> + <assertNotEqualsIgnoringCase stepKey="a6" message="pass"> + <expectedResult type="string">Cat</expectedResult> + <actualResult type="string">Dog</actualResult> + </assertNotEqualsIgnoringCase> </test> </tests> diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml similarity index 92% rename from dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml rename to dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml index 1ef25b43d..81a43ca12 100644 --- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml @@ -5,9 +5,8 @@ * See COPYING.txt for license details. */ --> - <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="BasicFunctionalTest"> <annotations> <severity value="CRITICAL"/> @@ -69,6 +68,7 @@ <fillField selector=".functionalTestSelector" userInput="0" stepKey="fillFieldKey2" /> <generateDate date="Now" format="H:i:s" stepKey="generateDateKey"/> <generateDate date="Now" format="H:i:s" stepKey="generateDateKey2" timezone="UTC"/> + <getOTP stepKey="getOtp"/> <grabAttributeFrom selector=".functionalTestSelector" userInput="someInput" stepKey="grabAttributeFromKey1" /> <grabCookie userInput="grabCookieInput" parameterArray="['domain' => 'www.google.com']" stepKey="grabCookieKey1" /> <grabFromCurrentUrl regex="/grabCurrentUrl" stepKey="grabFromCurrentUrlKey1" /> @@ -88,8 +88,7 @@ <moveForward stepKey="moveForwardKey1"/> <moveMouseOver selector=".functionalTestSelector" stepKey="moveMouseOverKey1"/> <openNewTab stepKey="openNewTabKey1"/> - <pauseExecution stepKey="pauseExecutionKey1"/> - <performOn selector="#selector" function="function(\WebDriverElement $el) {return $el->isDisplayed();}" stepKey="performOnKey1"/> + <pause stepKey="pauseKey1"/> <pressKey selector="#page" userInput="a" stepKey="pressKey1"/> <pressKey selector="#page" parameterArray="[['ctrl','a'],'new']" stepKey="pressKey2"/> <pressKey selector="#page" parameterArray="[['shift','111'],'1','x']" stepKey="pressKey3"/> @@ -136,14 +135,4 @@ <waitForJS function="someJsFunction" time="30" stepKey="waitForJSKey1" /> <waitForText selector=".functionalTestSelector" userInput="someInput" time="30" stepKey="waitForText1"/> </test> - <test name="MergeMassViaInsertBefore"> - <fillField selector="#foo" userInput="foo" stepKey="fillField1"/> - <fillField selector="#bar" userInput="bar" stepKey="fillField2"/> - <fillField selector="#baz" userInput="baz" stepKey="fillField3"/> - </test> - <test name="MergeMassViaInsertAfter"> - <fillField selector="#foo" userInput="foo" stepKey="fillField1"/> - <fillField selector="#bar" userInput="bar" stepKey="fillField2"/> - <fillField selector="#baz" userInput="baz" stepKey="fillField3"/> - </test> </tests> diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertAfter.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertAfter.xml new file mode 100644 index 000000000..6efe33e49 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertAfter.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeMassViaInsertAfter"> + <fillField selector="#foo" userInput="foo" stepKey="fillField1"/> + <fillField selector="#bar" userInput="bar" stepKey="fillField2"/> + <fillField selector="#baz" userInput="baz" stepKey="fillField3"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertBefore.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertBefore.xml new file mode 100644 index 000000000..897fb51cc --- /dev/null +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/MergeMassViaInsertBefore.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeMassViaInsertBefore"> + <fillField selector="#foo" userInput="foo" stepKey="fillField1"/> + <fillField selector="#bar" userInput="bar" stepKey="fillField2"/> + <fillField selector="#baz" userInput="baz" stepKey="fillField3"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/CharacterReplacementTest.xml b/dev/tests/verification/TestModule/Test/CharacterReplacementTest.xml index 9a8c0f17d..85b3fb34e 100644 --- a/dev/tests/verification/TestModule/Test/CharacterReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/CharacterReplacementTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="CharacterReplacementTest"> <click stepKey="charsInSectionElement" selector="{{SampleSection.underscore_element}}"/> <fillField stepKey="charsInDataRef" selector="{{SampleSection.underscore_element}}" userInput="{{simpleData.street[0]}}"/> diff --git a/dev/tests/verification/TestModule/Test/DataActionsTest.xml b/dev/tests/verification/TestModule/Test/DataActionsTest.xml index 03d7caa35..b75bc98f8 100644 --- a/dev/tests/verification/TestModule/Test/DataActionsTest.xml +++ b/dev/tests/verification/TestModule/Test/DataActionsTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="DataActionsTest"> <before> <createData entity="entity" stepKey="createdInBefore"/> diff --git a/dev/tests/verification/TestModule/Test/DataReplacementTest.xml b/dev/tests/verification/TestModule/Test/DataReplacementTest.xml index ae11b6fdc..f33a95b50 100644 --- a/dev/tests/verification/TestModule/Test/DataReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/DataReplacementTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="DataReplacementTest"> <fillField stepKey="inputReplace" selector="#selector" userInput="StringBefore {{simpleData.firstname}} StringAfter"/> <seeCurrentUrlMatches stepKey="seeInRegex" regex="~\/{{simpleData.firstname}}~i"/> diff --git a/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml b/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml index 733a34e80..20c7ccd0b 100644 --- a/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml +++ b/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="DeprecatedEntitiesTest"> <actionGroup ref="DeprecatedActionGroup" stepKey="deprecatedActionGroup" /> <amOnPage url="{{DeprecatedPage.url}}" stepKey="amOnPage" /> diff --git a/dev/tests/verification/TestModule/Test/DeprecatedTest.xml b/dev/tests/verification/TestModule/Test/DeprecatedTest.xml index cc5ae4994..075e8add3 100644 --- a/dev/tests/verification/TestModule/Test/DeprecatedTest.xml +++ b/dev/tests/verification/TestModule/Test/DeprecatedTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="DeprecatedTest" deprecated="Test is deprecated"> <actionGroup ref="DeprecatedActionGroup" stepKey="deprecatedActionGroup" /> <amOnPage url="{{DeprecatedPage.url}}" stepKey="amOnPage" /> diff --git a/dev/tests/verification/TestModule/Test/ExecuteInSeleniumTest.xml b/dev/tests/verification/TestModule/Test/ExecuteInSeleniumTest.xml deleted file mode 100644 index c25164220..000000000 --- a/dev/tests/verification/TestModule/Test/ExecuteInSeleniumTest.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="ExecuteInSeleniumTest"> - <executeInSelenium function="function ($webdriver) { return "Hello, World!"}" stepKey="executeInSeleniumStep"/> - </test> -</tests> diff --git a/dev/tests/verification/TestModule/Test/ExecuteJsTest.xml b/dev/tests/verification/TestModule/Test/ExecuteJsTest.xml index b361cdd28..ea80275e1 100644 --- a/dev/tests/verification/TestModule/Test/ExecuteJsTest.xml +++ b/dev/tests/verification/TestModule/Test/ExecuteJsTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ExecuteJsEscapingTest"> <executeJS function="return $javascriptVariable" stepKey="javaVariableEscape"/> <executeJS function="return {$doNotEscape}" stepKey="mftfVariableNotEscaped"/> diff --git a/dev/tests/verification/TestModule/Test/ExtendedDataTest.xml b/dev/tests/verification/TestModule/Test/ExtendedDataTest.xml index 21f06eb3a..053b26c38 100644 --- a/dev/tests/verification/TestModule/Test/ExtendedDataTest.xml +++ b/dev/tests/verification/TestModule/Test/ExtendedDataTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ExtendParentDataTest"> <createData entity="extendParentData" stepKey="simpleDataKey"/> <searchAndMultiSelectOption selector="#selector" parameterArray="[{{extendParentData.name}}]" stepKey="getName"/> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest.xml deleted file mode 100644 index 486a6036f..000000000 --- a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest.xml +++ /dev/null @@ -1,201 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="ParentExtendedTest"> - <annotations> - <severity value="AVERAGE"/> - <title value="ParentExtendedTest"/> - <group value="Parent"/> - <features value="Parent"/> - <stories value="Parent"/> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> - </after> - <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> - </test> - - <test name="ChildExtendedTestReplace" extends="ParentExtendedTest"> - <annotations> - <severity value="MINOR"/> - <title value="ChildExtendedTestReplace"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> - </test> - - <test name="ChildExtendedTestReplaceHook" extends="ParentExtendedTest"> - <annotations> - <severity value="MINOR"/> - <title value="ChildExtendedTestReplaceHook"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <before> - <amOnPage url="/slightlyDifferentBeforeUrl" stepKey="beforeAmOnPageKey"/> - </before> - </test> - - <test name="ChildExtendedTestMerging" extends="ParentExtendedTest"> - <annotations> - <severity value="MINOR"/> - <title value="ChildExtendedTestMerging"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <before> - <amOnPage url="/firstUrl" stepKey="firstBeforeAmOnPageKey" before="beforeAmOnPageKey"/> - <amOnPage url="/lastUrl" stepKey="lastBefore" after="beforeAmOnPageKey"/> - </before> - <comment stepKey="lastStepKey" userInput="Last Comment"/> - <comment stepKey="beforeBasicCommentWithNoData" userInput="Before Comment" before="basicCommentWithNoData"/> - <comment stepKey="afterBasicCommentWithNoData" userInput="After Comment" after="basicCommentWithNoData"/> - </test> - - <test name="ChildExtendedTestRemoveAction" extends="ParentExtendedTest"> - <annotations> - <severity value="CRITICAL"/> - <title value="ChildExtendedTestRemoveAction"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <remove keyForRemoval="basicCommentWithNoData"/> - </test> - - <test name="ParentExtendedTestNoHooks"> - <annotations> - <severity value="AVERAGE"/> - <title value="ParentExtendedTestNoHooks"/> - <group value="Parent"/> - <features value="Parent"/> - <stories value="Parent"/> - </annotations> - <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> - </test> - - <test name="ChildExtendedTestAddHooks"> - <annotations> - <severity value="AVERAGE"/> - <title value="ChildExtendedTestAddHooks"/> - <group value="Parent"/> - <features value="Parent"/> - <stories value="Parent"/> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> - </after> - </test> - - <test name="ChildExtendedTestRemoveHookAction" extends="ParentExtendedTest"> - <annotations> - <severity value="CRITICAL"/> - <title value="ChildExtendedTestRemoveHookAction"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <before> - <remove keyForRemoval="beforeAmOnPageKey"/> - </before> - </test> - <test name="ChildExtendedTestNoParent" extends="ThisTestDoesNotExist"> - <annotations> - <severity value="CRITICAL"/> - <title value="ChildExtendedTestNoParent"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <before> - <remove keyForRemoval="beforeAmOnPageKey"/> - </before> - </test> - <test name="SkippedParent"> - <annotations> - <severity value="CRITICAL"/> - <title value="PARENTSKIPPED"/> - <group value="Parent"/> - <features value="Parent"/> - <stories value="Parent"/> - <skip> - <issueId value="NONE"/> - </skip> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> - </after> - <comment userInput="text" stepKey="keepMe"/> - <comment userInput="text" stepKey="replaceMe"/> - </test> - <test name="ExtendingSkippedTest" extends="SkippedParent"> - <annotations> - <severity value="CRITICAL"/> - <title value="ChildExtendedTestSkippedParent"/> - <group value="Child"/> - <features value="Child"/> - <stories value="Child"/> - </annotations> - <comment userInput="child" stepKey="replaceMe"/> - </test> - - <test name="ExtendedTestRelatedToSuiteParentTest"> - <annotations> - <severity value="AVERAGE"/> - <title value="ExtendedTestRelatedToSuiteParentTest"/> - <group value="ExtendedTestRelatedToSuite"/> - <features value="ExtendedTestRelatedToSuiteParentTest"/> - <stories value="ExtendedTestRelatedToSuiteParentTest"/> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> - </after> - <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> - <amOnPage url="/url/in/parent" stepKey="amOnPageInParent"/> - </test> - - <test name="ExtendedChildTestInSuite" extends="ExtendedTestRelatedToSuiteParentTest"> - <annotations> - <severity value="MINOR"/> - <title value="ExtendedChildTestInSuite"/> - <group value="ExtendedTestInSuite"/> - <features value="ExtendedChildTestInSuite"/> - <stories value="ExtendedChildTestInSuite"/> - </annotations> - <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> - <remove keyForRemoval="amOnPageInParent"/> - </test> - <test name="ExtendedChildTestNotInSuite" extends="ExtendedTestRelatedToSuiteParentTest"> - <annotations> - <severity value="MINOR"/> - <title value="ExtendedChildTestNotInSuite"/> - <features value="ExtendedChildTestNotInSuite"/> - <stories value="ExtendedChildTestNotInSuite"/> - </annotations> - <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> - <remove keyForRemoval="amOnPageInParent"/> - </test> -</tests> \ No newline at end of file diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestAddHooks.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestAddHooks.xml new file mode 100644 index 000000000..70cb3c285 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestAddHooks.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestAddHooks"> + <annotations> + <severity value="AVERAGE"/> + <title value="ChildExtendedTestAddHooks"/> + <group value="Parent"/> + <features value="Parent"/> + <stories value="Parent"/> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> + </after> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestMerging.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestMerging.xml new file mode 100644 index 000000000..dfef954e1 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestMerging.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestMerging" extends="ParentExtendedTest"> + <annotations> + <severity value="MINOR"/> + <title value="ChildExtendedTestMerging"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <before> + <amOnPage url="/firstUrl" stepKey="firstBeforeAmOnPageKey" before="beforeAmOnPageKey"/> + <amOnPage url="/lastUrl" stepKey="lastBefore" after="beforeAmOnPageKey"/> + </before> + <comment stepKey="lastStepKey" userInput="Last Comment"/> + <comment stepKey="beforeBasicCommentWithNoData" userInput="Before Comment" before="basicCommentWithNoData"/> + <comment stepKey="afterBasicCommentWithNoData" userInput="After Comment" after="basicCommentWithNoData"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestNoParent.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestNoParent.xml new file mode 100644 index 000000000..81add5d0e --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestNoParent.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestNoParent" extends="ThisTestDoesNotExist"> + <annotations> + <severity value="CRITICAL"/> + <title value="ChildExtendedTestNoParent"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <before> + <remove keyForRemoval="beforeAmOnPageKey"/> + </before> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveAction.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveAction.xml new file mode 100644 index 000000000..aa82ced68 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveAction.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestRemoveAction" extends="ParentExtendedTest"> + <annotations> + <severity value="CRITICAL"/> + <title value="ChildExtendedTestRemoveAction"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <remove keyForRemoval="basicCommentWithNoData"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveHookAction.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveHookAction.xml new file mode 100644 index 000000000..7388a293e --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestRemoveHookAction.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestRemoveHookAction" extends="ParentExtendedTest"> + <annotations> + <severity value="CRITICAL"/> + <title value="ChildExtendedTestRemoveHookAction"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <before> + <remove keyForRemoval="beforeAmOnPageKey"/> + </before> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplace.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplace.xml new file mode 100644 index 000000000..1872fc645 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplace.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestReplace" extends="ParentExtendedTest"> + <annotations> + <severity value="MINOR"/> + <title value="ChildExtendedTestReplace"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplaceHook.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplaceHook.xml new file mode 100644 index 000000000..d12bb6d09 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ChildExtendedTestReplaceHook.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ChildExtendedTestReplaceHook" extends="ParentExtendedTest"> + <annotations> + <severity value="MINOR"/> + <title value="ChildExtendedTestReplaceHook"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <before> + <amOnPage url="/slightlyDifferentBeforeUrl" stepKey="beforeAmOnPageKey"/> + </before> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestInSuite.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestInSuite.xml new file mode 100644 index 000000000..76e1e10e3 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestInSuite.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendedChildTestInSuite" extends="ExtendedTestRelatedToSuiteParentTest"> + <annotations> + <severity value="MINOR"/> + <title value="ExtendedChildTestInSuite"/> + <group value="ExtendedTestInSuite"/> + <features value="ExtendedChildTestInSuite"/> + <stories value="ExtendedChildTestInSuite"/> + </annotations> + <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> + <remove keyForRemoval="amOnPageInParent"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestNotInSuite.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestNotInSuite.xml new file mode 100644 index 000000000..54d0f5cbf --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedChildTestNotInSuite.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendedChildTestNotInSuite" extends="ExtendedTestRelatedToSuiteParentTest"> + <annotations> + <severity value="MINOR"/> + <title value="ExtendedChildTestNotInSuite"/> + <features value="ExtendedChildTestNotInSuite"/> + <stories value="ExtendedChildTestNotInSuite"/> + </annotations> + <comment stepKey="basicCommentWithNoData" userInput="Different Input"/> + <remove keyForRemoval="amOnPageInParent"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedTestRelatedToSuiteParentTest.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedTestRelatedToSuiteParentTest.xml new file mode 100644 index 000000000..1bc656149 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendedTestRelatedToSuiteParentTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendedTestRelatedToSuiteParentTest"> + <annotations> + <severity value="AVERAGE"/> + <title value="ExtendedTestRelatedToSuiteParentTest"/> + <group value="ExtendedTestRelatedToSuite"/> + <features value="ExtendedTestRelatedToSuiteParentTest"/> + <stories value="ExtendedTestRelatedToSuiteParentTest"/> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> + </after> + <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> + <amOnPage url="/url/in/parent" stepKey="amOnPageInParent"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendingSkippedTest.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendingSkippedTest.xml new file mode 100644 index 000000000..f451c143a --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ExtendingSkippedTest.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExtendingSkippedTest" extends="SkippedParent"> + <annotations> + <severity value="CRITICAL"/> + <title value="ChildExtendedTestSkippedParent"/> + <group value="Child"/> + <features value="Child"/> + <stories value="Child"/> + </annotations> + <comment userInput="child" stepKey="replaceMe"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTest.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTest.xml new file mode 100644 index 000000000..ed5aa6c16 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTest.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ParentExtendedTest"> + <annotations> + <severity value="AVERAGE"/> + <title value="ParentExtendedTest"/> + <group value="Parent"/> + <features value="Parent"/> + <stories value="Parent"/> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> + </after> + <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTestNoHooks.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTestNoHooks.xml new file mode 100644 index 000000000..c7d17857e --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/ParentExtendedTestNoHooks.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ParentExtendedTestNoHooks"> + <annotations> + <severity value="AVERAGE"/> + <title value="ParentExtendedTestNoHooks"/> + <group value="Parent"/> + <features value="Parent"/> + <stories value="Parent"/> + </annotations> + <comment stepKey="basicCommentWithNoData" userInput="Parent Comment"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/SkippedParent.xml b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/SkippedParent.xml new file mode 100644 index 000000000..ff36905e7 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/ExtendedFunctionalTest/SkippedParent.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="SkippedParent"> + <annotations> + <severity value="CRITICAL"/> + <title value="PARENTSKIPPED"/> + <group value="Parent"/> + <features value="Parent"/> + <stories value="Parent"/> + <skip> + <issueId value="NONE"/> + </skip> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> + </after> + <comment userInput="text" stepKey="keepMe"/> + <comment userInput="text" stepKey="replaceMe"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/GroupSkipGenerationTest.xml b/dev/tests/verification/TestModule/Test/GroupSkipGenerationTest.xml new file mode 100644 index 000000000..35cf74d33 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/GroupSkipGenerationTest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="GroupSkipGenerationTest"> + <annotations> + <stories value="GroupSkipGenerationTestStory"/> + <title value="GroupSkipGenerationTestTitle"/> + <description value="GroupSkipGenerationTestDescription"/> + <severity value="AVERAGE"/> + <group value="skip"/> + </annotations> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/HookActionsTest.xml b/dev/tests/verification/TestModule/Test/HookActionsTest.xml index 7e3521e4f..0a26256d0 100644 --- a/dev/tests/verification/TestModule/Test/HookActionsTest.xml +++ b/dev/tests/verification/TestModule/Test/HookActionsTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="HookActionsTest"> <before> <createData entity="sampleCreatedEntity" stepKey="sampleCreateBefore"/> diff --git a/dev/tests/verification/TestModule/Test/LocatorFunctionTest.xml b/dev/tests/verification/TestModule/Test/LocatorFunctionTest.xml index f9caa59fc..eefd75e1f 100644 --- a/dev/tests/verification/TestModule/Test/LocatorFunctionTest.xml +++ b/dev/tests/verification/TestModule/Test/LocatorFunctionTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="LocatorFunctionTest"> <createData entity="ReplacementPerson" stepKey="data"/> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml deleted file mode 100644 index 5189b8cf4..000000000 --- a/dev/tests/verification/TestModule/Test/MergeFunctionalTest.xml +++ /dev/null @@ -1,61 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="BasicMergeTest"> - <annotations> - <severity value="CRITICAL"/> - <title value="BasicMergeTest"/> - <group value="functional"/> - <features value="Merge Functional Cest"/> - <stories value="MQE-433"/> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="before1"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="after1"/> - </after> - <amOnPage stepKey="step1" url="/step1"/> - <fillField stepKey="step3" selector="#username" userInput="step3"/> - <fillField stepKey="step5" selector="#password" userInput="step5"/> - <click stepKey="step6" selector=".step6"/> - <click stepKey="step10" selector="#step10ShouldNotInResult"/> - </test> - <test name="MergedReferencesTest"> - <annotations> - <severity value="CRITICAL"/> - <title value="MergedReferencesTest"/> - <group value="functional"/> - <features value="Merge Functional Cest"/> - <stories value="MQE-433"/> - </annotations> - <before> - <amOnPage url="/beforeUrl" stepKey="before1"/> - </before> - <after> - <amOnPage url="/afterUrl" stepKey="after1"/> - </after> - <fillField stepKey="fillField1" selector="{{SampleSection.mergeElement}}" userInput="{{DefaultPerson.mergedField}}"/> - <fillField stepKey="fillField2" selector="{{SampleSection.newElement}}" userInput="{{DefaultPerson.newField}}" /> - </test> - <test name="MergeMassViaInsertBefore" insertBefore="fillField2"> - <click stepKey="clickOne" selector="#mergeOne"/> - <click stepKey="clickTwo" selector="#mergeTwo"/> - <click stepKey="clickThree" selector="#mergeThree"/> - </test> - <test name="MergeMassViaInsertAfter" insertAfter="fillField2"> - <click stepKey="clickOne" selector="#mergeOne"/> - <click stepKey="clickTwo" selector="#mergeTwo"/> - <click stepKey="clickThree" selector="#mergeThree"/> - </test> - <test name="MergeSkip"> - <comment userInput="ThisTestShouldBeSkipped" stepKey="skipComment"/> - </test> -</tests> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest/BasicMergeTest.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/BasicMergeTest.xml new file mode 100644 index 000000000..3237ba7bb --- /dev/null +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/BasicMergeTest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="BasicMergeTest"> + <annotations> + <severity value="CRITICAL"/> + <title value="BasicMergeTest"/> + <group value="functional"/> + <features value="Merge Functional Cest"/> + <stories value="MQE-433"/> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="before1"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="after1"/> + </after> + <amOnPage stepKey="step1" url="/step1"/> + <fillField stepKey="step3" selector="#username" userInput="step3"/> + <fillField stepKey="step5" selector="#password" userInput="step5"/> + <click stepKey="step6" selector=".step6"/> + <click stepKey="step10" selector="#step10ShouldNotInResult"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertAfter.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertAfter.xml new file mode 100644 index 000000000..2f35be2cb --- /dev/null +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertAfter.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeMassViaInsertAfter" insertAfter="fillField2"> + <click stepKey="clickOne" selector="#mergeOne"/> + <click stepKey="clickTwo" selector="#mergeTwo"/> + <click stepKey="clickThree" selector="#mergeThree"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertBefore.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertBefore.xml new file mode 100644 index 000000000..913644f51 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeMassViaInsertBefore.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeMassViaInsertBefore" insertBefore="fillField2"> + <click stepKey="clickOne" selector="#mergeOne"/> + <click stepKey="clickTwo" selector="#mergeTwo"/> + <click stepKey="clickThree" selector="#mergeThree"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeSkip.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeSkip.xml new file mode 100644 index 000000000..1d8b82200 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergeSkip.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeSkip"> + <comment userInput="ThisTestShouldBeSkipped" stepKey="skipComment"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergedReferencesTest.xml b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergedReferencesTest.xml new file mode 100644 index 000000000..d48de5d3a --- /dev/null +++ b/dev/tests/verification/TestModule/Test/MergeFunctionalTest/MergedReferencesTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergedReferencesTest"> + <annotations> + <severity value="CRITICAL"/> + <title value="MergedReferencesTest"/> + <group value="functional"/> + <features value="Merge Functional Cest"/> + <stories value="MQE-433"/> + </annotations> + <before> + <amOnPage url="/beforeUrl" stepKey="before1"/> + </before> + <after> + <amOnPage url="/afterUrl" stepKey="after1"/> + </after> + <fillField stepKey="fillField1" selector="{{SampleSection.mergeElement}}" userInput="{{DefaultPerson.mergedField}}"/> + <fillField stepKey="fillField2" selector="{{SampleSection.newElement}}" userInput="{{DefaultPerson.newField}}" /> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/PageReplacementTest.xml b/dev/tests/verification/TestModule/Test/PageReplacementTest.xml index b6adee5d7..8cd6fe572 100644 --- a/dev/tests/verification/TestModule/Test/PageReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/PageReplacementTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="PageReplacementTest"> <createData entity="simpleData" stepKey="datakey"/> <amOnPage stepKey="noParamPage" url="{{NoParamPage.url}}"/> diff --git a/dev/tests/verification/TestModule/Test/ParameterArrayTest.xml b/dev/tests/verification/TestModule/Test/ParameterArrayTest.xml index e9bef4244..8bb57ae74 100644 --- a/dev/tests/verification/TestModule/Test/ParameterArrayTest.xml +++ b/dev/tests/verification/TestModule/Test/ParameterArrayTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="ParameterArrayTest"> <createData entity="simpleParamData" stepKey="simpleDataKey"/> <searchAndMultiSelectOption selector="#selector" parameterArray="[{{simpleParamData.name}}]" stepKey="xmlSimpleReplace"/> diff --git a/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml b/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml index 4b0f3c902..ba86a1a5d 100644 --- a/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="PersistedReplacementTest"> <before> <createData entity="ReplacementPerson" stepKey="createData1"/> diff --git a/dev/tests/verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml b/dev/tests/verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml index 20a9b6a28..c76409f26 100644 --- a/dev/tests/verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml +++ b/dev/tests/verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="PersistenceActionGroupAppendingTest"> <before> <actionGroup ref="DataPersistenceAppendingActionGroup" stepKey="ACTIONGROUPBEFORE"/> diff --git a/dev/tests/verification/TestModule/Test/PersistenceCustomFieldsTest.xml b/dev/tests/verification/TestModule/Test/PersistenceCustomFieldsTest.xml index c56106693..77a85060b 100644 --- a/dev/tests/verification/TestModule/Test/PersistenceCustomFieldsTest.xml +++ b/dev/tests/verification/TestModule/Test/PersistenceCustomFieldsTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="PersistenceCustomFieldsTest"> <before> <createData entity="DefaultPerson" stepKey="createData1"> diff --git a/dev/tests/verification/TestModule/Test/SampleSuite2Test.xml b/dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalExcludeTest2.xml similarity index 59% rename from dev/tests/verification/TestModule/Test/SampleSuite2Test.xml rename to dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalExcludeTest2.xml index 92f10ddd0..c38915bf4 100644 --- a/dev/tests/verification/TestModule/Test/SampleSuite2Test.xml +++ b/dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalExcludeTest2.xml @@ -5,9 +5,8 @@ * See COPYING.txt for license details. */ --> - <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="additionalExcludeTest2"> <annotations> <group value="exclude"/> @@ -17,10 +16,4 @@ <click stepKey="clickOnSomething" selector=".clickable"/> <fillField stepKey="fillAField" selector=".fillable"/> </test> - <test name="additionalIncludeTest2"> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> </tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalIncludeTest2.xml b/dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalIncludeTest2.xml new file mode 100644 index 000000000..81f6d7c1c --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuite2Test/AdditionalIncludeTest2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="additionalIncludeTest2"> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest.xml deleted file mode 100644 index 921071cfc..000000000 --- a/dev/tests/verification/TestModule/Test/SampleSuiteTest.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="IncludeTest"> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> - <test name="ExcludeTest"> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> - <test name="IncludeTest2"> - <annotations> - <group value="include"/> - </annotations> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> - <test name="additionalTest"> - <annotations> - <group value="include"/> - </annotations> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> - <test name="ExcludeTest2"> - <annotations> - <group value="include"/> - </annotations> - <amOnPage stepKey="testOnPage" url="/someUrl"/> - <see stepKey="seeThePage" selector=".someSelector"/> - <click stepKey="clickOnSomething" selector=".clickable"/> - <fillField stepKey="fillAField" selector=".fillable"/> - </test> -</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest/AdditionalTest.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest/AdditionalTest.xml new file mode 100644 index 000000000..848d45612 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuiteTest/AdditionalTest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="additionalTest"> + <annotations> + <group value="include"/> + </annotations> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest.xml new file mode 100644 index 000000000..0996e4a59 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExcludeTest"> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest2.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest2.xml new file mode 100644 index 000000000..d03b847da --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuiteTest/ExcludeTest2.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="ExcludeTest2"> + <annotations> + <group value="include"/> + </annotations> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest.xml new file mode 100644 index 000000000..b293742c7 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="IncludeTest"> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest2.xml b/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest2.xml new file mode 100644 index 000000000..d6c40fe2d --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SampleSuiteTest/IncludeTest2.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="IncludeTest2"> + <annotations> + <group value="include"/> + </annotations> + <amOnPage stepKey="testOnPage" url="/someUrl"/> + <see stepKey="seeThePage" selector=".someSelector"/> + <click stepKey="clickOnSomething" selector=".clickable"/> + <fillField stepKey="fillAField" selector=".fillable"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml b/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml index 4044a86e3..d87be5d3b 100644 --- a/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml +++ b/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="secretCredentialDataTest"> <createData entity="_defaultProduct" stepKey="createProductWithFieldOverridesUsingHardcodedData1"> <field key="qty">123</field> diff --git a/dev/tests/verification/TestModule/Test/SectionReplacementTest.xml b/dev/tests/verification/TestModule/Test/SectionReplacementTest.xml index 17aeb4d69..3b066fcdf 100644 --- a/dev/tests/verification/TestModule/Test/SectionReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/SectionReplacementTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="SectionReplacementTest"> <click stepKey="selectorReplace" selector="{{SampleSection.simpleElement}}"/> <click stepKey="selectorReplaceTimeout" selector="{{SampleSection.timeoutElement}}"/> diff --git a/dev/tests/verification/TestModule/Test/SkippedTest.xml b/dev/tests/verification/TestModule/Test/SkippedTest.xml deleted file mode 100644 index 7641e270e..000000000 --- a/dev/tests/verification/TestModule/Test/SkippedTest.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> - <test name="SkippedTest"> - <annotations> - <stories value="skipped"/> - <title value="skippedTest"/> - <description value=""/> - <severity value="AVERAGE"/> - <skip> - <issueId value="SkippedValue"/> - </skip> - </annotations> - </test> - <test name="SkippedTestWithHooks"> - <annotations> - <stories value="skippedWithHooks"/> - <title value="skippedTestWithHooks"/> - <description value=""/> - <severity value="AVERAGE"/> - <skip> - <issueId value="SkippedValue"/> - </skip> - </annotations> - <before> - <comment userInput="skippedComment" stepKey="beforeComment"/> - </before> - <after> - <comment userInput="skippedComment" stepKey="afterComment"/> - </after> - </test> - <test name="SkippedTestTwoIssues"> - <annotations> - <stories value="skippedMultiple"/> - <title value="skippedMultipleIssuesTest"/> - <description value=""/> - <severity value="AVERAGE"/> - <skip> - <issueId value="SkippedValue"/> - <issueId value="SecondSkippedValue"/> - </skip> - </annotations> - </test> - <test name="SkippedTestNoIssues"> - <annotations> - <stories value="skippedNo"/> - <title value="skippedNoIssuesTest"/> - <description value=""/> - <severity value="AVERAGE"/> - <group value="skip"/> - </annotations> - </test> -</tests> diff --git a/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTest.xml b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTest.xml new file mode 100644 index 000000000..f0162a562 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="SkippedTest"> + <annotations> + <stories value="skipped"/> + <title value="skippedTest"/> + <description value=""/> + <severity value="AVERAGE"/> + <skip> + <issueId value="SkippedValue"/> + </skip> + </annotations> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestTwoIssues.xml b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestTwoIssues.xml new file mode 100644 index 000000000..66ad090b4 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestTwoIssues.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="SkippedTestTwoIssues"> + <annotations> + <stories value="skippedMultiple"/> + <title value="skippedMultipleIssuesTest"/> + <description value=""/> + <severity value="AVERAGE"/> + <skip> + <issueId value="SkippedValue"/> + <issueId value="SecondSkippedValue"/> + </skip> + </annotations> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestWithHooks.xml b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestWithHooks.xml new file mode 100644 index 000000000..790a44a40 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SkippedTest/SkippedTestWithHooks.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="SkippedTestWithHooks"> + <annotations> + <stories value="skippedWithHooks"/> + <title value="skippedTestWithHooks"/> + <description value=""/> + <severity value="AVERAGE"/> + <skip> + <issueId value="SkippedValue"/> + </skip> + </annotations> + <before> + <comment userInput="skippedComment" stepKey="beforeComment"/> + </before> + <after> + <comment userInput="skippedComment" stepKey="afterComment"/> + </after> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml b/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml index f7fbd8dd6..b464dfc4c 100644 --- a/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml +++ b/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml @@ -6,7 +6,7 @@ */ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="XmlCommentedActionGroupTest"> <annotations> <severity value="CRITICAL"/> diff --git a/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml b/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml index 133588872..1da6a1fc0 100644 --- a/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml +++ b/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml @@ -6,7 +6,7 @@ */ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <test name="XmlCommentedTest"> <annotations> diff --git a/dev/tests/verification/TestModule/Test/XmlDuplicateTest/BasicDupedActionTest.xml b/dev/tests/verification/TestModule/Test/XmlDuplicateTest/BasicDupedActionTest.xml new file mode 100644 index 000000000..19104dbee --- /dev/null +++ b/dev/tests/verification/TestModule/Test/XmlDuplicateTest/BasicDupedActionTest.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="BasicDupedActionTest"> + <before> + <createData entity="simpleData" stepKey="cb1"> + <requiredEntity createDataKey="simpleData2"/> + </createData> + <amOnPage stepKey="aopb1" url="1"/> + <amOnPage stepKey="aopb2" url="2"/> + </before> + <after> + <createData entity="simpleData" stepKey="ca1"> + <requiredEntity createDataKey="simpleData2"/> + </createData> + <amOnPage stepKey="aopf1" url="1"/> + <amOnPage stepKey="aopf2" url="2"/> + </after> + <createData entity="simpleData" stepKey="c1"> + <requiredEntity createDataKey="simpleData2"/> + </createData> + <amOnPage stepKey="aop1" url="1"/> + <amOnPage stepKey="aop2" url="2"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml b/dev/tests/verification/TestModule/Test/XmlDuplicateTest/XmlDuplicateTest.xml similarity index 93% rename from dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml rename to dev/tests/verification/TestModule/Test/XmlDuplicateTest/XmlDuplicateTest.xml index 937c6edba..b24bac3b5 100644 --- a/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml +++ b/dev/tests/verification/TestModule/Test/XmlDuplicateTest/XmlDuplicateTest.xml @@ -5,9 +5,8 @@ * See COPYING.txt for license details. */ --> - <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="XmlDuplicateTest"> <before> <acceptPopup stepKey="ap1"/> @@ -82,14 +81,12 @@ <doubleClick selector="1" stepKey="dblclick2"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop1"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop2"/> - <executeInSelenium function="1" stepKey="executeSelenium1"/> - <executeInSelenium function="1" stepKey="executeSelenium2"/> <executeJS function="1" stepKey="execJS1"/> <executeJS function="1" stepKey="execJS2"/> <fillField stepKey="fill1"/> <fillField stepKey="fill21"/> - <formatMoney stepKey="frmtmoney1"/> - <formatMoney stepKey="frmtmoney12"/> + <formatCurrency userInput="1234.567890" locale="de_DE" currency="EUR" stepKey="frmtmoney1"/> + <formatCurrency userInput="1234.567890" locale="en_US" currency="EUR" stepKey="frmtmoney12"/> <getData entity="1" stepKey="getdata1"/> <getData entity="1" stepKey="getdata12"/> <grabAttributeFrom selector="1" stepKey="grabattribute1"/> @@ -128,10 +125,8 @@ <openNewTab stepKey="newtab12"/> <parseFloat stepKey="parsefloat1"/> <parseFloat stepKey="parsefloat12"/> - <pauseExecution stepKey="pause1"/> - <pauseExecution stepKey="pause12"/> - <performOn selector="1" function="1" stepKey="performon1"/> - <performOn selector="1" function="1" stepKey="performon12"/> + <pause stepKey="pause1"/> + <pause stepKey="pause12"/> <pressKey selector="1" stepKey="press1"/> <pressKey selector="1" stepKey="press12"/> <reloadPage stepKey="reload1"/> @@ -298,14 +293,12 @@ <doubleClick selector="1" stepKey="dblclick2"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop1"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop2"/> - <executeInSelenium function="1" stepKey="executeSelenium1"/> - <executeInSelenium function="1" stepKey="executeSelenium2"/> <executeJS function="1" stepKey="execJS1"/> <executeJS function="1" stepKey="execJS2"/> <fillField stepKey="fill1"/> <fillField stepKey="fill21"/> - <formatMoney stepKey="frmtmoney1"/> - <formatMoney stepKey="frmtmoney12"/> + <formatCurrency userInput="1234.567890" locale="de_DE" currency="EUR" stepKey="frmtmoney1"/> + <formatCurrency userInput="1234.567890" locale="en_US" currency="EUR" stepKey="frmtmoney12"/> <getData entity="1" stepKey="getdata1"/> <getData entity="1" stepKey="getdata12"/> <grabAttributeFrom selector="1" stepKey="grabattribute1"/> @@ -344,10 +337,8 @@ <openNewTab stepKey="newtab12"/> <parseFloat stepKey="parsefloat1"/> <parseFloat stepKey="parsefloat12"/> - <pauseExecution stepKey="pause1"/> - <pauseExecution stepKey="pause12"/> - <performOn selector="1" function="1" stepKey="performon1"/> - <performOn selector="1" function="1" stepKey="performon12"/> + <pause stepKey="pause1"/> + <pause stepKey="pause12"/> <pressKey selector="1" stepKey="press1"/> <pressKey selector="1" stepKey="press12"/> <reloadPage stepKey="reload1"/> @@ -513,14 +504,12 @@ <doubleClick selector="1" stepKey="dblclick2"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop1"/> <dragAndDrop selector1="1" selector2="2" stepKey="dragndrop2"/> - <executeInSelenium function="1" stepKey="executeSelenium1"/> - <executeInSelenium function="1" stepKey="executeSelenium2"/> <executeJS function="1" stepKey="execJS1"/> <executeJS function="1" stepKey="execJS2"/> <fillField stepKey="fill1"/> <fillField stepKey="fill21"/> - <formatMoney stepKey="frmtmoney1"/> - <formatMoney stepKey="frmtmoney12"/> + <formatCurrency userInput="1234.567890" locale="de_DE" currency="EUR" stepKey="frmtmoney1"/> + <formatCurrency userInput="1234.567890" locale="en_US" currency="EUR" stepKey="frmtmoney12"/> <getData entity="1" stepKey="getdata1"/> <getData entity="1" stepKey="getdata12"/> <grabAttributeFrom selector="1" stepKey="grabattribute1"/> @@ -559,10 +548,8 @@ <openNewTab stepKey="newtab12"/> <parseFloat stepKey="parsefloat1"/> <parseFloat stepKey="parsefloat12"/> - <pauseExecution stepKey="pause1"/> - <pauseExecution stepKey="pause12"/> - <performOn selector="1" function="1" stepKey="performon1"/> - <performOn selector="1" function="1" stepKey="performon12"/> + <pause stepKey="pause1"/> + <pause stepKey="pause12"/> <pressKey selector="1" stepKey="press1"/> <pressKey selector="1" stepKey="press12"/> <reloadPage stepKey="reload1"/> @@ -656,26 +643,4 @@ <waitForText stepKey="waittext1"/> <waitForText stepKey="waittext12"/> </test> - - <test name="BasicDupedActionTest"> - <before> - <createData entity="simpleData" stepKey="cb1"> - <requiredEntity createDataKey="simpleData2"/> - </createData> - <amOnPage stepKey="aopb1" url="1"/> - <amOnPage stepKey="aopb2" url="2"/> - </before> - <after> - <createData entity="simpleData" stepKey="ca1"> - <requiredEntity createDataKey="simpleData2"/> - </createData> - <amOnPage stepKey="aopf1" url="1"/> - <amOnPage stepKey="aopf2" url="2"/> - </after> - <createData entity="simpleData" stepKey="c1"> - <requiredEntity createDataKey="simpleData2"/> - </createData> - <amOnPage stepKey="aop1" url="1"/> - <amOnPage stepKey="aop2" url="2"/> - </test> -</tests> \ No newline at end of file +</tests> diff --git a/dev/tests/verification/TestModuleMerged/Data/MergeData.xml b/dev/tests/verification/TestModuleMerged/Data/MergeData.xml index 72d0dca61..531922aed 100644 --- a/dev/tests/verification/TestModuleMerged/Data/MergeData.xml +++ b/dev/tests/verification/TestModuleMerged/Data/MergeData.xml @@ -8,7 +8,7 @@ --> <entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd"> <entity name="DefaultPerson" type="samplePerson"> <data key="mergedField">merged</data> <data key="newField">newField</data> diff --git a/dev/tests/verification/TestModuleMerged/Section/MergeSection.xml b/dev/tests/verification/TestModuleMerged/Section/MergeSection.xml index fb661e906..6bbd862ae 100644 --- a/dev/tests/verification/TestModuleMerged/Section/MergeSection.xml +++ b/dev/tests/verification/TestModuleMerged/Section/MergeSection.xml @@ -7,7 +7,7 @@ --> <sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd"> <section name="SampleSection"> <element name="oneParamElement" type="button" selector="#element .{{var1}}" parameterized="true"/> <element name="twoParamElement" type="button" selector="#{{var1}} .{{var2}}" parameterized="true"/> diff --git a/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest.xml b/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/BasicMergeTest.xml similarity index 79% rename from dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest.xml rename to dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/BasicMergeTest.xml index 912854cc4..807258b0f 100644 --- a/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest.xml +++ b/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/BasicMergeTest.xml @@ -5,9 +5,8 @@ * See COPYING.txt for license details. */ --> - <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="BasicMergeTest"> <annotations> <group value="mergeTest"/> @@ -26,11 +25,4 @@ <click stepKey="step10" selector="#step10MergedInResult"/> <actionGroup ref="FunctionalActionGroupWithData" stepKey="step8Merge" after="step7Merge"/> </test> - <test name="MergeSkip"> - <annotations> - <skip> - <issueId value="Issue5"/> - </skip> - </annotations> - </test> </tests> diff --git a/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/MergeSkip.xml b/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/MergeSkip.xml new file mode 100644 index 000000000..5c9e189c3 --- /dev/null +++ b/dev/tests/verification/TestModuleMerged/Test/MergeFunctionalTest/MergeSkip.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="MergeSkip"> + <annotations> + <skip> + <issueId value="Issue5"/> + </skip> + </annotations> + </test> +</tests> diff --git a/dev/tests/verification/TestModuleMerged/Test/MergeXmlDuplicateTest.xml b/dev/tests/verification/TestModuleMerged/Test/MergeXmlDuplicateTest.xml index 2d99d5cbc..c9c731134 100644 --- a/dev/tests/verification/TestModuleMerged/Test/MergeXmlDuplicateTest.xml +++ b/dev/tests/verification/TestModuleMerged/Test/MergeXmlDuplicateTest.xml @@ -7,7 +7,7 @@ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="BasicDupedActionTest"> <before> <createData entity="simpleData" stepKey="cb3"> diff --git a/dev/tests/verification/Tests/BasicCestGenerationTest.php b/dev/tests/verification/Tests/BasicCestGenerationTest.php index 793b2a502..39802c50d 100644 --- a/dev/tests/verification/Tests/BasicCestGenerationTest.php +++ b/dev/tests/verification/Tests/BasicCestGenerationTest.php @@ -10,6 +10,7 @@ class BasicCestGenerationTest extends MftfTestCase { /** + * BasicFunctionalTest: * Tests flat generation of a hardcoded test file with no external references. * * @throws \Exception @@ -20,6 +21,30 @@ public function testBasicGeneration() $this->generateAndCompareTest('BasicFunctionalTest'); } + /** + * MergeMassViaInsertAfter: + * Tests flat generation of a hardcoded test file with no external references. + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergeMassViaInsertAfter() + { + $this->generateAndCompareTest('MergeMassViaInsertAfter'); + } + + /** + * MergeMassViaInsertBefore: + * Tests flat generation of a hardcoded test file with no external references. + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testMergeMassViaInsertBefore() + { + $this->generateAndCompareTest('MergeMassViaInsertBefore'); + } + /** * Tests flat generation of a hardcoded test file with no external references and with XML comments in: * - root `tests` element diff --git a/dev/tests/verification/Tests/ExecuteInSeleniumTest.php b/dev/tests/verification/Tests/GroupSkipGenerationTest.php similarity index 60% rename from dev/tests/verification/Tests/ExecuteInSeleniumTest.php rename to dev/tests/verification/Tests/GroupSkipGenerationTest.php index 36532b362..ad0ba6ec0 100644 --- a/dev/tests/verification/Tests/ExecuteInSeleniumTest.php +++ b/dev/tests/verification/Tests/GroupSkipGenerationTest.php @@ -7,16 +7,16 @@ use tests\util\MftfTestCase; -class ExecuteInSeleniumTest extends MftfTestCase +class GroupSkipGenerationTest extends MftfTestCase { /** - * Tests generation of executeInSelenium action. + * Tests group skip test generation * * @throws \Exception * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException */ - public function testExecuteInSeleniumTest() + public function testGroupSkipGenerationTest() { - $this->generateAndCompareTest('ExecuteInSeleniumTest'); + $this->generateAndCompareTest('GroupSkipGenerationTest'); } } diff --git a/dev/tests/verification/Tests/SchemaValidationTest.php b/dev/tests/verification/Tests/SchemaValidationTest.php index 92442bd37..c6187974c 100644 --- a/dev/tests/verification/Tests/SchemaValidationTest.php +++ b/dev/tests/verification/Tests/SchemaValidationTest.php @@ -35,7 +35,7 @@ public function testInvalidTestSchema() * After method functionality * @return void */ - protected function tearDown() + protected function tearDown(): void { AspectMock::clean(); } diff --git a/dev/tests/verification/Tests/SkippedGenerationTest.php b/dev/tests/verification/Tests/SkippedGenerationTest.php index 2d259e02c..2bc73986a 100644 --- a/dev/tests/verification/Tests/SkippedGenerationTest.php +++ b/dev/tests/verification/Tests/SkippedGenerationTest.php @@ -41,15 +41,4 @@ public function testMultipleSkippedIssuesGeneration() { $this->generateAndCompareTest('SkippedTestTwoIssues'); } - - /** - * Tests skipped test generation with no specified issues. Will be deprecated after MFTF 3.0.0 - * - * @throws \Exception - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException - */ - public function testSkippedNoIssueGeneration() - { - $this->generateAndCompareTest('SkippedTestNoIssues'); - } } diff --git a/dev/tests/verification/Tests/SuiteGenerationTest.php b/dev/tests/verification/Tests/SuiteGenerationTest.php index 485ef6411..4a8371692 100644 --- a/dev/tests/verification/Tests/SuiteGenerationTest.php +++ b/dev/tests/verification/Tests/SuiteGenerationTest.php @@ -39,7 +39,7 @@ class SuiteGenerationTest extends MftfTestCase /** * Set up config.yml for testing */ - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { // destroy _generated if it exists if (file_exists(self::GENERATE_RESULT_DIR)) { @@ -47,7 +47,7 @@ public static function setUpBeforeClass() } } - public function setUp() + public function setUp(): void { // copy config yml file to test dir $fileSystem = new \Symfony\Component\Filesystem\Filesystem(); @@ -118,10 +118,10 @@ public function testSuiteGenerationParallel() $groupName = 'functionalSuite1'; $expectedGroups = [ - 'functionalSuite1_0', - 'functionalSuite1_1', - 'functionalSuite1_2', - 'functionalSuite1_3' + 'functionalSuite1_0_G', + 'functionalSuite1_1_G', + 'functionalSuite1_2_G', + 'functionalSuite1_3_G' ]; $expectedContents = [ @@ -392,7 +392,7 @@ public function testSuiteCommentsGeneration() * revert any changes made to config.yml * remove _generated directory */ - public function tearDown() + public function tearDown(): void { DirSetupUtil::rmdirRecursive(self::GENERATE_RESULT_DIR); @@ -406,7 +406,7 @@ public function tearDown() /** * Remove yml if created during tests and did not exist before */ - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { TestLoggingUtil::getInstance()->clearMockLoggingUtil(); } diff --git a/docs/backward-incompatible-changes.md b/docs/backward-incompatible-changes.md new file mode 100644 index 000000000..746e4546b --- /dev/null +++ b/docs/backward-incompatible-changes.md @@ -0,0 +1,163 @@ +# MFTF 3.0.0 backward incompatible changes + +This page highlights backward incompatible changes between releases that have a major impact and require detailed explanation and special instructions to ensure third-party tests continue working with Magento core tests. + +## Minimum supported PHP version changes + +We changed the minimum PHP version requirement from 7.0 to 7.3. Because of the PHP version requirement change, this MFTF version only supports Magento 2.4 or later. + +## Folder structure changes + +We removed support to read test modules from the deprecated path `dev/tests/acceptance/tests/functional/Magento/FunctionalTest`. If there are test modules in this path, they should be moved to `dev/tests/acceptance/tests/functional/Magento`. + +## XSD schema changes + +- Files under test modules `ActionGroup`, `Page`, `Section`, `Test` and `Suite` only support a single entity per file. +- The `file` attribute from `<module>` has been removed from the suite schema. `<module file=""/>` is no longer supported in suites. +- Metadata filename format changed to ***`*Meta.xml`***. +- Only nested assertion syntax will be supported. See the [assertions page](./docs/test/assertions.md) for details. Here is an example of the nested assertion syntax: + ```xml + <assertEquals stepKey="assertAddressOrderPage"> + <actualResult type="const">$billingAddressOrderPage</actualResult> + <expectedResult type="const">$shippingAddressOrderPage</expectedResult> + </assertEquals> + ``` + +### Upgrading tests to the new schema + +The following table lists the upgrade scripts that are available to upgrade tests to the new schema. + +| Script name | Description | +|-----------------------|-----------------------------------------------------------------------------------------------------------| +|`splitMultipleEntitiesFiles`| Splits files that have multiple entities into multiple files with one entity per file. | +|`upgradeAssertionSchema`| Updates assert actions that uses the old assertion syntax into the new nested syntax.| +|`renameMetadataFiles`| Renames Metadata filenames to `*Meta.xml`.| +|`removeModuleFileInSuiteFiles`| Removes occurrences of `<module file=""/>` from all `<suite>`s.| +|`removeUnusedArguments`| Removes unused arguments from action groups.| +|`upgradeTestSchema`| Replaces relative schema paths to URN in test files.| + +To run the upgrade tests: + +1. Run `bin/mftf reset --hard` to remove old generated configurations. +1. Run `bin/mftf build:project` to generate new configurations. +1. Run `bin/mftf upgrade:tests`. [See command page for details](./docs/commands/mftf.md#upgradetests). +1. Lastly, try to generate all tests. Tests should all be generated as a result of the upgrades. If not, the most likely issue will be a changed XML schema. Check error messaging and search your codebase for the attributes listed. + +## MFTF commands + +`--debug` option `NONE` removed for strict schema validation. Ensure there are no schema validation errors in test modules before running MFTF commands. + +## MFTF actions + +### `executeInSelenium` and `performOn` removed + +**Action**: Deprecated actions `executeInSelenium` and `performOn` are removed in favor of new action `helper`. + +**Reason**: `executeInSelenium` and `performOn` allowed custom PHP code to be written inline inside of XML files which was difficult to maintain, troubleshoot, and modify. + +**Details**: + +The `helper` allows test writers to solve advanced requirements beyond what MFTF offers out of the box. See [custom-helpers](./docs/custom-helpers.md) for more information on usage. + +Here is an example of using `helper` in place of `executeSelenium` to achieve same workflow. + +Old usage: + +```xml +<executeInSelenium function="function ($webdriver) use ($I) { + $heading = $webdriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath('//div[contains(@class, \'inline-wysiwyg\')]//h2')); + $actions = new \Facebook\WebDriver\Interactions\WebDriverActions($webdriver); + $actions->moveToElement($heading, {{TinyMCEPartialHeadingSelection.startX}}, {{TinyMCEPartialHeadingSelection.startY}}) + ->clickAndHold() + ->moveToElement($heading, {{TinyMCEPartialHeadingSelection.endX}}, {{TinyMCEPartialHeadingSelection.endY}}) + ->release() + ->perform(); + }" stepKey="selectHeadingTextInTinyMCE"/> +``` + +New usage: + +```xml +<helper class="\Magento\PageBuilder\Test\Mftf\Helper\SelectText" method="selectText" stepKey="selectHeadingTextInTinyMCE"> + <argument name="context">//div[contains(@class, 'inline-wysiwyg')]//h2</argument> + <argument name="startX">{{TinyMCEPartialHeadingSelection.startX}}</argument> + <argument name="startY">{{TinyMCEPartialHeadingSelection.startY}}</argument> + <argument name="endX">{{TinyMCEPartialHeadingSelection.endX}}</argument> + <argument name="endY">{{TinyMCEPartialHeadingSelection.endY}}</argument> +</helper> +``` + +### `pauseExecution` removed + +**Action**: `pauseExecution` is removed in favor of `pause`. + +**Reason**: `[WebDriver]pauseExecution` is removed in Codeception 3 in favor of `I->pause()`. + +**Details**: + +See the [actions page for details](./docs/test/actions.md#pause). Here is a usage example: + +```xml +<pause stepKey="pauseExecutionKey"/> +``` + +### Removed assert actions + +**Action**: Assert actions `assertInternalType`, `assertNotInternalType` and `assertArraySubset` are removed. + +**Reason**: PHPUnit 9 has dropped support for these assertions. + +### Updated assert actions + +**Action**: The `delta` attribute has been removed from `assertEquals` and `assertNotEquals`. Instead, new assert actions have been introduced: + + - `assertEqualsWithDelta` + - `assertNotEqualsWithDelta` + - `assertEqualsCanonicalizing` + - `assertNotEqualsCanonicalizing` + - `assertEqualsIgnoringCase` + - `assertNotEqualsIgnoringCase` + +**Reason**: PHPUnit 9 has dropped support for optional parameters for `assertEquals` and `assertNotEquals` and has introduced these new assertions. + +**Details**: + +Usage of `assertEquals` or `assertNotEquals` with a specified `delta`, should be replaced with appropriate assertion from the above list. + +### `assertContains` supports only iterable haystacks + +**Action**: `assertContains` and `assertNotContains` now only supports iterable haystacks. These assert actions have been added to work with string haystacks: + +- `assertStringContainsString` +- `assertStringNotContainsString` +- `assertStringContainsStringIgnoringCase` +- `assertStringNotContainsStringIgnoringCase` + +**Reason**: With PHPUnit 9, `assertContains` and `assertNotContains` only allows iterable haystacks. New assertions have been introduced to support string haystacks. + +**Details**: + +Usages of `assertContains` and `assertNotContains` with string haystacks should be replaced with appropriate assertion from the above list. + +Usage example for string haystacks: + +```xml +<assertStringContainsString stepKey="assertDiscountOnPrice2"> + <actualResult type="const">$grabSimpleProdPrice2</actualResult> + <expectedResult type="string">$110.70</expectedResult> +</assertStringContainsString> +``` + +### `formatMoney` removed + +**Action**: `formatMoney` has been removed in favor of `formatCurrency`. + +**Reason**: PHP 7.4 has deprecated use of `formatMoney`. + +**Details**: Format input to specified currency according to the locale specified. + +Usage example: + +```xml +<formatCurrency userInput="1234.56789000" locale="de_DE" currency="USD" stepKey="usdInDE"/> +``` diff --git a/docs/best-practices.md b/docs/best-practices.md index 613f398ca..0ce9448cb 100644 --- a/docs/best-practices.md +++ b/docs/best-practices.md @@ -45,7 +45,8 @@ You can also help with MFTF Test Migration to get the experience and valuable fe ## Action group 1. [Action group] names should be sufficiently descriptive to inform a test writer of what the action group does and when it should be used. Add additional explanation in annotations if needed. -1. Provide default values for the arguments that apply to your most common case scenarios. +2. Provide default values for the arguments that apply to your most common case scenarios. +3. One `<actionGroup>` tag is allowed per action group XML file. ## `actionGroups` vs `extends` @@ -150,7 +151,8 @@ Use a lower case first letter for: ## Page object -Use [parameterized selectors] for constructing a selector when test specific or runtime generated information is needed. +1. One `<page>` tag is allowed per page XML file. +2. Use [parameterized selectors] for constructing a selector when test-specific or runtime-generated information is needed. Do not use them for static elements. <span class="color:red"> @@ -188,6 +190,7 @@ Define these three elements and reference them by name in the tests. It helps to inform the reader of what you are testing and to yield a more descriptive Allure report. * Explain in comments unclear or tricky test steps. 1. Refer to [sections] instead of writing selectors. +1. One `<test>` tag is allowed per test XML file. ## Test step merging order diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md index 00924671f..bc2e5c0ec 100644 --- a/docs/commands/mftf.md +++ b/docs/commands/mftf.md @@ -28,7 +28,7 @@ vendor/bin/mftf build:project vendor/bin/mftf build:project --upgrade ``` -Upgrades the existing MFTF tests after the MFTF major upgrade. +Upgrades all installed MFTF tests after a major MFTF upgrade. ### Generate all tests @@ -89,14 +89,6 @@ vendor/bin/mftf run:failed This command cleans up the previously generated tests; generates and runs the tests listed in `dev/tests/acceptance/tests/_output/failed`. For more details about `failed`, refer to [Reporting][]. -### Generate documentation for action groups - -```bash -vendor/bin/mftf generate:docs -``` - -This command generates documentation for action groups. - ## Reference ### `build:project` @@ -115,7 +107,7 @@ vendor/bin/mftf build:project [--upgrade] [config_param_options] | Option | Description | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `-u`, `--upgrade` | Upgrades existing MFTF tests according to requirements of the last major release. Specifying this flag upgrades only those tests in the default location. Example: `build:project --upgrade`. | +| `-u`, `--upgrade` | Upgrades all installed MFTF tests according to requirements of the last major release. Specifying this flag upgrades only those tests in the default location. Example: `build:project --upgrade`. | You can include options to set configuration parameter values for your environment since the project build process also [sets up the environment][setup]. @@ -164,7 +156,7 @@ vendor/bin/mftf generate:tests [option] [<test name>] [<test name>] [--remove] | `-i,--time` | Set time in minutes to determine the group size when `--config=parallel` is used. The __default value__ is `10`. Example: `generate:tests --config=parallel --time=15`| | `--tests` | Defines the test configuration as a JSON string.| | `--allow-skipped` | Allows MFTF to generate and run tests marked with `<skip>.`| -| `--debug or --debug=[<none>]`| Performs schema validations on XML files. <br/> DEFAULT: `generate:tests` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. <br/> DEVELOPER: `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred) when test generation fails because of an invalid XML schema. This option takes extra processing time. Use it after test generation has failed once.<br/>NONE: `--debug=none` skips debugging during test generation. Added for backward compatibility, it will be removed in the next MAJOR release.<br/>| +| `--debug` | Performs schema validations on XML files. <br/> DEFAULT: `generate:tests` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. <br/> DEVELOPER: `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred) when test generation fails because of an invalid XML schema. This option takes extra processing time. Use it after test generation has failed once.<br/>| | `-r,--remove`| Removes the existing generated suites and tests cleaning up the `_generated` directory before the actual run. For example, `generate:tests SampleTest --remove` cleans up the entire `_generated` directory and generates `SampleTest` only.| #### Examples of the JSON configuration @@ -270,32 +262,6 @@ vendor/bin/mftf generate:urn-catalog [--force] [<path to the directory with misc vendor/bin/mftf generate:urn-catalog .idea/ ``` -### `generate:docs` - -#### Description - -Generates documentation that lists all action groups available in the codebase. -The default path is `<projectRoot>/dev/tests/docs/documentation.md`. - -#### Usage - -```bash -vendor/bin/mftf generate:docs [--clean] [--output=/path/to/alternate/dir] -``` - -#### Options - -| Option | Description | -| ------------- | --------------------------------------------------------------------- | -| `-c, --clean` | Overwrites previously existing documentation | -| `-o, --output` | Changes the default output directory to a user specified directory | - -#### Example - -```bash -vendor/bin/mftf generate:docs --clean -``` - ### `reset` #### Description @@ -337,7 +303,7 @@ vendor/bin/mftf run:group [--skip-generate|--remove] [--] <group1> [<group2>] | --------------------- | --------------------------------------------------------------------------------------------------------- | | `-k, --skip-generate` | Skips generating from the source XML. Instead, the command executes previously-generated groups of tests. | | `-r, --remove` | Removes previously generated suites and tests before the actual generation and run. | -| `--debug or --debug=[<none>]`| Performs schema validations on XML files. `run:group` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred). `--debug=none` skips debugging during test run. Added for backward compatibility, it will be removed in the next MAJOR release.| +| `--debug` | Performs schema validations on XML files. `run:group` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred).| #### Examples @@ -369,7 +335,7 @@ vendor/bin/mftf run:test [--skip-generate|--remove] [--] <name1> [<name2>] |-----------------------|-----------------------------------------------------------------------------------------------------------| | `-k, --skip-generate` | Skips generating from the source XML. Instead, the command executes previously-generated groups of tests. | | `-r, --remove` | Remove previously generated suites and tests. | -| `--debug or --debug=[<none>]`| Performs schema validations on XML files. `run:test` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred). `--debug=none` skips debugging during test run. Added for backward compatibility, it will be removed in the next MAJOR release. +| `--debug` | Performs schema validations on XML files. `run:test` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred).| #### Examples @@ -419,7 +385,7 @@ vendor/bin/mftf run:failed | Option | Description | |-----------------------|-----------------------------------------------------------------------------------------------------------| -| `--debug or --debug=[<none>]`| Performs schema validations on XML files. `run:failed` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred). Use it after test run has failed once. `--debug=none` skips debugging during test run. Added for backward compatibility, it will be removed in the next MAJOR release.| +| `--debug` | Performs schema validations on XML files. `run:failed` implicitly performs schema validation on merged files. It does not indicate the file name where the error is encountered. `--debug` performs per-file validation and returns additional debug information (such as the filename where an error occurred). Use it after test run has failed once.| #### Examples @@ -465,7 +431,13 @@ The example parameters are taken from the `etc/config/.env.example` file. ### `static-checks` Runs all or specific MFTF static-checks on the test codebase that MFTF is currently attached to. -If no script name argument is specified, all existing static check scripts will run. +Behavior for determining what tests to run is as follows: + +* If test names are specified, only those tests are run. +* If no test names are specified, tests are run according to `staticRuleset.json`. +* If no `staticRuleset.json` is found, all tests are run. + +Static checks errors are written to *.txt files under TEST_BP/tests/_output/static-results/ #### Usage @@ -473,6 +445,12 @@ If no script name argument is specified, all existing static check scripts will vendor/bin/mftf static-checks [<names>]... ``` +#### Options + +| Option | Description | +|-----------------------|-----------------------------------------------------------------------------------------------------------| +| `-p, --path` | Path to a MFTF test module to run "deprecatedEntityUsage" static check script. Option is ignored by other static check scripts. + #### Examples To check what existing static check scripts are available @@ -492,33 +470,83 @@ To run specific static check scripts ```bash vendor/bin/mftf static-checks testDependencies ``` + ```bash vendor/bin/mftf static-checks actionGroupArguments ``` + +```bash +vendor/bin/mftf static-checks deprecatedEntityUsage +``` + +```bash +vendor/bin/mftf static-checks annotations +``` + +```bash +vendor/bin/mftf static-checks deprecatedEntityUsage -p path/to/mftf/test/module +``` + ```bash vendor/bin/mftf static-checks testDependencies actionGroupArguments ``` #### Existing static checks -* Test Dependency: Checks that test dependencies do not violate Magento module's composer dependencies. -* Action Group Unused Arguments: Checks that action groups do not have unused arguments. - +| Argument | Description | +|-----------------------|-----------------------------------------------------------------------------------------------------------| +|`testDependencies` | Checks that test dependencies do not violate Magento module's composer dependencies.| +|`actionGroupArguments` | Checks that action groups do not have unused arguments.| +|`deprecatedEntityUsage`| Checks that deprecated test entities are not being referenced.| +|`annotations`| Checks various details of test annotations, such as missing annotations or duplicate annotations.| + +#### Defining ruleset + +The `static-checks` command will look for a `staticRuleset.json` file under either: + +* `dev/tests/acceptance/staticRuleset.json`, if embedded with Magento2 +* `dev/staticRuleset.json`, if standalone + +This file works as the default configuration to easily allow for the integration of `static-checks` in a CI environment. +Currently, the ruleset only defines the tests to run. Here is an example of the expected format: + +```json +{ + "tests": [ + "actionGroupArguments", + "anotherTest" + ] +} +``` + ### `upgrade:tests` -Applies all the MFTF major version upgrade scripts to test components in the given path (`test.xml`, `data.xml`, etc). +When the path argument is specified, this `upgrade` command applies all the major version MFTF upgrade scripts to a `Test Module` in the given path. +Otherwise, it will apply all the major version MFTF upgrade scripts to all installed test components. + +`Test Module` should have the directory structure of ActionGroup, Data, Metadata, Page, Section, Test, and Suite. + +**Note**: + +The upgrade scripts are meant to be used for Test Modules under source code control. If you have old versions of test modules under vendor, those test modules will get upgraded #### Usage ```bash -vendor/bin/mftf upgrade:tests <path> +vendor/bin/mftf upgrade:tests [<path>] ``` -`<path>` is the path that contains MFTF test components that need to be upgraded. +`<path>` is the path to a MFTF `Test Module` that needs to be upgraded. The command searches recursively for any `*.xml` files to upgrade. #### Examples +To upgrade all installed MFTF tests: + +```bash +vendor/bin/mftf upgrade:tests +``` + To upgrade all test components inside modules in the `dev/tests/acceptance/tests/` directory: ```bash diff --git a/docs/configuration.md b/docs/configuration.md index a7b81c7c9..b16f85d8f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -224,15 +224,15 @@ Example: TESTS_MODULE_PATH=~/magento2/dev/tests/acceptance/tests/functional/Magento/FunctionalTest ``` -### MODULE_WHITELIST +### MODULE_ALLOWLIST Use for a new module. -When adding a new directory at `Magento/FunctionalTest`, add the directory name to `MODULE_WHITELIST` to enable the MFTF to process it. +When adding a new directory at `Magento/FunctionalTest`, add the directory name to `MODULE_ALLOWLIST` to enable the MFTF to process it. Example: ```conf -MODULE_WHITELIST=Magento_Framework,Magento_ConfigurableProductWishlist,Magento_ConfigurableProductCatalogSearch +MODULE_ALLOWLIST=Magento_Framework,Magento_ConfigurableProductWishlist,Magento_ConfigurableProductCatalogSearch ``` ### MAGENTO_CLI_COMMAND_PATH @@ -309,6 +309,20 @@ Example: CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE=default ``` +### VERBOSE_ARTIFACTS + +Determines if passed tests should still have all their Allure artifacts. These artifacts include `.txt` attachments for `dontSee` actions and `createData` actions. + +If enabled, all tests will have all of their normal Allure artifacts. + +If disabled, passed tests will have their Allure artifacts trimmed. Failed tests will still contain all their artifacts. + +This is set `false` by default. + +```conf +VERBOSE_ARTIFACTS=true +``` + ### ENABLE_BROWSER_LOG Enables addition of browser logs to Allure steps @@ -317,14 +331,24 @@ Enables addition of browser logs to Allure steps ENABLE_BROWSER_LOG=true ``` -### BROWSER_LOG_BLACKLIST +### SELENIUM_CLOSE_ALL_SESSIONS + +Forces MFTF to close all Selenium sessions after running a suite. + +Use this if you're having issues with sessions hanging in an MFTF suite. + +```conf +SELENIUM_CLOSE_ALL_SESSIONS=true +``` + +### BROWSER_LOG_BLOCKLIST -Blacklists types of browser log entries from appearing in Allure steps. +Blocklists types of browser log entries from appearing in Allure steps. Denoted in browser log entry as `"SOURCE": "type"`. ```conf -BROWSER_LOG_BLACKLIST=other,console-api +BROWSER_LOG_BLOCKLIST=other,console-api ``` ### WAIT_TIMEOUT diff --git a/docs/configure-2fa.md b/docs/configure-2fa.md new file mode 100644 index 000000000..f50838f0c --- /dev/null +++ b/docs/configure-2fa.md @@ -0,0 +1,49 @@ +# Configuring MFTF for Two-Factor Authentication (2FA) + +Using two-factor authentication (2FA) with MFTF is possible with some configurations settings in Magento. +In this document, we will use Google as the authentication provider. + +## Configure Magento {#config-magento-2fa} + +To prepare Magento for MFTF testing when 2FA is enabled, set the following configurations through the Magento CLI. + +First, select `Google Authenticator` as Magento's 2FA provider: + +```bash +bin/magento config:set twofactorauth/general/force_providers google +``` + +Now set the OTP window to `60` seconds: + +```bash +bin/magento config:set twofactorauth/google/otp_window 60 +``` + +Set a base32-encoded `secret` for `Google Authenticator` to generate a OTP for the default admin user that you set for `MAGENTO_ADMIN_USERNAME` in `.env`: + +```bash +bin/magento security:tfa:google:set-secret <MAGENTO_ADMIN_USERNAME> <OTP_SHARED_SECRET> +``` + +## Configure the MFTF {#config-mftf-2fa} + +Save the same base32-encoded `secret` in a MFTF credential storage, e.g. `.credentials` file, `HashiCorp Vault` or `AWS Secrets Manager`. +More details are [here](./credentials.md). + +The path of the `secret` should be: + +```conf +magento/tfa/OTP_SHARED_SECRET +``` + +## GetOTP {#getOTP} + +A one-time password (OTP) is required when an admin user logs into the Magento admin. +Use the action `getOTP` [Reference](./test/actions.md#getotp) to generate the code and use it for the `Authenticator code` text field in 2FA - Google Auth page. + +Note: +You will need to set the `secret` for any non-default admin users first, before using `getOTP`. For example: + +```xml +<magentoCLI command="security:tfa:google:set-secret admin2 {{_CREDS.magento/tfa/OTP_SHARED_SECRET}}" stepKey="setSecret"/> +``` diff --git a/docs/custom-helpers.md b/docs/custom-helpers.md new file mode 100644 index 000000000..bf1ebc572 --- /dev/null +++ b/docs/custom-helpers.md @@ -0,0 +1,129 @@ +# Custom Helpers + +<div class="bs-callout-warning"> +Due to complexity, you should only write new custom helpers as a last resort, after trying to implement your test using built-in actions. +</div> + +Custom Helpers allow test writers to write custom test actions to solve advanced requirements beyond what MFTF offers out of the box. + +In MFTF version 3.0.0, the following test actions were removed: + +* `<executeInSelenium>` +* `<performOn>` + +These actions were removed because they allowed custom PHP code to be written inline inside of XML files. This code was difficult to read. It had no proper syntax highlighting and no linting. It was difficult to maintain, troubleshoot, and modify. + +However, sometimes custom logic beyond what MFTF offers is necessary so we have provided an alternative solution: the `<helper>` action. + +## Example + +Custom helpers are implemented in PHP files that must be placed in this directory: + +```text +<ModuleName>/Test/Mftf/Helper +``` + +This custom helper selects text on the page with this approach: + +1. Move to a very specific X,Y starting position. +1. Click and hold the mouse button down. +1. Move to another specific X,Y position. +1. Release the mouse button. + +This functionality is used to select text on the page and cannot be accomplished using built-in test actions. + +### PHP File + +```php +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\PageBuilder\Test\Mftf\Helper; + +use Magento\FunctionalTestingFramework\Helper\Helper; + +/** + * Class SelectText provides an ability to select needed text. + */ +class SelectText extends Helper +{ + /** + * Select needed text. + * + * @param string $context + * @param int $startX + * @param int $startY + * @param int $endX + * @param int $endY + * @return void + */ + public function selectText(string $context, int $startX, int $startY, int $endX, int $endY) + { + try { + /** @var \Magento\FunctionalTestingFramework\Module\MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + + $contextElement = $webDriver->webDriver->findElement(\Facebook\WebDriver\WebDriverBy::xpath($context)); + $actions = new \Facebook\WebDriver\Interactions\WebDriverActions($webDriver->webDriver); + $actions->moveToElement($contextElement, $startX, $startY) + ->clickAndHold() + ->moveToElement($contextElement, $endX, $endY) + ->release() + ->perform(); + } catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } +} +``` + +### Notes about this PHP file + +The following details are important about the above file: + +1. The `namespace` must match the file location: `namespace Magento\PageBuilder\Test\Mftf\Helper;` +2. The class must `extends Helper` and have the corresponding `use` statement to match. +3. You may access the WebDriver object via `$this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')`. +4. You may implement multiple related methods within the same class. +5. Specify the correct function argument types to match the type of values you want to pass in. In this case, we specified `string $context, int $startX, int $startY, int $endX, int $endY`. In the XML we will match these types. + +You should follow the same patterns in any custom helpers that you write yourself, but you may implement any logic or iteration that you need to solve for your use case. + +### Referencing in a test + +Once you have implemented something like the above PHP file, reference it in a test: + +```xml +<helper class="\Magento\PageBuilder\Test\Mftf\Helper\SelectText" method="selectText" stepKey="selectHeadingTextInTinyMCE"> + <argument name="context">//div[contains(@class, 'inline-wysiwyg')]//h2</argument> + <argument name="startX">{{TinyMCEPartialHeadingSelection.startX}}</argument> + <argument name="startY">{{TinyMCEPartialHeadingSelection.startY}}</argument> + <argument name="endX">{{TinyMCEPartialHeadingSelection.endX}}</argument> + <argument name="endY">{{TinyMCEPartialHeadingSelection.endY}}</argument> +</helper> +``` + +### Notes about the XML + +1. Specify an argument value for every argument that matches our PHP implementation. This allows us to pass other test data to the Custom Helper. +1. The `class` attribute matches the namespace specified in the PHP file. +1. Specify the method from the class via the `method` attribute. +1. If the function has a return value, it will be assigned to the `stepKey` variable. In this case, `$selectHeadingTextInTinyMCE` holds the return value. +1. The types of argument values must match the PHP implementation's expected types. + +## Key takeaways + +Custom helpers allow you to solve complex use cases such as conditional logic, iteration, or complex WebDriver usage. + +With access to the WebDriver object, you have a lot of flexibility available to you. See the [Codeception WebDriver](https://github.com/Codeception/module-webdriver/blob/master/src/Codeception/Module/WebDriver.php) for technical details and functionality available for use. + +A custom helper is written in a PHP file and then referenced in test XML, like other actions. + +You should only use these as a last resort after trying to implement your test using built-in actions. + +## References + +[Codeception WebDriver source code](https://github.com/Codeception/module-webdriver/blob/master/src/Codeception/Module/WebDriver.php) - Reference for using the WebDriver Object diff --git a/docs/data.md b/docs/data.md index fa4c90dcf..8b0a86e3d 100644 --- a/docs/data.md +++ b/docs/data.md @@ -276,6 +276,11 @@ Attributes|Type|Use|Description `<item>` is an individual piece of data to be passed in as part of the parent `<array>` type. +Attributes|Type|Use|Description +---|---|---|--- +`name`|string|optional|Key attribute of <item/> entity in which to assign a value. By default numeric key will be generated. + + <!-- Link Definitions --> [`<array>`]: #array-tag [`<data>`]: #data-tag diff --git a/docs/getting-started.md b/docs/getting-started.md index 8bdb7d5a1..ec0afba0d 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -109,6 +109,10 @@ Clean the cache after changing the configuration values: bin/magento cache:clean config full_page ``` +### Testing with the Magento Two-Factor Authentication (2FA) extension {#2fa} + +If the Magento instance under test has the [Magento Two-Factor Authentication (2FA) extension][] installed and enabled, additional configurations is needed to run MFTF tests. Learn more in [Configure MFTF for Magento with Two-Factor Authentication (2FA)](./configure-2fa.md). + ### Webserver configuration {#web-server-configuration} The MFTF does not support executing CLI commands if your web server points to `<MAGE_ROOT_DIR>/pub` directory as recommended in the [Installation Guide][Installation Guide docroot]. For the MFTF to execute the CLI commands, the web server must point to the Magento root directory. @@ -353,3 +357,4 @@ allure serve dev/tests/_output/allure-results/ [test suite]: suite.html [Find your MFTF version]: introduction.html#find-your-mftf-version [Installation Guide docroot]: https://devdocs.magento.com/guides/v2.3/install-gde/tutorials/change-docroot-to-pub.html +[Magento Two-Factor Authentication (2FA) extension]: https://devdocs.magento.com/guides/v2.3/security/two-factor-authentication.html diff --git a/docs/guides/git-vs-composer-install.md b/docs/guides/git-vs-composer-install.md index 3a45e3a68..fd9006cc1 100644 --- a/docs/guides/git-vs-composer-install.md +++ b/docs/guides/git-vs-composer-install.md @@ -55,6 +55,8 @@ The file structure under both paths is the same: │   └── ... ├── Section │   └── ... +├── Suite +│   └── ... └── Test └── ... ``` @@ -65,6 +67,7 @@ With either type of installation, all tests and test data are read and merged by 1. `<magento_root>/app/code/<vendor_name>/<module_name>/Test/Mftf/` 1. `<magento_root>/vendor/<vendor_name>/<module_name>/Test/Mftf/` +1. `<magento_root>/dev/tests/acceptance/tests/functional/<vendor_name>/<module_name>/` ## Conclusion diff --git a/docs/introduction.md b/docs/introduction.md index 53b763d8c..5a75777af 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,6 +1,13 @@ # Introduction to the Magento Functional Testing Framework -The Magento Functional Tesitng Framework (MFTF) is a framework used to perform automated end-to-end functional testing. +<div class="bs-callout bs-callout-info" markdown="1"> +These are the docs for the latest MFTF release. +To find older documentation, please refer to the [docs folder] of your desired release in Github. +</div> + +[Find your MFTF version][] of the MFTF. + +The Magento Functional Testing Framework (MFTF) is a framework used to perform automated end-to-end functional testing. ## Goals @@ -113,6 +120,43 @@ utils // The test-running utilities. codeception.dist.yml // Codeception configuration (generated while running 'bin/mftf build:project') ``` +## MFTF output + +- Generated PHP Codeception tests +- Codeception results and console logs +- Screenshots and HTML failure report +- Allure formatted XML results +- Allure report dashboard of results + +## MFTF tests + +The MFTF supports three different locations for storing the tests and test artifacts: +- `<magento_root>/app/code/<vendor_name>/<module_name>/Test/Mftf/` is the directory to create new tests. +- `<magento_root>/vendor/<vendor_name>/<module_name>/Test/Mftf/` is the directory with the out of the box tests (fetched by the Composer). +- `<magento_root>/dev/tests/acceptance/tests/functional/<vendor_name>/<module_name>/` is used to store tests that depend on multiple modules. + +All tests and test data from these locations are merged in the order indicated in the above list. + +Directories immediately following the above paths will use the same format, and sub-directories under each category are supported. + +```tree +<Path> +├── ActionGroup +│   └── ... +├── Data +│   └── ... +├── Metadata +│   └── ... +├── Page +│   └── ... +├── Section +│   └── ... +├── Suite +│   └── ... +└── Test + └── ... +``` + ## MFTF on Github Follow the [MFTF project] and [contribute on Github]. @@ -123,3 +167,4 @@ Follow the [MFTF project] and [contribute on Github]. [MFTF project]: https://github.com/magento/magento2-functional-testing-framework [Find your MFTF version]: #find-your-mftf-version [MFTF Test Migration]: https://github.com/magento/magento-functional-tests-migration +[docs folder]: https://github.com/magento/magento2-functional-testing-framework/tree/master/docs diff --git a/docs/merging.md b/docs/merging.md index 9cb48c41f..fc187d576 100644 --- a/docs/merging.md +++ b/docs/merging.md @@ -44,7 +44,7 @@ To add a `<test>`, create a new `*Test.xml` file or add a `<test>` node to an ex ## Remove a test Tests cannot be removed while merging. -If a [`<test>`][tests] must be skipped due to a module completely invalidating a function, you can add the test to the `skip` group. +If a [`<test>`][tests] must be skipped due to a module completely invalidating a function, you can use `skip` annotation to skip the test. Learn more about running tests with different options using [`mftf`] or [`codecept`] commands. diff --git a/docs/metadata.md b/docs/metadata.md index 36ff1556e..3f6032b57 100644 --- a/docs/metadata.md +++ b/docs/metadata.md @@ -67,8 +67,8 @@ The following diagram demonstrates the XML structure of a metadata file: ## Principles {#principles} 1. A `dataType` value must match the `type` value of the corresponding entity. -2. A file name should contain data type split with `_` and must end with `-meta`. - Example: `product_attribute-meta.xml`. +2. A file name should be PascalCase and end with `Meta.xml`. + Example: `ProductAttributeMeta.xml`. 3. A metadata file may contain different types of operations (`type`) with the same data entity (`dataType`). Example: @@ -139,7 +139,7 @@ _Catalog/Data/CategoryData.xml_: Here, `type` is equal to `"category"`, which instructs the MFTF to search an operation with `dataType="category"`. Since the action is __to create__ a category, the MFTF will also search for operation with `type="create"` in _Metadata_ for `dataType="category"`. -_Catalog/Metadata/category-meta.xml_: +_Catalog/Metadata/CategoryMeta.xml_: ```xml <operation name="CreateCategory" dataType="category" type="create" auth="adminOauth" url="/V1/categories" method="POST"> @@ -187,10 +187,10 @@ Comments in the example below are used to demonstrate relation between JSON requ JSON does not support comments. </div> -Model schema for _catalogCategoryRepositoryV1SavePostBody_ with XML representation of _Catalog/Metadata/category-meta.xml_ in comments: +Model schema for _catalogCategoryRepositoryV1SavePostBody_ with XML representation of _Catalog/Metadata/CategoryMeta.xml_ in comments: ```json -{ // XML representation in the MFTF metadata format (see 'Catalog/Metadata/category-meta.xml') +{ // XML representation in the MFTF metadata format (see 'Catalog/Metadata/CategoryMeta.xml') "category": { // <object key="category" dataType="category"> "id": 0, // Skipped, because Category ID is not available on UI when you create a new category. "parent_id": 0, // <field key="parent_id">integer</field> @@ -206,9 +206,9 @@ Model schema for _catalogCategoryRepositoryV1SavePostBody_ with XML representati "string" // <value>string</value> ], // </array> "include_in_menu": true, // <field key="include_in_menu">boolean</field> - "extension_attributes": {}, // <field key="extension_attributes">empty_extension_attribute</field>, where 'empty_extension_attribute' is a reference to operation with 'dataType="empty_extension_attribute"' (see 'Catalog/Metadata/empty_extension_attribute-meta.xml') + "extension_attributes": {}, // <field key="extension_attributes">empty_extension_attribute</field>, where 'empty_extension_attribute' is a reference to operation with 'dataType="empty_extension_attribute"' (see 'Catalog/Metadata/EmptyExtensionAttributeMeta.xml') "custom_attributes": [ // <array key="custom_attributes"> - { // <value>custom_attribute</value>, where 'custom_attribute' is a reference to operation with 'dataType="custom_attribute"' (see 'Catalog/Metadata/custom_attribute-meta.xml') + { // <value>custom_attribute</value>, where 'custom_attribute' is a reference to operation with 'dataType="custom_attribute"' (see 'Catalog/Metadata/CustomAttributeMeta.xml') "attribute_code": "string", "value": "string" } @@ -343,7 +343,7 @@ You are able to create assurances with `successRegex`, and, optionally, return v The `CreateStoreGroup` operation is used to persist a store group: -Source file is _Store/Metadata/store_group-meta.xml_: +Source file is _Store/Metadata/StoreGroupMeta.xml_: ```xml <operation name="CreateStoreGroup" dataType="group" type="create" auth="adminFormKey" url="/admin/system_store/save" method="POST" successRegex="/messages-message-success/" > @@ -379,7 +379,7 @@ The operation enables you to assign the following form fields: The MFTF uses the `CreateWishlist` operation to create a wish list on storefront: -Source file is _Wishlist/Metadata/wishlist-meta.xml_ +Source file is _Wishlist/Metadata/WishlistMeta.xml_ ```xml <operation name="CreateWishlist" dataType="wishlist" type="create" auth="customerFormKey" url="/wishlist/index/add/" method="POST" successRegex="" returnRegex="~\/wishlist_id\/(\d*?)\/~" > diff --git a/docs/mftf-tests-packaging.md b/docs/mftf-tests-packaging.md new file mode 100644 index 000000000..8a37b8013 --- /dev/null +++ b/docs/mftf-tests-packaging.md @@ -0,0 +1,58 @@ +<style> +.mftf-dl { + margin-bottom: 2.5em; +} +dl dt{ + font-weight:400; +} +</style> + +# MFTF functional test modules and packaging + +## MFTF predefined test module paths +The Magento Functional Testing Framework can run tests from predefined paths and custom paths. The predefined paths are: +``` +app/code/<Vendor>/<Module>/Test/Mftf +dev/tests/acceptance/tests/functional/<Vendor>/<TestModule> +vendor/<Vendor>/<Module>/Test/Mftf +vendor/<Vendor>/<TestModule> +``` + +To support future service isolation, Test module in `dev/tests/acceptance/tests/functional/<Vendor>/<TestModule>` and +`vendor/<Vendor>/<TestModule>` must define the module type as `magento2-functional-test-module` in its `composer.json` file. +No `composer.json` file is required for tests in `app/code/<Vendor>/<Module>/Test/Mftf` and `vendor/<Vendor>/<Module>/Test/Mftf` +as they are part of the Magento modules. + +Test module for a specific Magento module can only be in one of the paths. + +## Test module composer.json format + +Test module `composer.json` file should use type `magento2-functional-test-module`. + +Test module `composer.json` file should define Magento module dependencies in suggests block. +MFTF will recognize the dependency if the suggest message of a module specifies `type` using `magento2-module` and `name` +using module name registered with Magento. + +Here is an example `composer.json` file for the test module `dev/tests/acceptance/tests/functional/Magento/ConfigurableProductCatalogSearch`: + +```json +{ + "name": "magento/module-configurable-product-catalog-search-functional-test", + "description": "MFTF test module for Magento_ConfigurableProduct and Magento_CatalogSearch", + "type": "magento2-functional-test-module", + "config": { + "sort-packages": true + }, + "require": { + "magento/magento2-functional-testing-framework": ">=2.5" + }, + "suggest": { + "magento/module-configurable-product": "type: magento2-module, name: Magento_ConfigurableProduct, version: *", + "magento/module-catalog-search": "type: magento2-module, name: Magento_CatalogSearch, version: *" + }, + "license": [ + "OSL-3.0", + "AFL-3.0" + ] +} +``` \ No newline at end of file diff --git a/docs/page.md b/docs/page.md index cf8448dd8..41afd274f 100644 --- a/docs/page.md +++ b/docs/page.md @@ -45,7 +45,8 @@ The following conventions apply to MFTF pages: - `<page>` name must be alphanumeric. - `*Page.xml` is stored in the _Page_ directory of a module. - The name format is `{Admin|Storefront}{PageDescription}Page.xml`. - +- One `<page>` tag is allowed per page XML file. + The `.url` attribute is required when using the page for [actions] that require the URL argument. ## Page examples diff --git a/docs/section.md b/docs/section.md index aa3555dc4..421c98fdd 100644 --- a/docs/section.md +++ b/docs/section.md @@ -48,7 +48,7 @@ The following conventions apply to MFTF sections: - `*Section.xml` is stored in the _Section_ directory of a module. - The name format is `{Admin|Storefront}{SectionDescription}Section.xml`. - Camel case is used for `<section>` elements. - They describe the function of the element rather than attempting to describe the selector used. +- One `<section>` tag is allowed per section XML file. ## Example diff --git a/docs/suite.md b/docs/suite.md index 38e54926f..7917cd347 100644 --- a/docs/suite.md +++ b/docs/suite.md @@ -46,12 +46,13 @@ The format of a suite: - must not match any existing group value. For example, the suite `<suite name="ExampleTest">` will fail during test run if any test contains in annotations `<group value="ExampleTest">`. - must not be `default` or `skip`. Tests that are not in any suite are generated under the `default` suite. - The suite name `skip` is synonymous to including a test in the `<group value="skip"/>`, which will be deprecated in MFTF 3.0.0. + The suite name `skip` is synonymous to including a test in the `<group value="skip"/>`. - can contain letters, numbers, and underscores. - should be upper camel case. - A suite must contain at least one `<include>`, or one `<exclude>`, or both. - Using `<before>` in a suite, you must add the corresponding `<after>` to restore the initial state of your testing instance. +- One `<suite>` tag is allowed per suite XML file. ## Conditions diff --git a/docs/test.md b/docs/test.md index 363732fd7..78021fb26 100644 --- a/docs/test.md +++ b/docs/test.md @@ -1,9 +1,9 @@ # Test Test cases in the Magento Functional Testing Framework (MFTF) are defined in XML as [`<tests>`]. -`<tests>` is a [Codeception test container][Codeception] that contains multiple individual tests with test metadata and before and after actions. +`<tests>` is a [Codeception test container][Codeception] that contains individual test [`<test>`] with its metadata ([`<annotations>`]), before ([`<before>`]) and after ([`<after>`]) section. -MFTF `<tests>` is considered a sequence of actions with associated parameters. +MFTF `<test>` is considered a sequence of actions with associated parameters. Any failed [assertion] within a test constitutes a failed test. <div class="bs-callout bs-callout-info" markdown="1"> @@ -18,7 +18,7 @@ The following diagram shows the structure of an MFTF test case: ## Format -The format of `<tests>` is: +The format of a test XML file is: ```xml <?xml version="1.0" encoding="UTF-8"?> @@ -44,28 +44,23 @@ The format of `<tests>` is: The following conventions apply to MFTF tests: -* All names within the framework are in the CamelCase format. -* `<test>` name must be alphanumeric. -* Each action and action group has its own identifier `<stepKey>` for reference purposes. +* One `<test>` tag is allowed per test XML file. +* All names within the framework are in the **PascalCase** format and must be alphanumeric. +* Each action and action group call should have its own identifier `<stepKey>`. * A test may have any number of [assertions][assertion] at any point within the `<test>`. -* If `<test>` is included in `<suite>`, it **cannot be generated in isolation** to the rest of the contents of the suite (see [suites] for details). - -Multiple `<test>` tags per XML file can make it hard to find and organize tags. -To simplify, we generate one `test.php` file per `<test>` tag provided, though we support both single and multiple `<test>` tags per XML file. +* If `<test>` is included in [`<suite>`][suites], it **cannot be generated in isolation** from `<before>` and `<after>` section of the suite (see [suites] for details). ## Elements reference -There are several XML elements that are used in `<tests>` in the MFTF. +There are several XML elements that are used within `<test>` in the MFTF. ### tests {#tests-tag} -`<tests>` is a container for multiple tests. It is a group of test methods that define test flows within a test case. - -`<tests>` must contain at least one [`<test>`]. +`<tests>` is a container for test and must contain exactly one [`<test>`]. ### test {#test-tag} -`<test>` is a set of steps, including [actions] and [assertions][assertion]. It is a sequence of test steps that define test flow within a test method. +`<test>` is a set of steps, including [actions], [assertions][assertion] and Action Group calls. It is a sequence of test steps that define test flow within a test method. Attribute|Type|Use|Description ---|---|---|--- @@ -87,21 +82,20 @@ Allure annotations provide metadata for reporting. ### before {#before-tag} -`<before>` wraps the steps to perform before the [`<test>`]. +`<before>` wraps the steps that are preconditions for the [`<test>`]. For example: Change configuration, create Customer Account, Create Category and Product. `<before>` may contain these child elements: -* Any [`<action>`][actions] -* [`<actionGroup>`] +* Any [Action][actions] +* [`<actionGroup>`]s ### after {#after-tag} -`<after>` wraps the steps to perform after the [`<test>`]. -The steps are run in both successful **and** failed test runs. +`<after>` wraps the steps to perform after the [`<test>`]. The steps are run in both successful **and** failed test runs. The goal of this section is to perform cleanup (revert the environment to the pre-test state). `<after>` may contain: -* Any [`<action>`][actions] +* Any [Action][actions] * [`<actionGroup>`] ### actionGroup {#actiongroup-tag} diff --git a/docs/test/action-groups.md b/docs/test/action-groups.md index 162ac0541..70af0621a 100644 --- a/docs/test/action-groups.md +++ b/docs/test/action-groups.md @@ -15,7 +15,7 @@ The following conventions apply to MFTF action groups: - All action groups are declared in XML files and stored in the `<module>/Test/Mftf/ActionGroup/` directory. - Every file name ends with `ActionGroup` suffix. For exampe `LoginAsAdminActionGroup.xml`. - Action group name should be the same as file name without extension. -- Single file should contain only one `<actionGroup>` node +- One `<actionGroup>` tag is allowed per action group XML file. The XML format for the `actionGroups` declaration is: diff --git a/docs/test/actions.md b/docs/test/actions.md index 19ec3f43b..1d2f83802 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -150,6 +150,7 @@ The following test actions return a variable: * [grabTextFrom](#grabtextfrom) * [grabValueFrom](#grabvaluefrom) * [executeJS](#executejs) +* [getOTP](#getotp) Learn more in [Using data returned by test actions](../data.md#use-data-returned-by-test-actions). @@ -971,26 +972,6 @@ Attribute|Type|Use|Description <dragAndDrop selector1="#block1" selector2="#block2" x="50" y="50" stepKey="dragAndDrop"/> ``` -### executeInSelenium - -#### NOTE: `executeInSelenium` action is DEPRECATED and will be removed in MFTF 3.0.0. - -See [executeInSelenium docs on codeception.com](http://codeception.com/docs/modules/WebDriver#executeInSelenium). - -Attribute|Type|Use|Description ----|---|---|--- -`function`|string|optional| Name of Selenium function to run. -`stepKey`|string|required| A unique identifier of the action. -`before`|string|optional| `stepKey` of action that must be executed next. -`after`|string|optional| `stepKey` of preceding action. - -#### Example - -```xml -<!-- Execute the Selenium function `function(\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) {$webdriver->get('http://google.com');}`. --> -<executeInSelenium function="function(\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) {$webdriver->get('http://google.com');}" stepKey="executeInSelenium"/> -``` - ### executeJS See [executeJS docs on codeception.com](http://codeception.com/docs/modules/WebDriver#executeJS). @@ -1032,12 +1013,15 @@ Attribute|Type|Use|Description <fillField userInput="Sample text" selector="input#myfield" stepKey="fillField"/> ``` -### formatMoney +### formatCurrency +Format input to specified currency according to the locale specified. Returns formatted string for test use. +Use NumberFormatter::formatCurrency(), see https://www.php.net/manual/en/numberformatter.formatcurrency.php Attribute|Type|Use|Description ---|---|---|--- -`userInput`|string|optional| Value for the money form field. -`locale`|string|optional| The PHP locale value for the store. +`userInput`|string|required| Number to be formatted. +`locale`|string|required| The locale to format to. +`currency`|string|required| The 3-letter ISO 4217 currency code indicating the currency to use. `stepKey`|string|required| A unique identifier of the action. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of preceding action. @@ -1089,6 +1073,25 @@ The `ProductAttributeOptionGetter` entity must be defined in the corresponding [ This action can optionally contain one or more [requiredEntity](#requiredentity) child elements. +### getOTP + +Generate a one-time password (OTP) based on a saved `secret` at path `magento/tfa/OTP_SHARED_SECRET` in a MFTF credential storage. +The one-time password (OTP) is returned and accessible through the stepkey. + +MFTF use TOTP from [Spomky-Labs/otphp](https://github.com/Spomky-Labs/otphp), if you want to learn more about this action. + +Attribute|Type|Use|Description +---|---|---|--- +`stepKey`|string|required| A unique identifier of the action. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of preceding action. + +#### Example + +```xml +<getOTP stepKey="getOtp"/> +``` + ### grabAttributeFrom See [grabAttributeFrom docs on codeception.com](http://codeception.com/docs/modules/WebDriver#grabAttributeFrom). @@ -1442,9 +1445,9 @@ Attribute|Type|Use|Description `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of preceding action. -### pauseExecution +### pause -See [pauseExecution docs on codeception.com](http://codeception.com/docs/modules/WebDriver#pauseExecution). +See [pause docs on codeception.com](https://codeception.com/docs/02-GettingStarted). Attribute|Type|Use|Description ---|---|---|--- @@ -1456,23 +1459,9 @@ Attribute|Type|Use|Description ```xml <!-- Halt test execution until the `enter` key is pressed to continue. --> -<pauseExecution stepKey="pause"/> +<pause stepKey="pause"/> ``` -### performOn - -#### NOTE: `performOn` action is DEPRECATED and will be removed in MFTF 3.0.0. - -See [performOn docs on codeception.com](http://codeception.com/docs/modules/WebDriver#performOn). - -Attribute|Type|Use|Description ----|---|---|--- -`selector`|string|optional| The selector identifying the corresponding HTML element. -`function`|string|optional| Function or actions to be taken on the selected element. -`stepKey`|string|required| A unique identifier of the action. -`before`|string|optional| `stepKey` of action that must be executed next. -`after`|string|optional| `stepKey` of preceding action. - ### pressKey See [pressKey docs on codeception.com](http://codeception.com/docs/modules/WebDriver#pressKey). diff --git a/docs/test/annotations.md b/docs/test/annotations.md index f30b8104e..4e9194bb0 100644 --- a/docs/test/annotations.md +++ b/docs/test/annotations.md @@ -87,7 +87,7 @@ Add `<skip>` to the test to skip it during test run. Attribute|Type|Use|Definition ---|---|---|--- -`value`|string|required|A value that is used to group tests. It should be lower case. `skip` is reserved to ignore content of the test and generate an empty test. +`value`|string|required|A value that is used to group tests. It should be lower case. #### Example diff --git a/docs/test/assertions.md b/docs/test/assertions.md index 17a3d194a..554852fcc 100644 --- a/docs/test/assertions.md +++ b/docs/test/assertions.md @@ -1,6 +1,5 @@ # Assertions - Assertions serve to pass or fail the [test](../test.md#test-tag) if a condition is not met. These assertions will look familiar to you if you've used any other testing framework, like PHPUnit. All assertions contain the same [common actions attributes](./actions.md#common-attributes): `stepKey`, `before`, and `after`. @@ -31,6 +30,8 @@ To use variables embedded in a string in `expected` and `actual` of your asserti `actual="A long assert string {$stepKeyOfGrab} with an embedded variable reference." actualType="variable"` +In case of `assertContains` actions, `<expectedResult>` is the needle and `<actualResult>` is the haystack. + ## Example The following example shows a common test that gets text from a page and asserts that it matches what we expect to see. If it does not, the test will fail at the assert step. @@ -53,14 +54,13 @@ The following example shows a common test that gets text from a page and asserts Example: ```xml -<assertElementContainsAttribute selector=".admin__menu-overlay" attribute="style" expectedValue="color: #333;" stepKey="assertElementContainsAttribute"/> +<assertElementContainsAttribute stepKey="assertElementContainsAttribute"> + <expectedResult selector=".admin__menu-overlay" attribute="style" type="string">color: #333;</expectedResult> +</assertElementContainsAttribute> ``` Attribute|Type|Use|Description ---|---|---|--- -`selector`|string|required| -`expectedValue`|string|optional| A value of the expected result. -`attribute`|string|required| `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. @@ -92,12 +92,7 @@ It must be in typical array format like `[1,2,3,4,5]` or `[alpha, brontosaurus, See [assertArrayHasKey docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertArrayHasKey) Attribute|Type|Use|Description ----|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`message`|string|optional|Text of informational message about a cause of failure. +---|---|---|---`message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. @@ -108,44 +103,42 @@ See [assertArrayNotHasKey docs on codeception.com](http://codeception.com/docs/m Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. -### assertArraySubset +### assertContains -See [assertArraySubset docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertArraySubset). +See [assertContains docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertContains). Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`strict`|boolean|optional| `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. -### assertContains +### assertStringContainsString -See [assertContains docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertContains). +See [assertStringContainsString docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertStringContainsString). Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`message`|string|optional|Text of informational message about a cause of failure. +`message`|string|optional|Text describing the cause of the failure. +`stepKey`|string|required| Unique identifier of the text step. +`before`|string|optional| `stepKey` of the action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertStringContainsStringIgnoringCase + +See [assertStringContainsStringIgnoringCase docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertStringContainsStringIgnoringCase). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Message describing the cause of failure. `stepKey`|string|required| A unique identifier of the text step. -`before`|string|optional| `stepKey` of action that must be executed next. +`before`|string|optional| `stepKey` of the action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. ### assertCount @@ -154,10 +147,6 @@ See [assertCount docs on codeception.com](http://codeception.com/docs/modules/As Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -169,8 +158,6 @@ See [assertEmpty docs on codeception.com](http://codeception.com/docs/modules/As Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -182,24 +169,51 @@ See [assertEquals docs on codeception.com](http://codeception.com/docs/modules/A Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertEqualsWithDelta + +See [assertEqualsWithDelta docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertEqualsWithDelta). + +Attribute|Type|Use|Description +---|---|---|--- `delta`|string|optional| `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. +### assertEqualsCanonicalizing + +See [assertEqualsCanonicalizing docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertEqualsCanonicalizing). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertEqualsIgnoringCase + +See [assertEqualsIgnoringCase docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertEqualsIgnoringCase). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + ### assertFalse See [assertFalse docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertFalse). Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| Actual value. -`actualType`|assertEnum|optional| Type of actual value. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -211,8 +225,6 @@ See [assertFileExists docs on codeception.com](http://codeception.com/docs/modul Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -224,8 +236,6 @@ See [assertFileNotExists docs on codeception.com](http://codeception.com/docs/mo Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -237,10 +247,6 @@ See [assertGreaterOrEquals docs on codeception.com](http://codeception.com/docs/ Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -252,10 +258,6 @@ See [assertGreaterThan docs on codeception.com](http://codeception.com/docs/modu Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -267,10 +269,6 @@ See [assertGreaterThanOrEqual docs on codeception.com](http://codeception.com/do Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -282,25 +280,6 @@ See [assertInstanceOf docs on codeception.com](http://codeception.com/docs/modul Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`message`|string|optional|Text of informational message about a cause of failure. -`stepKey`|string|required| A unique identifier of the text step. -`before`|string|optional| `stepKey` of action that must be executed next. -`after`|string|optional| `stepKey` of the preceding action. - -### assertInternalType - -See [assertInternalType docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertInternalType). - -Attribute|Type|Use|Description ----|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -312,8 +291,6 @@ See [assertIsEmpty docs on codeception.com](http://codeception.com/docs/modules/ Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -325,10 +302,6 @@ See [assertLessOrEquals docs on codeception.com](http://codeception.com/docs/mod Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -340,10 +313,6 @@ See [assertLessThan docs on codeception.com](http://codeception.com/docs/modules Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -355,10 +324,6 @@ See [assertLessThanOrEqual docs on codeception.com](http://codeception.com/docs/ Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -370,10 +335,28 @@ See [assertNotContains docs on codeception.com](http://codeception.com/docs/modu Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertStringNotContainsString + +See [assertStringNotContainsString docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertStringNotContainsString). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertStringContainsStringIgnoringCase + +See [assertStringNotContainsStringIgnoringCase docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertStringNotContainsStringIgnoringCase). + +Attribute|Type|Use|Description +---|---|---|--- `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -385,8 +368,6 @@ See [assertNotEmpty docs on codeception.com](http://codeception.com/docs/modules Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -398,26 +379,51 @@ See [assertNotEquals docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertNotEqualsWithDelta + +See [assertNotEqualsWithDelta docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertNotEqualsWithDelta). + +Attribute|Type|Use|Description +---|---|---|--- `delta`|string|optional| `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. +### assertNotEqualsCanonicalizing + +See [assertNotEqualsCanonicalizing docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertNotEqualsCanonicalizing). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + +### assertNotEqualsIgnoringCase + +See [assertNotEqualsIgnoringCase docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertNotEqualsIgnoringCase). + +Attribute|Type|Use|Description +---|---|---|--- +`message`|string|optional|Text of informational message about a cause of failure. +`stepKey`|string|required| A unique identifier of the text step. +`before`|string|optional| `stepKey` of action that must be executed next. +`after`|string|optional| `stepKey` of the preceding action. + ### assertNotInstanceOf See [assertNotInstanceOf docs on codeception.com](http://codeception.com/docs/modules/Asserts#assertNotInstanceOf). Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -429,8 +435,6 @@ See [assertNotNull docs on codeception.com](http://codeception.com/docs/modules/ Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -442,10 +446,6 @@ See [assertNotRegExp docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -457,10 +457,6 @@ See [assertNotSame docs on codeception.com](http://codeception.com/docs/modules/ Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -472,8 +468,6 @@ See [assertNull docs on codeception.com](http://codeception.com/docs/modules/Ass Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -485,10 +479,6 @@ See [assertRegExp docs on codeception.com](http://codeception.com/docs/modules/A Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -500,10 +490,6 @@ See [assertSame docs on codeception.com](http://codeception.com/docs/modules/Ass Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -515,10 +501,6 @@ See [assertStringStartsNotWith docs on codeception.com](http://codeception.com/d Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -530,10 +512,6 @@ See [assertStringStartsWith docs on codeception.com](http://codeception.com/docs Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -545,8 +523,6 @@ See [assertTrue docs on codeception.com](http://codeception.com/docs/modules/Ass Attribute|Type|Use|Description ---|---|---|--- -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `message`|string|optional|Text of informational message about a cause of failure. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. @@ -558,10 +534,6 @@ See [expectException docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`expected`|string|required| A value of the expected result. -`expectedType`|string|optional| A type of the expected result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. -`actual`|string|required| A value of the actual result. -`actualType`|string|optional| A type of the actual result. Possible values: `const` (default), `int`, `float`, `bool`, `string`, `variable`, `array`. `stepKey`|string|required| A unique identifier of the text step. `before`|string|optional| `stepKey` of action that must be executed next. `after`|string|optional| `stepKey` of the preceding action. diff --git a/etc/config/.credentials.example b/etc/config/.credentials.example index 429e9d19f..25400bd63 100644 --- a/etc/config/.credentials.example +++ b/etc/config/.credentials.example @@ -1,3 +1,5 @@ +magento/tfa/OTP_SHARED_SECRET + #magento/carriers_fedex_account= #magento/carriers_fedex_meter_number= #magento/carriers_fedex_key= @@ -72,4 +74,3 @@ #magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_password= #magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_signature= -#magento/fraud_protection_signifyd_api_key= \ No newline at end of file diff --git a/etc/config/.env.example b/etc/config/.env.example index 349d7da9c..53b12036f 100644 --- a/etc/config/.env.example +++ b/etc/config/.env.example @@ -21,6 +21,7 @@ MAGENTO_ADMIN_PASSWORD=123123q #SELENIUM_PORT=4444 #SELENIUM_PROTOCOL=http #SELENIUM_PATH=/wd/hub +SELENIUM_CLOSE_ALL_SESSIONS=true #*** Browser for running tests, default chrome. Uncomment and change if you want to run tests on another browser (ex. firefox). BROWSER=chrome @@ -47,7 +48,7 @@ BROWSER=chrome #DEFAULT_TIMEZONE=America/Los_Angeles #*** These properties impact the modules loaded into MFTF, you can point to your own full path, or a custom set of modules located with the core set -MODULE_WHITELIST=Magento_Framework,ConfigurableProductWishlist,ConfigurableProductCatalogSearch +MODULE_ALLOWLIST=Magento_Framework,ConfigurableProductWishlist,ConfigurableProductCatalogSearch #CUSTOM_MODULE_PATHS= #*** Bool property which allows the user to toggle debug output during test execution @@ -59,9 +60,12 @@ MODULE_WHITELIST=Magento_Framework,ConfigurableProductWishlist,ConfigurableProdu #*** Default timeout for wait actions #WAIT_TIMEOUT=30 -#*** Uncomment and set to enable browser log entries on actions in Allure. Blacklist is used to filter logs of a specific "source" +#*** Uncomment and set to enable all tests, regardless of passing status, to have all their Allure artifacts. +#VERBOSE_ARTIFACTS=true + +#*** Uncomment and set to enable browser log entries on actions in Allure. Blocklist is used to filter logs of a specific "source" #ENABLE_BROWSER_LOG=true -#BROWSER_LOG_BLACKLIST=other +BROWSER_LOG_BLOCKLIST=other #*** Elastic Search version used for test ***# ELASTICSEARCH_VERSION=7 diff --git a/etc/config/functional.suite.dist.yml b/etc/config/functional.suite.dist.yml index 319804d7a..fefcec410 100644 --- a/etc/config/functional.suite.dist.yml +++ b/etc/config/functional.suite.dist.yml @@ -12,12 +12,11 @@ namespace: Magento\FunctionalTestingFramework modules: enabled: - \Magento\FunctionalTestingFramework\Module\MagentoWebDriver - - \Magento\FunctionalTestingFramework\Helper\Acceptance - - \Magento\FunctionalTestingFramework\Helper\MagentoFakerData - \Magento\FunctionalTestingFramework\Module\MagentoSequence - \Magento\FunctionalTestingFramework\Module\MagentoAssert - \Magento\FunctionalTestingFramework\Module\MagentoActionProxies - Asserts + - \Magento\FunctionalTestingFramework\Helper\HelperContainer config: \Magento\FunctionalTestingFramework\Module\MagentoWebDriver: url: "%MAGENTO_BASE_URL%" @@ -29,10 +28,14 @@ modules: username: "%MAGENTO_ADMIN_USERNAME%" password: "%MAGENTO_ADMIN_PASSWORD%" pageload_timeout: "%WAIT_TIMEOUT%" + request_timeout: "%WAIT_TIMEOUT%" + connection_timeout: "%WAIT_TIMEOUT%" host: "%SELENIUM_HOST%" port: "%SELENIUM_PORT%" protocol: "%SELENIUM_PROTOCOL%" path: "%SELENIUM_PATH%" + close_all_sessions: "%SELENIUM_CLOSE_ALL_SESSIONS%" capabilities: - chromeOptions: - args: ["--window-size=1280,1024", "--disable-extensions", "--enable-automation", "--disable-gpu", "--enable-Passthrough"] + unhandledPromptBehavior: "ignore" + chromeOptions: + args: ["--window-size=1280,1024", "--disable-extensions", "--enable-automation", "--disable-gpu", "--enable-Passthrough", "--disable-dev-shm-usage", "--ignore-certificate-errors"] diff --git a/etc/di.xml b/etc/di.xml index e5e31cf87..e561911da 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -8,7 +8,7 @@ <!-- Entity value gets replaced in Dom.php before reading $xml --> <!DOCTYPE config [ - <!ENTITY commonTestActions "acceptPopup|actionGroup|amOnPage|amOnUrl|amOnSubdomain|appendField|assertArrayIsSorted|assertArraySubset|assertElementContainsAttribute|attachFile|cancelPopup|checkOption|clearField|click|clickWithLeftButton|clickWithRightButton|closeAdminNotification|closeTab|comment|conditionalClick|createData|deleteData|updateData|getData|dontSee|dontSeeJsError|dontSeeCheckboxIsChecked|dontSeeCookie|dontSeeCurrentUrlEquals|dontSeeCurrentUrlMatches|dontSeeElement|dontSeeElementInDOM|dontSeeInCurrentUrl|dontSeeInField|dontSeeInFormFields|dontSeeInPageSource|dontSeeInSource|dontSeeInTitle|dontSeeLink|dontSeeOptionIsSelected|doubleClick|dragAndDrop|entity|executeJS|executeInSelenium|fillField|formatMoney|generateDate|grabAttributeFrom|grabCookie|grabFromCurrentUrl|grabMultiple|grabPageSource|grabTextFrom|grabValueFrom|loadSessionSnapshot|loginAsAdmin|magentoCLI|magentoCron|makeScreenshot|maximizeWindow|moveBack|moveForward|moveMouseOver|mSetLocale|mResetLocale|openNewTab|pauseExecution|parseFloat|performOn|pressKey|reloadPage|resetCookie|submitForm|resizeWindow|saveSessionSnapshot|scrollTo|scrollToTopOfPage|searchAndMultiSelectOption|see|seeCheckboxIsChecked|seeCookie|seeCurrentUrlEquals|seeCurrentUrlMatches|seeElement|seeElementInDOM|seeInCurrentUrl|seeInField|seeInFormFields|seeInPageSource|seeInPopup|seeInSource|seeInTitle|seeLink|seeNumberOfElements|seeOptionIsSelected|selectOption|setCookie|submitForm|switchToIFrame|switchToNextTab|switchToPreviousTab|switchToWindow|typeInPopup|uncheckOption|unselectOption|wait|waitForAjaxLoad|waitForElement|waitForElementChange|waitForElementNotVisible|waitForElementVisible|waitForPwaElementNotVisible|waitForPwaElementVisible|waitForJS|waitForLoadingMaskToDisappear|waitForPageLoad|waitForText|assertArrayHasKey|assertArrayNotHasKey|assertArraySubset|assertContains|assertCount|assertEmpty|assertEquals|assertFalse|assertFileExists|assertFileNotExists|assertGreaterOrEquals|assertGreaterThan|assertGreaterThanOrEqual|assertInstanceOf|assertInternalType|assertIsEmpty|assertLessOrEquals|assertLessThan|assertLessThanOrEqual|assertNotContains|assertNotEmpty|assertNotEquals|assertNotInstanceOf|assertNotNull|assertNotRegExp|assertNotSame|assertNull|assertRegExp|assertSame|assertStringStartsNotWith|assertStringStartsWith|assertTrue|expectException|fail|dontSeeFullUrlEquals|dontSee|dontSeeFullUrlMatches|dontSeeInFullUrl|seeFullUrlEquals|seeFullUrlMatches|seeInFullUrl|grabFromFullUrl"> + <!ENTITY commonTestActions "acceptPopup|actionGroup|amOnPage|amOnUrl|amOnSubdomain|appendField|assertArrayIsSortasserted|assertElementContainsAttribute|attachFile|cancelPopup|checkOption|clearField|click|clickWithLeftButton|clickWithRightButton|closeAdminNotification|closeTab|comment|conditionalClick|createData|deleteData|updateData|getData|dontSee|dontSeeJsError|dontSeeCheckboxIsChecked|dontSeeCookie|dontSeeCurrentUrlEquals|dontSeeCurrentUrlMatches|dontSeeElement|dontSeeElementInDOM|dontSeeInCurrentUrl|dontSeeInField|dontSeeInFormFields|dontSeeInPageSource|dontSeeInSource|dontSeeInTitle|dontSeeLink|dontSeeOptionIsSelected|doubleClick|dragAndDrop|entity|executeJS|fillField|formatCurrency|generateDate|getOTP|grabAttributeFrom|grabCookie|grabFromCurrentUrl|grabMultiple|grabPageSource|grabTextFrom|grabValueFrom|loadSessionSnapshot|loginAsAdmin|magentoCLI|magentoCron|makeScreenshot|maximizeWindow|moveBack|moveForward|moveMouseOver|mSetLocale|mResetLocale|openNewTab|pause|parseFloat|pressKey|reloadPage|resetCookie|submitForm|resizeWindow|saveSessionSnapshot|scrollTo|scrollToTopOfPage|searchAndMultiSelectOption|see|seeCheckboxIsChecked|seeCookie|seeCurrentUrlEquals|seeCurrentUrlMatches|seeElement|seeElementInDOM|seeInCurrentUrl|seeInField|seeInFormFields|seeInPageSource|seeInPopup|seeInSource|seeInTitle|seeLink|seeNumberOfElements|seeOptionIsSelected|selectOption|setCookie|submitForm|switchToIFrame|switchToNextTab|switchToPreviousTab|switchToWindow|typeInPopup|uncheckOption|unselectOption|wait|waitForAjaxLoad|waitForElement|waitForElementChange|waitForElementNotVisible|waitForElementVisible|waitForPwaElementNotVisible|waitForPwaElementVisible|waitForJS|waitForLoadingMaskToDisappear|waitForPageLoad|waitForText|assertArrayHasKey|assertArrayNotHasKey|assertContains|assertStringContainsString|assertStringContainsStringIgnoringCase|assertCount|assertEmpty|assertEquals|assertFalse|assertFileExists|assertFileNotExists|assertGreaterOrEquals|assertGreaterThan|assertGreaterThanOrEqual|assertInstanceOf|assertIsEmpty|assertLessOrEquals|assertLessThan|assertLessThanOrEqual|assertNotContains|assertStringNotContainsString|assertStringNotContainsStringIgnoringCase|assertNotEmpty|assertNotEquals|assertNotInstanceOf|assertNotNull|assertNotRegExp|assertNotSame|assertNull|assertRegExp|assertSame|assertStringStartsNotWith|assertStringStartsWith|assertTrue|expectException|fail|dontSeeFullUrlEquals|dontSee|dontSeeFullUrlMatches|dontSeeInFullUrl|seeFullUrlEquals|seeFullUrlMatches|seeInFullUrl|grabFromFullUrl|helper|assertEqualsWithDelta|assertEqualsCanonicalizing|assertEqualsIgnoringCase|assertNotEqualsWithDelta|assertNotEqualsCanonicalizing|assertNotEqualsIgnoringCase"> ]> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../src/Magento/FunctionalTestingFramework/ObjectManager/etc/config.xsd"> @@ -70,17 +70,17 @@ <virtualType name="Magento\FunctionalTestingFramework\Config\SchemaLocator\Page" type="Magento\FunctionalTestingFramework\Config\SchemaLocator"> <arguments> - <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd</argument> + <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Page/etc/mergedPageObject.xsd</argument> </arguments> </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\SchemaLocator\Section" type="Magento\FunctionalTestingFramework\Config\SchemaLocator"> <arguments> - <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd</argument> + <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Page/etc/mergedSectionObject.xsd</argument> </arguments> </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\Page" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\Converter</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\Page</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Page\Config\Dom</argument> @@ -88,13 +88,13 @@ <item name="/pages/page" xsi:type="string">name</item> <item name="/pages/page/section" xsi:type="string">name</item> </argument> - <argument name="fileName" xsi:type="string">*Page.xml</argument> + <argument name="fileName" xsi:type="string">/Page\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Page</argument> </arguments> </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\Section" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\Converter</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\Section</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Page\Config\SectionDom</argument> @@ -102,7 +102,7 @@ <item name="/sections/section" xsi:type="string">name</item> <item name="/sections/section/element" xsi:type="string">name</item> </argument> - <argument name="fileName" xsi:type="string">*Section.xml</argument> + <argument name="fileName" xsi:type="string">/Section\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Section</argument> </arguments> </virtualType> @@ -150,20 +150,21 @@ </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\DataProfile" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\Converter</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\DataGenerator\Config\Dom</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\DataProfile</argument> <argument name="idAttributes" xsi:type="array"> <item name="/entities/entity" xsi:type="string">name</item> <item name="/entities/entity/(data|array)" xsi:type="string">key</item> + <item name="/entities/entity/array/item" xsi:type="string">name</item> <item name="/entities/entity/requiredEntity" xsi:type="string">type</item> </argument> <argument name="mergeablePaths" xsi:type="array"> <item name="/entities/entity/requiredEntity" xsi:type="string"/> <item name="/entities/entity/array" xsi:type="string"/> </argument> - <argument name="fileName" xsi:type="string">*Data.xml</argument> + <argument name="fileName" xsi:type="string">/Data\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Data</argument> </arguments> </virtualType> @@ -187,7 +188,7 @@ </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\Metadata" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\Converter</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\DataGenerator\Config\OperationDom</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\Metadata</argument> @@ -198,7 +199,7 @@ <argument name="mergeablePaths" xsi:type="array"> <item name="/operations/operation/object" xsi:type="string"/> </argument> - <argument name="fileName" xsi:type="string">*-meta.xml</argument> + <argument name="fileName" xsi:type="string">/Meta\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Metadata</argument> </arguments> </virtualType> @@ -212,7 +213,7 @@ </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\TestData" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\TestDataConverter</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\TestData</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Test\Config\Dom</argument> @@ -222,6 +223,8 @@ <item name="/tests/test/(createData|updateData|getData)/requiredEntity" xsi:type="string">createDataKey</item> <item name="/tests/test/(createData|updateData|getData)/field" xsi:type="string">key</item> <item name="/tests/test/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item> + <item name="/tests/test/helper/argument" xsi:type="string">name</item> + <item name="/tests/test/(before|after)/helper/argument" xsi:type="string">name</item> <item name="/tests/test/(before|after)/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item> <item name="/tests/test/remove" xsi:type="string">keyForRemoval</item> <item name="/tests/test/(before|after)/remove" xsi:type="string">keyForRemoval</item> @@ -229,7 +232,7 @@ <item name="/tests/test/(before|after)/(createData|updateData|getData)/field" xsi:type="string">key</item> <item name="/tests/test/annotations(/group)+" xsi:type="string">value</item> </argument> - <argument name="fileName" xsi:type="string">*.xml</argument> + <argument name="fileName" xsi:type="string">/\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Test</argument> </arguments> </virtualType> @@ -239,6 +242,8 @@ <argument name="assocArrayAttributes" xsi:type="array"> <item name="/tests/test/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item> <item name="/tests/test/(before|after)/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item> + <item name="/tests/test/helper/argument" xsi:type="string">name</item> + <item name="/tests/test/(before|after)/helper/argument" xsi:type="string">name</item> <item name="/tests/test/remove" xsi:type="string">keyForRemoval</item> <item name="/tests/test/(before|after)/remove" xsi:type="string">keyForRemoval</item> <item name="/tests/test" xsi:type="string">name</item> @@ -286,25 +291,26 @@ <virtualType name="Magento\FunctionalTestingFramework\Config\SchemaLocator\ActionGroup" type="Magento\FunctionalTestingFramework\Config\SchemaLocator"> <arguments> - <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd</argument> + <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Test/etc/mergedActionGroupSchema.xsd</argument> </arguments> </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\ActionGroupData" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> - <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Module</argument> + <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Mask</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\ActionGroupDataConverter</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\ActionGroup</argument> <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Test\Config\ActionGroupDom</argument> <argument name="idAttributes" xsi:type="array"> <item name="/actionGroups/actionGroup" xsi:type="string">name</item> <item name="/actionGroups/actionGroup/arguments/argument" xsi:type="string">name</item> + <item name="/actionGroups/actionGroup/helper/argument" xsi:type="string">name</item> <item name="/actionGroups/actionGroup/(&commonTestActions;)" xsi:type="string">stepKey</item> <item name="/actionGroups/actionGroup/(createData|updateData|getData)/requiredEntity" xsi:type="string">createDataKey</item> <item name="/actionGroups/actionGroup/(createData|updateData|getData)/field" xsi:type="string">key</item> <item name="/actionGroups/actionGroup/remove" xsi:type="string">keyForRemoval</item> </argument> - <argument name="fileName" xsi:type="string">*ActionGroup.xml</argument> + <argument name="fileName" xsi:type="string">/ActionGroup\.xml$/</argument> <argument name="defaultScope" xsi:type="string">ActionGroup</argument> </arguments> </virtualType> @@ -316,6 +322,7 @@ <item name="/actionGroups/actionGroup/remove" xsi:type="string">keyForRemoval</item> <item name="/actionGroups/actionGroup" xsi:type="string">name</item> <item name="/actionGroups/actionGroup/arguments/argument" xsi:type="string">name</item> + <item name="/actionGroups/actionGroup/helper/argument" xsi:type="string">name</item> <item name="/actionGroups/actionGroup/(createData|updateData|getData)/requiredEntity" xsi:type="string">createDataKey</item> <item name="/actionGroups/actionGroup/(createData|updateData|getData)/field" xsi:type="string">key</item> </argument> @@ -353,14 +360,15 @@ </virtualType> <virtualType name="Magento\FunctionalTestingFramework\Config\SchemaLocator\SuiteData" type="Magento\FunctionalTestingFramework\Config\SchemaLocator"> <arguments> - <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd</argument> + <argument name="schemaPath" xsi:type="string">Magento/FunctionalTestingFramework/Suite/etc/mergedSuiteSchema.xsd</argument> </arguments> </virtualType> - <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\SuiteData" type="Magento\FunctionalTestingFramework\Config\Reader\Filesystem"> + <virtualType name="Magento\FunctionalTestingFramework\Config\Reader\SuiteData" type="Magento\FunctionalTestingFramework\Config\Reader\MftfFilesystem"> <arguments> <argument name="fileResolver" xsi:type="object">Magento\FunctionalTestingFramework\Config\FileResolver\Root</argument> <argument name="converter" xsi:type="object">Magento\FunctionalTestingFramework\Config\SuiteDataConverter</argument> <argument name="schemaLocator" xsi:type="object">Magento\FunctionalTestingFramework\Config\SchemaLocator\SuiteData</argument> + <argument name="domDocumentClass" xsi:type="string">Magento\FunctionalTestingFramework\Suite\Config\SuiteDom</argument> <argument name="idAttributes" xsi:type="array"> <item name="/suites/suite" xsi:type="string">name</item> <item name="/suites/suite/(before|after)/remove" xsi:type="string">keyForRemoval</item> @@ -371,7 +379,7 @@ <item name="/suites/suite/include/(group|test|module)" xsi:type="string">name</item> <item name="/suites/suite/exclude/(group|test|module)" xsi:type="string">name</item> </argument> - <argument name="fileName" xsi:type="string">*.xml</argument> + <argument name="fileName" xsi:type="string">/\.xml$/</argument> <argument name="defaultScope" xsi:type="string">Suite</argument> </arguments> </virtualType> diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index e9e1c344c..7d7a7bd44 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -5,13 +5,18 @@ */ namespace Magento\FunctionalTestingFramework\Allure\Adapter; +use Codeception\Codecept; +use Codeception\Test\Cest; use Codeception\Step\Comment; use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Util\TestGenerator; +use Yandex\Allure\Adapter\Model\Failure; +use Yandex\Allure\Adapter\Model\Provider; use Yandex\Allure\Adapter\Model\Status; use Yandex\Allure\Adapter\Model\Step; +use Yandex\Allure\Adapter\Allure; use Yandex\Allure\Codeception\AllureCodeception; use Yandex\Allure\Adapter\Event\StepStartedEvent; use Yandex\Allure\Adapter\Event\StepFinishedEvent; @@ -19,9 +24,11 @@ use Yandex\Allure\Adapter\Event\TestCaseFailedEvent; use Yandex\Allure\Adapter\Event\TestCaseFinishedEvent; use Yandex\Allure\Adapter\Event\TestCaseBrokenEvent; +use Yandex\Allure\Adapter\Event\AddAttachmentEvent; use Codeception\Event\FailEvent; use Codeception\Event\SuiteEvent; use Codeception\Event\StepEvent; +use Codeception\Event\TestEvent; /** * Class MagentoAllureAdapter @@ -114,6 +121,7 @@ private function sanitizeGroupName($group) // if we can't find this group in the generated suites we have to assume that the group was split for generation $groupNameSplit = explode("_", $group); array_pop($groupNameSplit); + array_pop($groupNameSplit); $originalName = implode("_", $groupNameSplit); // confirm our original name is one of the existing suite names otherwise just return the original group name @@ -245,11 +253,17 @@ public function testError(FailEvent $failEvent) /** * Override of parent method, polls stepStorage for testcase and formats it according to actionGroup nesting. - * + * @param TestEvent $testEvent + * @throws \Yandex\Allure\Adapter\AllureException * @return void */ - public function testEnd() + public function testEnd(TestEvent $testEvent) { + $test = $this->getLifecycle()->getTestCaseStorage()->get(); + // update testClass label to consolidate re-try reporting + $this->formatAllureTestClassName($test); + // Peek top of testCaseStorage to check of failure + $testFailed = $test->getFailure(); // Pops top of stepStorage, need to add it back in after processing $rootStep = $this->getLifecycle()->getStepStorage()->pollLast(); $formattedSteps = []; @@ -257,6 +271,7 @@ public function testEnd() $actionGroupStepKey = null; foreach ($rootStep->getSteps() as $step) { + $this->removeAttachments($step, $testFailed); $stepKey = str_replace($actionGroupStepKey, '', $step->getName()); if ($stepKey !== '[]' && $stepKey !== null) { $step->setName($stepKey); @@ -309,9 +324,28 @@ function () use ($rootStep, $formattedSteps) { $this->getLifecycle()->getStepStorage()->put($rootStep); + $this->addAttachmentEvent($testEvent); + $this->getLifecycle()->fire(new TestCaseFinishedEvent()); } + /** + * Fire add attachment event + * @param TestEvent $testEvent + * @throws \Yandex\Allure\Adapter\AllureException + * @return void + */ + private function addAttachmentEvent(TestEvent $testEvent) + { + // attachments supported since Codeception 3.0 + if (version_compare(Codecept::VERSION, '3.0.0') > -1 && $testEvent->getTest() instanceof Cest) { + $artifacts = $testEvent->getTest()->getMetadata()->getReports(); + foreach ($artifacts as $name => $artifact) { + Allure::lifecycle()->fire(new AddAttachmentEvent($artifact, $name, null)); + } + } + } + /** * Reads action group stepKey from step. * @@ -354,4 +388,60 @@ private function retrieveStepKey($stepLine) return $stepKey; } + + /** + * Removes attachments from step depending on MFTF configuration + * @param Step $step + * @param Failure $testFailed + * @return void + */ + private function removeAttachments($step, $testFailed) + { + //Remove Attachments if verbose flag is not true AND test did not fail + if (getenv('VERBOSE_ARTIFACTS') !== "true" && $testFailed === null) { + foreach ($step->getAttachments() as $index => $attachment) { + $step->removeAttachment($index); + unlink(Provider::getOutputDirectory() . DIRECTORY_SEPARATOR . $attachment->getSource()); + } + } + } + + /** + * Format testClass label to consolidate re-try reporting for groups split for parallel execution + * @param TestCase $test + * @return void + */ + private function formatAllureTestClassName($test) + { + if ($this->getGroup() !== null) { + foreach ($test->getLabels() as $name => $label) { + if ($label->getName() == 'testClass') { + $originalTestClass = $this->sanitizeTestClassLabel($label->getValue()); + call_user_func(\Closure::bind( + function () use ($label, $originalTestClass) { + $label->value = $originalTestClass; + }, + null, + $label + )); + break; + } + } + } + } + + /** + * Function which sanitizes testClass label for split group runs + * @param string $testClass + * @return string + */ + private function sanitizeTestClassLabel($testClass) + { + $originalTestClass = $testClass; + $originalGroupName = $this->sanitizeGroupName($this->getGroup()); + if ($originalGroupName !== $this->getGroup()) { + $originalTestClass = str_replace($this->getGroup(), $originalGroupName, $testClass); + } + return $originalTestClass; + } } diff --git a/src/Magento/FunctionalTestingFramework/Config/Dom.php b/src/Magento/FunctionalTestingFramework/Config/Dom.php index 6d10811ca..881b677dc 100644 --- a/src/Magento/FunctionalTestingFramework/Config/Dom.php +++ b/src/Magento/FunctionalTestingFramework/Config/Dom.php @@ -246,8 +246,8 @@ protected function getNodePathByParent(\DOMElement $node, $parentPath) $idAttribute = $this->nodeMergingConfig->getIdAttribute($path); if ($idAttribute) { foreach (explode('|', $idAttribute) as $idAttributeValue) { - if ($value = $node->getAttribute($idAttributeValue)) { - $path .= "[@{$idAttributeValue}='{$value}']"; + if ($node->hasAttribute($idAttributeValue)) { + $path .= "[@{$idAttributeValue}='" . $node->getAttribute($idAttributeValue) . "']"; break; } } diff --git a/src/Magento/FunctionalTestingFramework/Config/FileResolver/Root.php b/src/Magento/FunctionalTestingFramework/Config/FileResolver/Root.php index 4ebb11942..230586852 100644 --- a/src/Magento/FunctionalTestingFramework/Config/FileResolver/Root.php +++ b/src/Magento/FunctionalTestingFramework/Config/FileResolver/Root.php @@ -11,7 +11,7 @@ use Magento\FunctionalTestingFramework\Util\Iterator\File; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; -class Root extends Module +class Root extends Mask { const ROOT_SUITE_DIR = "tests/_suite"; @@ -26,16 +26,29 @@ class Root extends Module */ public function get($filename, $scope) { - // first pick up the root level test suite dir + // First pick up the root level test suite dir $paths = glob( FilePathFormatter::format(TESTS_BP) . self::ROOT_SUITE_DIR - . DIRECTORY_SEPARATOR . $filename + . DIRECTORY_SEPARATOR . '*.xml' ); - // then merge this path into the module based paths - // Since we are sharing this code with Module based resolution we will unncessarily glob against modules in the + // include root suite dir when running standalone version + $altPath = FilePathFormatter::format(MAGENTO_BP) . 'dev/tests/acceptance'; + + if (realpath($altPath) && ($altPath !== TESTS_BP)) { + $paths = array_merge( + $paths, + glob( + FilePathFormatter::format($altPath) . self::ROOT_SUITE_DIR + . DIRECTORY_SEPARATOR . '*.xml' + ) + ); + } + + // Then merge this path into the module based paths + // Since we are sharing this code with Module based resolution we will unnecessarily glob against modules in the // dev/tests dir tree, however as we plan to migrate to app/code this will be a temporary unneeded check. - $paths = array_merge($paths, $this->getPaths($filename, $scope)); + $paths = array_merge($paths, $this->getFileCollection($filename, $scope)); // create and return the iterator for these file paths $iterator = new File($paths); diff --git a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php index 4b215cb4f..ab06b5612 100644 --- a/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php +++ b/src/Magento/FunctionalTestingFramework/Config/MftfApplicationConfig.php @@ -23,8 +23,7 @@ class MftfApplicationConfig */ const LEVEL_DEFAULT = "default"; const LEVEL_DEVELOPER = "developer"; - const LEVEL_NONE = "none"; - const MFTF_DEBUG_LEVEL = [self::LEVEL_DEFAULT, self::LEVEL_DEVELOPER, self::LEVEL_NONE]; + const MFTF_DEBUG_LEVEL = [self::LEVEL_DEFAULT, self::LEVEL_DEVELOPER]; /** * Contains object with test filters. @@ -89,7 +88,7 @@ private function __construct( $forceGenerate = false, $phase = self::EXECUTION_PHASE, $verboseEnabled = null, - $debugLevel = self::LEVEL_NONE, + $debugLevel = self::LEVEL_DEFAULT, $allowSkipped = false, $filters = [] ) { @@ -101,14 +100,17 @@ private function __construct( $this->phase = $phase; $this->verboseEnabled = $verboseEnabled; - switch ($debugLevel) { + if (isset($debugLevel) && !in_array(strtolower($debugLevel), self::MFTF_DEBUG_LEVEL)) { + throw new TestFrameworkException("{$debugLevel} is not a debug level. Use 'DEFAULT' or 'DEVELOPER'"); + } + switch (strtolower($debugLevel)) { case self::LEVEL_DEVELOPER: case self::LEVEL_DEFAULT: - case self::LEVEL_NONE: $this->debugLevel = $debugLevel; break; - default: + case null: $this->debugLevel = self::LEVEL_DEVELOPER; + break; } $this->allowSkipped = $allowSkipped; $this->filterList = new FilterList($filters); @@ -131,7 +133,7 @@ public static function create( $forceGenerate = false, $phase = self::EXECUTION_PHASE, $verboseEnabled = null, - $debugLevel = self::LEVEL_NONE, + $debugLevel = self::LEVEL_DEFAULT, $allowSkipped = false, $filters = [] ) { diff --git a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php index db96b010c..ab7d64ea9 100644 --- a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php +++ b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php @@ -146,6 +146,7 @@ protected function readFiles($fileList) { /** @var \Magento\FunctionalTestingFramework\Config\Dom $configMerger */ $configMerger = null; + $debugLevel = MftfApplicationConfig::getConfig()->getDebugLevel(); foreach ($fileList as $key => $content) { //check if file is empty and continue to next if it is if (!$this->verifyFileEmpty($content, $fileList->getFilename())) { @@ -157,7 +158,7 @@ protected function readFiles($fileList) } else { $configMerger->merge($content); } - if (MftfApplicationConfig::getConfig()->getDebugLevel() === MftfApplicationConfig::LEVEL_DEVELOPER) { + if (strcasecmp($debugLevel, MftfApplicationConfig::LEVEL_DEVELOPER) == 0) { $this->validateSchema($configMerger, $fileList->getFilename()); } } catch (\Magento\FunctionalTestingFramework\Config\Dom\ValidationException $e) { diff --git a/src/Magento/FunctionalTestingFramework/Config/Reader/MftfFilesystem.php b/src/Magento/FunctionalTestingFramework/Config/Reader/MftfFilesystem.php index cd075e57c..3740d683f 100644 --- a/src/Magento/FunctionalTestingFramework/Config/Reader/MftfFilesystem.php +++ b/src/Magento/FunctionalTestingFramework/Config/Reader/MftfFilesystem.php @@ -42,7 +42,7 @@ public function readFiles($fileList) $configMerger->merge($content, $fileList->getFilename(), $exceptionCollector); } // run per file validation with generate:tests -d - if ($debugLevel === MftfApplicationConfig::LEVEL_DEVELOPER) { + if (strcasecmp($debugLevel, MftfApplicationConfig::LEVEL_DEVELOPER) == 0) { $this->validateSchema($configMerger, $fileList->getFilename()); } } catch (\Magento\FunctionalTestingFramework\Config\Dom\ValidationException $e) { @@ -52,7 +52,7 @@ public function readFiles($fileList) $exceptionCollector->throwException(); //run validation on merged file with generate:tests - if ($debugLevel === MftfApplicationConfig::LEVEL_DEFAULT) { + if (strcasecmp($debugLevel, MftfApplicationConfig::LEVEL_DEFAULT) == 0) { $this->validateSchema($configMerger); } diff --git a/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php b/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php index 273632586..f3becf935 100644 --- a/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php @@ -23,12 +23,7 @@ class BaseGenerateCommand extends Command { - const MFTF_3_O_0_DEPRECATION_MESSAGE = "MFTF NOTICES:\n" - . "DEPRECATED ACTIONS: \"executeInSelenium\" and \"performOn\" actions will be removed in MFTF 3.0.0\n" - . "DEPRECATED TEST PATH: support for \"dev/tests/acceptance/tests/functional/Magento/FunctionalTest will be " - . "removed in MFTF 3.0.0\n" - . "XSD schema change to only allow single entity per xml file for all entities except data and metadata in " - . "MFTF 3.0.0\n"; + const MFTF_NOTICES = "Placeholder text for MFTF notices\n"; /** * Console output style @@ -63,8 +58,7 @@ protected function configure() 'debug', 'd', InputOption::VALUE_OPTIONAL, - 'Run extra validation when generating and running tests. Use option \'none\' to turn off debugging -- - added for backward compatibility, will be removed in the next MAJOR release', + 'Run extra validation when generating and running tests.', MftfApplicationConfig::LEVEL_DEFAULT ); } @@ -196,14 +190,15 @@ protected function getGroupAndSuiteConfiguration(array $groupOrSuiteNames) } /** - * Set Symfony Style for output + * Set Symfony IO Style * - * @param InputInterface $input + * @param InputInterface $input * @param OutputInterface $output + * @return void */ - protected function setOutputStyle(InputInterface $input, OutputInterface $output) + protected function setIOStyle(InputInterface $input, OutputInterface $output) { - // For output style + // For IO style if (null === $this->ioStyle) { $this->ioStyle = new SymfonyStyle($input, $output); } @@ -218,9 +213,9 @@ protected function setOutputStyle(InputInterface $input, OutputInterface $output protected function showMftfNotices(OutputInterface $output) { if (null !== $this->ioStyle) { - $this->ioStyle->note(self::MFTF_3_O_0_DEPRECATION_MESSAGE); + $this->ioStyle->note(self::MFTF_NOTICES); } else { - $output->writeln(self::MFTF_3_O_0_DEPRECATION_MESSAGE); + $output->writeln(self::MFTF_NOTICES); } } } diff --git a/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php b/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php index 02dfcda82..23736925f 100644 --- a/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php @@ -109,7 +109,7 @@ function ($type, $buffer) use ($output) { if ($input->getOption('upgrade')) { $upgradeCommand = new UpgradeTestsCommand(); - $upgradeOptions = new ArrayInput(['path' => FilePathFormatter::format(TESTS_MODULE_PATH)]); + $upgradeOptions = new ArrayInput([]); $upgradeCommand->run($upgradeOptions, $output); } } diff --git a/src/Magento/FunctionalTestingFramework/Console/CommandList.php b/src/Magento/FunctionalTestingFramework/Console/CommandList.php index bf9cbd58e..f77c2c576 100644 --- a/src/Magento/FunctionalTestingFramework/Console/CommandList.php +++ b/src/Magento/FunctionalTestingFramework/Console/CommandList.php @@ -31,7 +31,6 @@ public function __construct(array $commands = []) $this->commands = [ 'build:project' => new BuildProjectCommand(), 'doctor' => new DoctorCommand(), - 'generate:docs' => new GenerateDocsCommand(), 'generate:suite' => new GenerateSuiteCommand(), 'generate:tests' => new GenerateTestsCommand(), 'generate:urn-catalog' => new GenerateDevUrnCommand(), diff --git a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php index 6fc9afa55..aa0c81d57 100644 --- a/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/DoctorCommand.php @@ -8,7 +8,7 @@ namespace Magento\FunctionalTestingFramework\Console; use Codeception\Configuration; -use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; +use Magento\FunctionalTestingFramework\DataTransport\Auth\WebApiAuth; use Symfony\Component\EventDispatcher\EventDispatcher; use Codeception\SuiteManager; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; @@ -16,7 +16,6 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Magento\FunctionalTestingFramework\Util\ModuleResolver; use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; use Magento\FunctionalTestingFramework\Module\MagentoWebDriverDoctor; use Symfony\Component\Console\Style\SymfonyStyle; @@ -125,7 +124,7 @@ private function checkAuthenticationToMagentoAdmin() $result = false; try { $this->ioStyle->text("Requesting API token for admin user through cURL ..."); - ModuleResolver::getInstance()->getAdminToken(); + WebApiAuth::getAdminToken(); $this->ioStyle->success('Successful'); $result = true; } catch (TestFrameworkException $e) { diff --git a/src/Magento/FunctionalTestingFramework/Console/GenerateDevUrnCommand.php b/src/Magento/FunctionalTestingFramework/Console/GenerateDevUrnCommand.php index f953deb16..bca72421b 100644 --- a/src/Magento/FunctionalTestingFramework/Console/GenerateDevUrnCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/GenerateDevUrnCommand.php @@ -4,7 +4,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -declare(strict_types = 1); +declare(strict_types=1); namespace Magento\FunctionalTestingFramework\Console; @@ -19,6 +19,14 @@ class GenerateDevUrnCommand extends Command { + /** + * Argument for the path to IDE config file + */ + const IDE_FILE_PATH_ARGUMENT = 'path'; + + const PROJECT_PATH_IDENTIFIER = '$PROJECT_DIR$'; + const MFTF_SRC_PATH = 'src/Magento/FunctionalTestingFramework/'; + /** * Configures the current command. * @@ -27,8 +35,12 @@ class GenerateDevUrnCommand extends Command protected function configure() { $this->setName('generate:urn-catalog') - ->setDescription('This command generates an URN catalog to enable PHPStorm to recognize and highlight URNs.') - ->addArgument('path', InputArgument::REQUIRED, 'path to PHPStorm misc.xml file (typically located in [ProjectRoot]/.idea/misc.xml)') + ->setDescription('Generates the catalog of URNs to *.xsd mappings for the IDE to highlight xml.') + ->addArgument( + self::IDE_FILE_PATH_ARGUMENT, + InputArgument::REQUIRED, + 'Path to file to output the catalog. For PhpStorm use .idea/misc.xml' + ) ->addOption( "force", 'f', @@ -47,7 +59,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $miscXmlFilePath = $input->getArgument('path') . DIRECTORY_SEPARATOR . "misc.xml"; + $miscXmlFilePath = $input->getArgument(self::IDE_FILE_PATH_ARGUMENT); $miscXmlFile = realpath($miscXmlFilePath); $force = $input->getOption('force'); @@ -71,7 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output) //Locate ProjectResources node, create one if none are found. $nodeForWork = null; - foreach($dom->getElementsByTagName('component') as $child) { + foreach ($dom->getElementsByTagName('component') as $child) { if ($child->getAttribute('name') === 'ProjectResources') { $nodeForWork = $child; } @@ -109,35 +121,74 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Generates urn => location array for all MFTF schema. + * * @return array - * @throws TestFrameworkException */ private function generateResourcesArray() { $resourcesArray = [ 'urn:magento:mftf:DataGenerator/etc/dataOperation.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd'), + $this->getResourcePath('DataGenerator/etc/dataOperation.xsd'), 'urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd'), + $this->getResourcePath('DataGenerator/etc/dataProfileSchema.xsd'), 'urn:magento:mftf:Page/etc/PageObject.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd'), + $this->getResourcePath('Page/etc/PageObject.xsd'), 'urn:magento:mftf:Page/etc/SectionObject.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd'), + $this->getResourcePath('Page/etc/SectionObject.xsd'), 'urn:magento:mftf:Test/etc/actionGroupSchema.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd'), + $this->getResourcePath('Test/etc/actionGroupSchema.xsd'), 'urn:magento:mftf:Test/etc/testSchema.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd'), + $this->getResourcePath('Test/etc/testSchema.xsd'), 'urn:magento:mftf:Suite/etc/suiteSchema.xsd' => - realpath(FilePathFormatter::format(FW_BP) - . 'src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd') + $this->getResourcePath('Suite/etc/suiteSchema.xsd') ]; return $resourcesArray; } + /** + * Returns path (full or PhpStorm project-based) to XSD file + * + * @param $relativePath + * @return string + * @throws TestFrameworkException + */ + private function getResourcePath($relativePath) + { + $urnPath = realpath(FilePathFormatter::format(FW_BP) . self::MFTF_SRC_PATH . $relativePath); + $projectRoot = $this->getProjectRootPath(); + + if ($projectRoot !== null) { + return str_replace($projectRoot, self::PROJECT_PATH_IDENTIFIER, $urnPath); + } + + return $urnPath; + } + + /** + * Returns Project root directory absolute path + * @TODO Find out how to detect other types of installation + * + * @return string|null + */ + private function getProjectRootPath() + { + $frameworkRoot = realpath(__DIR__); + + if ($this->isInstalledByComposer($frameworkRoot)) { + return strstr($frameworkRoot, '/vendor/', true); + } + + return null; + } + + /** + * Determines whether MFTF was installed using Composer + * + * @param string $frameworkRoot + * @return bool + */ + private function isInstalledByComposer($frameworkRoot) + { + return false !== strpos($frameworkRoot, '/vendor/'); + } } diff --git a/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php b/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php deleted file mode 100644 index 7def3894f..000000000 --- a/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -declare(strict_types = 1); - -namespace Magento\FunctionalTestingFramework\Console; - -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; -use Magento\FunctionalTestingFramework\Util\DocGenerator; -use PhpParser\Comment\Doc; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -class GenerateDocsCommand extends Command -{ - /** - * Configures the current command. - * - * @return void - */ - protected function configure() - { - $this->setName('generate:docs') - ->setDescription('This command generates documentation for created MFTF files.') - ->addOption( - "output", - 'o', - InputOption::VALUE_REQUIRED, - 'Output Directory' - )->addOption( - "clean", - 'c', - InputOption::VALUE_NONE, - 'Clean Output Directory' - )->addOption( - "force", - 'f', - InputOption::VALUE_NONE, - 'Force Document Generation For All Action Groups' - ); - } - - /** - * Executes the current command. - * - * @param InputInterface $input - * @param OutputInterface $output - * @return void - * @throws TestFrameworkException - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException - * @throws \Magento\FunctionalTestingFramework\Exceptions\XmlException - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - defined('COMMAND') || define('COMMAND', 'generate:docs'); - $config = $input->getOption('output'); - $clean = $input->getOption('clean'); - $force = $input->getOption('force'); - - MftfApplicationConfig::create( - $force, - MftfApplicationConfig::GENERATION_PHASE, - false, - MftfApplicationConfig::LEVEL_NONE, - true - ); - - $allActionGroups = ActionGroupObjectHandler::getInstance()->getAllObjects(); - $docGenerator = new DocGenerator(); - $docGenerator->createDocumentation($allActionGroups, $config, $clean); - - $output->writeln("Generate Docs Command Run"); - - if (empty($config)) { - $output->writeln("Output to ". DocGenerator::DEFAULT_OUTPUT_DIR); - } else { - $output->writeln("Output to ". $config); - } - } -} diff --git a/src/Magento/FunctionalTestingFramework/Console/GenerateSuiteCommand.php b/src/Magento/FunctionalTestingFramework/Console/GenerateSuiteCommand.php index 2c91aa7f7..8da3493aa 100644 --- a/src/Magento/FunctionalTestingFramework/Console/GenerateSuiteCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/GenerateSuiteCommand.php @@ -58,9 +58,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $allowSkipped ); - $this->setOutputStyle($input, $output); - $this->showMftfNotices($output); - // Remove previous GENERATED_DIR if --remove option is used if ($remove) { $this->removeGeneratedDirectory($output, $output->isVerbose()); diff --git a/src/Magento/FunctionalTestingFramework/Console/GenerateTestsCommand.php b/src/Magento/FunctionalTestingFramework/Console/GenerateTestsCommand.php index 3ca53f8f6..b76d3ab3c 100644 --- a/src/Magento/FunctionalTestingFramework/Console/GenerateTestsCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/GenerateTestsCommand.php @@ -77,7 +77,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->setOutputStyle($input, $output); + $this->setIOStyle($input, $output); $tests = $input->getArgument('name'); $config = $input->getOption('config'); $json = $input->getOption('tests'); // for backward compatibility @@ -107,9 +107,6 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - $this->setOutputStyle($input, $output); - $this->showMftfNotices($output); - if (!empty($tests)) { $json = $this->getTestAndSuiteConfiguration($tests); } @@ -126,8 +123,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Remove previous GENERATED_DIR if --remove option is used if ($remove) { - $this->removeGeneratedDirectory($output, $verbose || - ($debug !== MftfApplicationConfig::LEVEL_NONE)); + $this->removeGeneratedDirectory($output, $verbose); } try { diff --git a/src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php b/src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php index 08b84d6a1..373256cfc 100644 --- a/src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php @@ -84,9 +84,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $allowSkipped ); - $this->setOutputStyle($input, $output); - $this->showMftfNotices($output); - $testConfiguration = $this->getTestAndSuiteConfiguration($tests); if (!$skipGeneration) { diff --git a/src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php b/src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php index 1909c7e0b..c6a2d0b76 100644 --- a/src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/RunTestFailedCommand.php @@ -96,9 +96,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $allowSkipped ); - $this->setOutputStyle($input, $output); - $this->showMftfNotices($output); - $testConfiguration = $this->getFailedTestList(); if ($testConfiguration === null) { @@ -168,11 +165,7 @@ private function getFailedTestList() if ($suiteName == self::DEFAULT_TEST_GROUP) { array_push($failedTestDetails['tests'], $testName); } else { - // Trim potential suite_parallel_0 to suite_parallel - $suiteNameArray = explode("_", $suiteName); - if (is_numeric(array_pop($suiteNameArray))) { - $suiteName = implode("_", $suiteNameArray); - } + $suiteName = $this->sanitizeSuiteName($suiteName); $failedTestDetails['suites'] = array_merge_recursive( $failedTestDetails['suites'], [$suiteName => [$testName]] @@ -194,6 +187,23 @@ private function getFailedTestList() return $testConfigurationJson; } + /** + * Trim potential suite_parallel_0_G to suite_parallel + * + * @param string $suiteName + * @return string + */ + private function sanitizeSuiteName($suiteName) + { + $suiteNameArray = explode("_", $suiteName); + if (array_pop($suiteNameArray) == 'G') { + if (is_numeric(array_pop($suiteNameArray))) { + $suiteName = implode("_", $suiteNameArray); + } + } + return $suiteName; + } + /** * Returns an array of run commands read from the manifest file created post generation * diff --git a/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php b/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php index be6236c73..6ea37785d 100644 --- a/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php @@ -79,9 +79,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $allowSkipped ); - $this->setOutputStyle($input, $output); - $this->showMftfNotices($output); - if (!$skipGeneration) { $testConfiguration = $this->getGroupAndSuiteConfiguration($groups); $command = $this->getApplication()->find('generate:tests'); diff --git a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php index 30c9cd600..fe07dbaaf 100644 --- a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php @@ -15,11 +15,20 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Exception; +use Symfony\Component\Console\Style\SymfonyStyle; class StaticChecksCommand extends Command { + /** + * Associative array containing static ruleset properties. + * + * @var array + */ + private $ruleSet; + /** * Pool of all existing static check objects * @@ -34,6 +43,13 @@ class StaticChecksCommand extends Command */ private $staticCheckObjects; + /** + * Console output style + * + * @var SymfonyStyle + */ + protected $ioStyle; + /** * Configures the current command. * @@ -44,14 +60,20 @@ protected function configure() $list = new StaticChecksList(); $this->allStaticCheckObjects = $list->getStaticChecks(); $staticCheckNames = implode(', ', array_keys($this->allStaticCheckObjects)); - $description = "This command will run all static checks on xml test materials. " - . "Available static check scripts are:\n{$staticCheckNames}"; + $description = 'This command will run all static checks on xml test materials. ' + . 'Available static check scripts are:' . PHP_EOL . $staticCheckNames; $this->setName('static-checks') ->setDescription($description) ->addArgument( 'names', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'name(s) of specific static check script(s) to run' + )->addOption( + 'path', + 'p', + InputOption::VALUE_OPTIONAL, + 'Path to a MFTF test module to run "deprecatedEntityUsage" static check script. ' . PHP_EOL + . 'Option is ignored by other static check scripts.' . PHP_EOL ); } @@ -65,32 +87,41 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->ioStyle = new SymfonyStyle($input, $output); try { - $this->validateInputArguments($input, $output); + $this->validateInput($input); } catch (InvalidArgumentException $e) { LoggingUtil::getInstance()->getLogger(StaticChecksCommand::class)->error($e->getMessage()); - $output->writeln($e->getMessage() . " Please fix input arguments and rerun."); + $this->ioStyle->error($e->getMessage() . ' Please fix input argument(s) or option(s) and rerun.'); return 1; } + $cmdFailed = false; $errors = []; foreach ($this->staticCheckObjects as $name => $staticCheck) { LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->info( - "\nRunning static check script for: " . $name - ); - $output->writeln( - "\nRunning static check script for: " . $name + 'Running static check script for: ' . $name . PHP_EOL ); - $staticCheck->execute($input); + $this->ioStyle->text(PHP_EOL . 'Running static check script for: ' . $name . PHP_EOL); + $start = microtime(true); + try { + $staticCheck->execute($input); + } catch (Exception $e) { + $cmdFailed = true; + LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->error($e->getMessage() . PHP_EOL); + $this->ioStyle->error($e->getMessage()); + } + $end = microtime(true); + $errors += $staticCheck->getErrors(); $staticOutput = $staticCheck->getOutput(); LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->info($staticOutput); - $output->writeln($staticOutput); - $errors += $staticCheck->getErrors(); - } + $this->ioStyle->text($staticOutput); - if (empty($errors)) { + $this->ioStyle->text('Total execution time is ' . (string)($end - $start) . ' seconds.' . PHP_EOL); + } + if (!$cmdFailed && empty($errors)) { return 0; } else { return 1; @@ -104,30 +135,73 @@ protected function execute(InputInterface $input, OutputInterface $output) * @return void * @throws InvalidArgumentException */ - private function validateInputArguments(InputInterface $input) + private function validateInput(InputInterface $input) { $this->staticCheckObjects = []; $requiredChecksNames = $input->getArgument('names'); - $invalidCheckNames = []; - // Found user required static check script(s) to run, - // If no static check name is supplied, run all static check scripts + // Build list of static check names to run. + if (empty($requiredChecksNames)) { + $this->parseRulesetJson(); + $requiredChecksNames = $this->ruleSet['tests'] ?? null; + } if (empty($requiredChecksNames)) { $this->staticCheckObjects = $this->allStaticCheckObjects; } else { - for ($index = 0; $index < count($requiredChecksNames); $index++) { - if (in_array($requiredChecksNames[$index], array_keys($this->allStaticCheckObjects))) { - $this->staticCheckObjects[$requiredChecksNames[$index]] = - $this->allStaticCheckObjects[$requiredChecksNames[$index]]; - } else { - $invalidCheckNames[] = $requiredChecksNames[$index]; - } + $this->validateTestNames($requiredChecksNames); + } + + if ($input->getOption('path')) { + if ( (count($this->staticCheckObjects) !== 1) + || array_keys($this->staticCheckObjects)[0] !== StaticChecksList::DEPRECATED_ENTITY_USAGE_CHECK_NAME ) + throw new InvalidArgumentException( + '--path option can only be used for "' + . StaticChecksList::DEPRECATED_ENTITY_USAGE_CHECK_NAME + . '".' + ); + } + } + + /** + * Validates that all passed in static-check names match an existing static check + * @param string[] $requiredChecksNames + * @return void + */ + private function validateTestNames($requiredChecksNames) + { + $invalidCheckNames = []; + for ($index = 0; $index < count($requiredChecksNames); $index++) { + if (in_array($requiredChecksNames[$index], array_keys($this->allStaticCheckObjects))) { + $this->staticCheckObjects[$requiredChecksNames[$index]] = + $this->allStaticCheckObjects[$requiredChecksNames[$index]]; + } else { + $invalidCheckNames[] = $requiredChecksNames[$index]; } } if (!empty($invalidCheckNames)) { throw new InvalidArgumentException( - "Invalid static check script(s): " . implode(', ', $invalidCheckNames) . "." + 'Invalid static check script(s): ' . implode(', ', $invalidCheckNames) . '.' ); } } + + /** + * Parses and sets local ruleSet. If not found, simply returns and lets script continue. + * @return void; + */ + private function parseRulesetJson() + { + $pathAddition = "/dev/tests/acceptance/"; + // MFTF is both NOT attached and no MAGENTO_BP defined in .env + if (MAGENTO_BP === FW_BP) { + $pathAddition = "/dev/"; + } + $pathToRuleset = MAGENTO_BP . $pathAddition . "staticRuleset.json"; + if (!file_exists($pathToRuleset)) { + $this->ioStyle->text("No ruleset under $pathToRuleset" . PHP_EOL); + return; + } + $this->ioStyle->text("Using ruleset under $pathToRuleset" . PHP_EOL); + $this->ruleSet = json_decode(file_get_contents($pathToRuleset), true); + } } diff --git a/src/Magento/FunctionalTestingFramework/Console/UpgradeTestsCommand.php b/src/Magento/FunctionalTestingFramework/Console/UpgradeTestsCommand.php index 8e24290b5..526ab4903 100644 --- a/src/Magento/FunctionalTestingFramework/Console/UpgradeTestsCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/UpgradeTestsCommand.php @@ -32,8 +32,12 @@ class UpgradeTestsCommand extends Command protected function configure() { $this->setName('upgrade:tests') - ->setDescription('This command will upgrade all tests in the provided path according to new MFTF Major version requirements.') - ->addArgument('path', InputArgument::REQUIRED, 'path to MFTF tests to upgrade'); + ->setDescription( + 'This command will upgrade MFTF tests according to new MFTF Major version requirements. ' + . 'It will upgrade MFTF tests in specific path when "path" argument is specified, otherwise it will ' + . 'upgrade all MFTF tests installed.' + ) + ->addArgument('path', InputArgument::OPTIONAL, 'path to MFTF tests to upgrade'); $this->upgradeScriptsList = new UpgradeScriptList(); } @@ -49,10 +53,11 @@ protected function execute(InputInterface $input, OutputInterface $output) { /** @var \Magento\FunctionalTestingFramework\Upgrade\UpgradeInterface[] $upgradeScriptObjects */ $upgradeScriptObjects = $this->upgradeScriptsList->getUpgradeScripts(); - foreach ($upgradeScriptObjects as $upgradeScriptObject) { - $upgradeOutput = $upgradeScriptObject->execute($input); + foreach ($upgradeScriptObjects as $scriptName => $upgradeScriptObject) { + $output->writeln('Running upgrade script: ' . $scriptName . PHP_EOL); + $upgradeOutput = $upgradeScriptObject->execute($input, $output); LoggingUtil::getInstance()->getLogger(get_class($upgradeScriptObject))->info($upgradeOutput); - $output->writeln($upgradeOutput); + $output->writeln($upgradeOutput . PHP_EOL); } } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Dom.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Dom.php index d4b8f7c8f..bc19c35aa 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Dom.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Dom.php @@ -81,6 +81,13 @@ public function initDom($xml, $filename = null) } } + $itemNodes = $dom->getElementsByTagName('item'); + /** @var \DOMElement $itemNode */ + foreach ($itemNodes as $itemKey => $itemNode) { + if ($itemNode->hasAttribute("name") == false) { + $itemNode->setAttribute("name", (string)$itemKey); + } + } return $dom; } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Reader/Filesystem.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Reader/Filesystem.php deleted file mode 100644 index 4f21fabea..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Config/Reader/Filesystem.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Config\Reader; - -/** - * Filesystem configuration loader. Loads configuration from XML files, split by scopes. - */ -class Filesystem extends \Magento\FunctionalTestingFramework\Config\Reader\Filesystem -{ - /** - * An array of paths which do have a key for merging but instead are value based nodes which can only be appended - * - * @var array - */ - private $mergeablePaths; - - /** - * Constructor - * - * @param \Magento\FunctionalTestingFramework\Config\FileResolverInterface $fileResolver - * @param \Magento\FunctionalTestingFramework\Config\ConverterInterface $converter - * @param \Magento\FunctionalTestingFramework\Config\SchemaLocatorInterface $schemaLocator - * @param \Magento\FunctionalTestingFramework\Config\ValidationStateInterface $validationState - * @param string $fileName - * @param array $idAttributes - * @param array $mergeablePaths - * @param string $domDocumentClass - * @param string $defaultScope - */ - public function __construct( - \Magento\FunctionalTestingFramework\Config\FileResolverInterface $fileResolver, - \Magento\FunctionalTestingFramework\Config\ConverterInterface $converter, - \Magento\FunctionalTestingFramework\Config\SchemaLocatorInterface $schemaLocator, - \Magento\FunctionalTestingFramework\Config\ValidationStateInterface $validationState, - $fileName, - $idAttributes = [], - $mergeablePaths = [], - $domDocumentClass = \Magento\FunctionalTestingFramework\Config\Dom::class, - $defaultScope = 'global' - ) { - $this->fileResolver = $fileResolver; - $this->converter = $converter; - $this->fileName = $fileName; - $this->idAttributes = array_replace($this->idAttributes, $idAttributes); - $this->mergeablePaths = $mergeablePaths; - $this->validationState = $validationState; - $this->schemaFile = $schemaLocator->getSchema(); - $this->perFileSchema = $schemaLocator->getPerFileSchema() && $validationState->isValidationRequired() - ? $schemaLocator->getPerFileSchema() : null; - $this->domDocumentClass = $domDocumentClass; - $this->defaultScope = $defaultScope; - } - - /** - * Return newly created instance of a config merger. Overridden to include new arg in mergerClass. - * - * @param string $mergerClass - * @param string $initialContents - * @return \Magento\FunctionalTestingFramework\Config\Dom - * @throws \UnexpectedValueException - */ - protected function createConfigMerger($mergerClass, $initialContents) - { - $result = new $mergerClass( - $initialContents, - $this->idAttributes, - $this->mergeablePaths, - null, - $this->perFileSchema - ); - if (!$result instanceof \Magento\FunctionalTestingFramework\Config\Dom) { - throw new \UnexpectedValueException( - "Instance of the DOM config merger is expected, got {$mergerClass} instead." - ); - } - return $result; - } -} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php index a210710db..5a4b42dc4 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php @@ -14,6 +14,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\DataGenerator\Util\DataExtensionUtil; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; class DataObjectHandler implements ObjectHandlerInterface { @@ -58,6 +59,20 @@ class DataObjectHandler implements ObjectHandlerInterface */ private $extendUtil; + /** + * Validates and keeps track of entity name violations. + * + * @var NameValidationUtil + */ + private $entityNameValidator; + + /** + * Validates and keeps track of entity key violations. + * + * @var NameValidationUtil + */ + private $entityKeyValidator; + /** * Constructor */ @@ -68,6 +83,8 @@ private function __construct() if (!$parserOutput) { return; } + $this->entityNameValidator = new NameValidationUtil(); + $this->entityKeyValidator = new NameValidationUtil(); $this->entityDataObjects = $this->processParserOutput($parserOutput); $this->extendUtil = new DataExtensionUtil(); } @@ -132,6 +149,12 @@ private function processParserOutput($parserOutput) throw new XmlException(sprintf(self::DATA_NAME_ERROR_MSG, $name)); } + $filename = $rawEntity[self::_FILENAME] ?? null; + $this->entityNameValidator->validatePascalCase( + $name, + NameValidationUtil::DATA_ENTITY_NAME, + $filename + ); $type = $rawEntity[self::_TYPE] ?? null; $data = []; $deprecated = null; @@ -139,7 +162,6 @@ private function processParserOutput($parserOutput) $uniquenessData = []; $vars = []; $parentEntity = null; - $filename = $rawEntity[self::_FILENAME] ?? null; if (array_key_exists(self::_DATA, $rawEntity)) { $data = $this->processDataElements($rawEntity); @@ -188,7 +210,8 @@ private function processParserOutput($parserOutput) $entityDataObjects[$entityDataObject->getName()] = $entityDataObject; } - + $this->entityNameValidator->summarize(NameValidationUtil::DATA_ENTITY_NAME); + $this->entityKeyValidator->summarize(NameValidationUtil::DATA_ENTITY_KEY); return $entityDataObjects; } @@ -203,8 +226,8 @@ private function processParserOutput($parserOutput) private function processArray($arrayItems, $data, $key) { $items = []; - foreach ($arrayItems as $item) { - $items[] = $item[self::_VALUE]; + foreach ($arrayItems as $key => $item) { + $items[$key] = $item[self::_VALUE]; } return array_merge($items, $data[$key] ?? []); @@ -220,7 +243,14 @@ private function processDataElements($entityData) { $dataValues = []; foreach ($entityData[self::_DATA] as $dataElement) { - $dataElementKey = strtolower($dataElement[self::_KEY]); + $originalDataElementKey = $dataElement[self::_KEY]; + $filename = $entityData[self::_FILENAME] ?? null; + $this->entityKeyValidator->validateCamelCase( + $originalDataElementKey, + NameValidationUtil::DATA_ENTITY_KEY, + $filename + ); + $dataElementKey = strtolower($originalDataElementKey); $dataElementValue = $dataElement[self::_VALUE] ?? ""; $dataValues[$dataElementKey] = $dataElementValue; } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php index 8c2ec7b0a..2c8ab7530 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php @@ -12,6 +12,7 @@ use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; class OperationDefinitionObjectHandler implements ObjectHandlerInterface { @@ -136,7 +137,14 @@ private function initialize() $objectManager = ObjectManagerFactory::getObjectManager(); $parser = $objectManager->create(OperationDefinitionParser::class); $parserOutput = $parser->readOperationMetadata()[OperationDefinitionObjectHandler::ENTITY_OPERATION_ROOT_TAG]; + + $operationNameValidator = new NameValidationUtil(); foreach ($parserOutput as $dataDefName => $opDefArray) { + $operationNameValidator->validatePascalCase( + $dataDefName, + NameValidationUtil::METADATA_OPERATION_NAME + ); + $operation = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_TYPE]; $dataType = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_DATA_TYPE]; $url = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_URL] ?? null; @@ -230,6 +238,7 @@ private function initialize() $deprecated ); } + $operationNameValidator->summarize(NameValidationUtil::METADATA_OPERATION_NAME); } /** diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php index 927c0ab4e..49da76697 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php @@ -86,17 +86,6 @@ public function createEntity( foreach ($dependentObjectKeys as $objectKey) { $retrievedDependentObjects[] = $this->retrieveEntity($objectKey, $scope); } - - foreach ($overrideFields as $index => $field) { - try { - $decrptedField = CredentialStore::getInstance()->decryptAllSecretsInString($field); - if ($decrptedField !== false) { - $overrideFields[$index] = $decrptedField; - } - } catch (TestFrameworkException $e) { - //catch exception if Credentials are not defined - } - } $retrievedEntity = DataObjectHandler::getInstance()->getObject($entity); @@ -107,6 +96,8 @@ public function createEntity( ); } + $overrideFields = $this->resolveOverrideFields($overrideFields); + $persistedObject = new DataPersistenceHandler( $retrievedEntity, $retrievedDependentObjects, @@ -262,4 +253,29 @@ public function clearSuiteObjects() { $this->suiteObjects = []; } + + /** + * Resolve secret values in $overrideFields + * + * @param array $overrideFields + * @return array + */ + private function resolveOverrideFields($overrideFields) + { + foreach ($overrideFields as $index => $field) { + if (is_array($field)) { + $overrideFields[$index] = $this->resolveOverrideFields($field); + } elseif (is_string($field)) { + try { + $decrptedField = CredentialStore::getInstance()->decryptAllSecretsInString($field); + if ($decrptedField !== false) { + $overrideFields[$index] = $decrptedField; + } + } catch (TestFrameworkException $e) { + //catch exception if Credentials are not defined + } + } + } + return $overrideFields; + } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AbstractExecutor.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AbstractExecutor.php deleted file mode 100644 index e27da3718..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AbstractExecutor.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl; - -use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; - -/** - * Abstract Curl executor. - */ -abstract class AbstractExecutor implements CurlInterface -{ - /** - * Returns Magento base URL. Used as a fallback for other services (eg. WebApi, Backend) - * - * @var string - */ - protected static $baseUrl = null; - - /** - * Returns base URL for Magento instance - * @return string - * @throws TestFrameworkException - */ - public function getBaseUrl(): string - { - return UrlFormatter::format(getenv('MAGENTO_BASE_URL')); - } -} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php index 05178c915..362d25e75 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php @@ -6,15 +6,15 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Persist; use Magento\FunctionalTestingFramework\Allure\AllureHelper; -use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\AdminExecutor; -use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\FrontendExecutor; -use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\WebapiExecutor; -use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\WebapiNoAuthExecutor; +use Magento\FunctionalTestingFramework\DataTransport\AdminFormExecutor; +use Magento\FunctionalTestingFramework\DataTransport\FrontendFormExecutor; +use Magento\FunctionalTestingFramework\DataTransport\WebApiExecutor; +use Magento\FunctionalTestingFramework\DataTransport\WebApiNoAuthExecutor; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; use Magento\FunctionalTestingFramework\DataGenerator\Objects\OperationDefinitionObject; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; /** * Class CurlHandler @@ -134,19 +134,21 @@ public function executeRequest($dependentEntities) false ); + AllureHelper::addAttachmentToCurrentStep(json_encode($this->requestData, JSON_PRETTY_PRINT), 'Request Body'); + if (($contentType === 'application/json') && ($authorization === 'adminOauth')) { $this->isJson = true; - $executor = new WebapiExecutor($this->storeCode); + $executor = new WebApiExecutor($this->storeCode); } elseif ($authorization === 'adminFormKey') { - $executor = new AdminExecutor($this->operationDefinition->removeUrlBackend()); + $executor = new AdminFormExecutor($this->operationDefinition->removeUrlBackend()); } elseif ($authorization === 'customerFormKey') { - $executor = new FrontendExecutor( + $executor = new FrontendFormExecutor( $this->requestData['customer_email'], $this->requestData['customer_password'] ); } elseif ($authorization === 'anonymous') { $this->isJson = true; - $executor = new WebapiNoAuthExecutor($this->storeCode); + $executor = new WebApiNoAuthExecutor($this->storeCode); } if (!$executor) { @@ -169,7 +171,6 @@ public function executeRequest($dependentEntities) $response = $executor->read($successRegex, $returnRegex, $returnIndex); $executor->close(); - AllureHelper::addAttachmentToCurrentStep(json_encode($this->requestData, JSON_PRETTY_PRINT), 'Request Body'); AllureHelper::addAttachmentToCurrentStep( json_encode(json_decode($response, true), JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE+JSON_UNESCAPED_SLASHES), 'Response Data' @@ -229,7 +230,7 @@ private function resolveUrlReference($urlIn, $entityObjects) foreach ($entityObjects as $entityObject) { $param = null; - if ($paramEntityParent === "" || $entityObject->getType() == $paramEntityParent) { + if ($paramEntityParent === "" || $entityObject->getType() === $paramEntityParent) { $param = $entityObject->getDataByName( $dataItem, EntityDataObject::CEST_UNIQUE_VALUE diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php index 3a12bdce1..53fe71fc0 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php @@ -62,7 +62,7 @@ public function extendEntity($entityObject) // Get all data for both parent and child and merge $referencedData = $parentEntity->getAllData(); - $newData = array_merge($referencedData, $entityObject->getAllData()); + $newData = array_extend($referencedData, $entityObject->getAllData()); // Get all linked references for both parent and child and merge $referencedLinks = $parentEntity->getLinkedEntities(); diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd index 58fad8d8b..c2682e737 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd @@ -109,4 +109,4 @@ <xs:enumeration value="DELETE" /> </xs:restriction> </xs:simpleType> -</xs:schema> \ No newline at end of file +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd index 9d0d8bb35..923f7c48f 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd @@ -118,17 +118,32 @@ <xs:complexType name="arrayType"> <xs:sequence> - <xs:element name="item" type="xs:string" maxOccurs="unbounded" minOccurs="0"> - <xs:annotation> - <xs:documentation> - Individual piece of data to be passed in as part of the parrent array type. - </xs:documentation> - </xs:annotation> + <xs:element name="item" type="itemType" maxOccurs="unbounded" minOccurs="0"> + <xs:annotation> + <xs:documentation> + Individual piece of data to be passed in as part of the parrent array type. + </xs:documentation> + </xs:annotation> </xs:element> </xs:sequence> <xs:attribute type="xs:string" name="key" use="required"/> </xs:complexType> + + <xs:complexType name="itemType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="name" use="optional"> + <xs:annotation> + <xs:documentation> + Key attribute of item pair. + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="requiredEntityType"> <xs:simpleContent> <xs:extension base="xs:string"> diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AdminExecutor.php b/src/Magento/FunctionalTestingFramework/DataTransport/AdminFormExecutor.php similarity index 76% rename from src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AdminExecutor.php rename to src/Magento/FunctionalTestingFramework/DataTransport/AdminFormExecutor.php index 86b3b742f..5639ee8d7 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/AdminExecutor.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/AdminFormExecutor.php @@ -4,17 +4,19 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl; +namespace Magento\FunctionalTestingFramework\DataTransport; -use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\Util\MftfGlobals; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa\OTP; +use Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa; /** * Curl executor for requests to Admin. */ -class AdminExecutor extends AbstractExecutor implements CurlInterface +class AdminFormExecutor implements CurlInterface { /** * Curl transport protocol. @@ -57,25 +59,6 @@ public function __construct($removeBackend) $this->authorize(); } - /** - * Returns base URL for Magento backend instance - * @return string - * @throws TestFrameworkException - */ - public function getBaseUrl(): string - { - $backendHost = getenv('MAGENTO_BACKEND_BASE_URL') - ? - UrlFormatter::format(getenv('MAGENTO_BACKEND_BASE_URL')) - : - parent::getBaseUrl(); - return empty(getenv('MAGENTO_BACKEND_NAME')) - ? - $backendHost - : - $backendHost . getenv('MAGENTO_BACKEND_NAME') . '/'; - } - /** * Authorize admin on backend. * @@ -85,11 +68,11 @@ public function getBaseUrl(): string private function authorize() { // Perform GET to backend url so form_key is set - $this->transport->write($this->getBaseUrl(), [], CurlInterface::GET); + $this->transport->write(MftfGlobals::getBackendBaseUrl(), [], CurlInterface::GET); $this->read(); // Authenticate admin user - $authUrl = $this->getBaseUrl() . 'admin/auth/login/'; + $authUrl = MftfGlobals::getBackendBaseUrl() . 'admin/auth/login/'; $data = [ 'login[username]' => getenv('MAGENTO_ADMIN_USERNAME'), 'login[password]' => getenv('MAGENTO_ADMIN_PASSWORD'), @@ -97,9 +80,25 @@ private function authorize() ]; $this->transport->write($authUrl, $data, CurlInterface::POST); $response = $this->read(); + if (strpos($response, 'login-form')) { throw new TestFrameworkException('Admin user authentication failed!'); } + + // Get OTP + if (Tfa::isEnabled()) { + $authUrl = MftfGlobals::getBackendBaseUrl() . Tfa::getProviderAdminFormEndpoint('google'); + $data = [ + 'tfa_code' => OTP::getOTP(), + 'form_key' => $this->formKey, + ]; + $this->transport->write($authUrl, $data, CurlInterface::POST); + $response = json_decode($this->read()); + + if (!$response->success) { + throw new TestFrameworkException('Admin user 2FA authentication failed!'); + } + } } /** @@ -128,10 +127,11 @@ private function setFormKey() public function write($url, $data = [], $method = CurlInterface::POST, $headers = []) { $url = ltrim($url, "/"); - $apiUrl = $this->getBaseUrl() . $url; + $apiUrl = MftfGlobals::getBackendBaseUrl() . $url; if ($this->removeBackend) { - $apiUrl = parent::getBaseUrl() . $url; + //TODO + //Cannot find usage. Do we need this? } if ($this->formKey) { diff --git a/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa.php b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa.php new file mode 100644 index 000000000..04f1971b7 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataTransport\Auth; + +use Magento\FunctionalTestingFramework\Util\MftfGlobals; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; + +/** + * Class Tfa (i.e. 2FA) + */ +class Tfa +{ + const WEB_API_AUTH_GOOGLE = 'V1/tfa/provider/google/authenticate'; + const ADMIN_FORM_AUTH_GOOGLE = 'tfa/google/authpost/?isAjax=true'; + const TFA_SCHEMA = 'schema?services=twoFactorAuthAdminTokenServiceV1'; + + /** + * If 2FA is enabled + * + * @var boolean|null + */ + private static $tfaEnabled = null; + + /** Rest request headers + * + * @var string[] + */ + private static $headers = [ + 'Accept: application/json', + 'Content-Type: application/json', + ]; + + /** + * 2FA provider web API authentication endpoints + * + * @var string[] + */ + private static $providerWebApiAuthEndpoints = [ + 'google' => self::WEB_API_AUTH_GOOGLE, + ]; + + /** + * 2FA provider admin form authentication endpoints + * + * @var string[] + */ + private static $providerAdminFormAuthEndpoints = [ + 'google' => self::ADMIN_FORM_AUTH_GOOGLE, + ]; + + /** + * Check if 2FA is enabled for Magento instance under test + * + * @return boolean + * @throws TestFrameworkException + */ + public static function isEnabled() + { + if (self::$tfaEnabled !== null) { + return self::$tfaEnabled; + } + + $schemaUrl = MftfGlobals::getWebApiBaseUrl() . self::TFA_SCHEMA; + $transport = new CurlTransport(); + try { + $transport->write($schemaUrl, [], CurlInterface::GET, self::$headers); + $response = $transport->read(); + $transport->close(); + $schema = json_decode($response, true); + if (isset($schema['definitions'], $schema['paths'])) { + return true; + } + } catch (TestFrameworkException $e) { + $transport->close(); + } + return false; + } + + /** + * Return provider's 2FA web API authentication endpoint + * + * @param string $name + * @return string|null + */ + public static function getProviderWebApiAuthEndpoint($name) + { + // Currently only support Google Authenticator + return self::$providerWebApiAuthEndpoints[$name] ?? null; + } + + /** + * Return 2FA provider's admin form authentication endpoint + * + * @param string $name + * @return string|null + */ + public static function getProviderAdminFormEndpoint($name) + { + // Currently only support Google Authenticator + return self::$providerAdminFormAuthEndpoints[$name] ?? null; + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php new file mode 100644 index 000000000..dcd6715c9 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php @@ -0,0 +1,61 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use OTPHP\TOTP; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; + +/** + * Class OTP + */ +class OTP +{ + const OTP_SHARED_SECRET_PATH = 'magento/tfa/OTP_SHARED_SECRET'; + + /** + * TOTP object + * + * @var TOTP + */ + private static $totp = null; + + /** + * Return OTP for custom secret stored in `magento/tfa/OTP_SHARED_SECRET` + * + * @return string + * @throws TestFrameworkException + */ + public static function getOTP() + { + return self::create()->now(); + } + + /** + * Create TOTP object + * + * @return TOTP + * @throws TestFrameworkException + */ + private static function create() + { + if (self::$totp === null) { + try { + // Get shared secret from Credential storage + $encryptedSecret = CredentialStore::getInstance()->getSecret(self::OTP_SHARED_SECRET_PATH); + $secret = CredentialStore::getInstance()->decryptSecretValue($encryptedSecret); + } catch (TestFrameworkException $e) { + throw new TestFrameworkException('Unable to get OTP' . PHP_EOL . $e->getMessage()); + } + + self::$totp = TOTP::create($secret); + self::$totp->setIssuer('MFTF'); + self::$totp->setLabel('MFTF Testing'); + } + return self::$totp; + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataTransport/Auth/WebApiAuth.php b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/WebApiAuth.php new file mode 100644 index 000000000..566d2b348 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/WebApiAuth.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataTransport\Auth; + +use Magento\FunctionalTestingFramework\Util\MftfGlobals; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa\OTP; + +/** + * Class WebApiAuth + */ +class WebApiAuth +{ + const PATH_ADMIN_AUTH = 'V1/integration/admin/token'; + + /** Rest request headers + * + * @var string[] + */ + private static $headers = [ + 'Accept: application/json', + 'Content-Type: application/json', + ]; + + /** + * Tokens for admin users + * + * @var string[] + */ + private static $adminAuthTokens = []; + + /** + * Return the API token for an admin user + * Use MAGENTO_ADMIN_USERNAME and MAGENTO_ADMIN_PASSWORD when $username and/or $password is/are omitted + * + * @param string $username + * @param string $password + * @return string + * @throws TestFrameworkException + */ + public static function getAdminToken($username = null, $password = null) + { + $login = $username ?? getenv('MAGENTO_ADMIN_USERNAME'); + $password = $password ?? getenv('MAGENTO_ADMIN_PASSWORD'); + if (!$login || !$password) { + $message = 'Cannot retrieve API token without credentials. Please fill out .env.'; + $context = [ + 'MAGENTO_BASE_URL' => getenv('MAGENTO_BASE_URL'), + 'MAGENTO_BACKEND_BASE_URL' => getenv('MAGENTO_BACKEND_BASE_URL'), + 'MAGENTO_ADMIN_USERNAME' => getenv('MAGENTO_ADMIN_USERNAME'), + 'MAGENTO_ADMIN_PASSWORD' => getenv('MAGENTO_ADMIN_PASSWORD'), + ]; + throw new TestFrameworkException($message, $context); + } + + if (isset(self::$adminAuthTokens[$login])) { + return self::$adminAuthTokens[$login]; + } + + $authUrl = MftfGlobals::getWebApiBaseUrl() . self::PATH_ADMIN_AUTH; + + $data = [ + 'username' => $login, + 'password' => $password + ]; + + if (Tfa::isEnabled()) { + $authUrl = MftfGlobals::getWebApiBaseUrl() . Tfa::getProviderWebApiAuthEndpoint('google'); + $data['otp'] = OTP::getOTP(); + } + + $transport = new CurlTransport(); + $transport->write( + $authUrl, + json_encode($data, JSON_PRETTY_PRINT), + CurlInterface::POST, + self::$headers + ); + + try { + $response = $transport->read(); + $transport->close(); + $token = json_decode($response); + if ($token !== null) { + self::$adminAuthTokens[$login] = $token; + return $token; + } + $errMessage = "Invalid response: {$response}"; + } catch (TestFrameworkException $e) { + $transport->close(); + $errMessage = $e->getMessage(); + } + + $message = 'Cannot retrieve API token with credentials. Please check the following credentials'; + $message .= Tfa::isEnabled() ? ' and 2FA settings:' : ':' . PHP_EOL; + $message .= "username: {$login}" . PHP_EOL; + $message .= "password: {$password}" . PHP_EOL; + $message .= $errMessage; + $context = ['url' => $authUrl]; + throw new TestFrameworkException($message, $context); + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/FrontendExecutor.php b/src/Magento/FunctionalTestingFramework/DataTransport/FrontendFormExecutor.php similarity index 90% rename from src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/FrontendExecutor.php rename to src/Magento/FunctionalTestingFramework/DataTransport/FrontendFormExecutor.php index 799cd6d5c..0cf69ec94 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/FrontendExecutor.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/FrontendFormExecutor.php @@ -4,16 +4,17 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl; +namespace Magento\FunctionalTestingFramework\DataTransport; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\Util\MftfGlobals; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; /** * Curl executor for requests to Frontend. */ -class FrontendExecutor extends AbstractExecutor implements CurlInterface +class FrontendFormExecutor implements CurlInterface { /** * Curl transport protocol. @@ -58,7 +59,7 @@ class FrontendExecutor extends AbstractExecutor implements CurlInterface private $customerPassword; /** - * FrontendExecutor constructor. + * FrontendFormExecutor constructor. * * @param string $customerEmail * @param string $customerPassWord @@ -81,11 +82,11 @@ public function __construct($customerEmail, $customerPassWord) */ private function authorize() { - $url = $this->getBaseUrl() . 'customer/account/login/'; + $url = MftfGlobals::getBaseUrl() . 'customer/account/login/'; $this->transport->write($url, [], CurlInterface::GET); $this->read(); - $url = $this->getBaseUrl() . 'customer/account/loginPost/'; + $url = MftfGlobals::getBaseUrl() . 'customer/account/loginPost/'; $data = [ 'login[username]' => $this->customerEmail, 'login[password]' => $this->customerPassword, @@ -143,7 +144,7 @@ public function write($url, $data = [], $method = CurlInterface::POST, $headers if (isset($data['customer_password'])) { unset($data['customer_password']); } - $apiUrl = $this->getBaseUrl() . $url; + $apiUrl = MftfGlobals::getBaseUrl() . $url; if ($this->formKey) { $data['form_key'] = $this->formKey; } else { diff --git a/src/Magento/FunctionalTestingFramework/Util/Protocol/CurlInterface.php b/src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlInterface.php similarity index 94% rename from src/Magento/FunctionalTestingFramework/Util/Protocol/CurlInterface.php rename to src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlInterface.php index a2d6bc344..d15dbb18b 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Protocol/CurlInterface.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlInterface.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\Util\Protocol; +namespace Magento\FunctionalTestingFramework\DataTransport\Protocol; /** * Curl protocol interface. diff --git a/src/Magento/FunctionalTestingFramework/Util/Protocol/CurlTransport.php b/src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlTransport.php similarity index 99% rename from src/Magento/FunctionalTestingFramework/Util/Protocol/CurlTransport.php rename to src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlTransport.php index 16c716e22..a34bad6ce 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Protocol/CurlTransport.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Protocol/CurlTransport.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\Util\Protocol; +namespace Magento\FunctionalTestingFramework\DataTransport\Protocol; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiExecutor.php b/src/Magento/FunctionalTestingFramework/DataTransport/WebApiExecutor.php similarity index 51% rename from src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiExecutor.php rename to src/Magento/FunctionalTestingFramework/DataTransport/WebApiExecutor.php index 494ce8f97..4c6682438 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiExecutor.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/WebApiExecutor.php @@ -4,29 +4,30 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl; +namespace Magento\FunctionalTestingFramework\DataTransport; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\Util\MftfGlobals; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\DataTransport\Auth\WebApiAuth; /** * Curl executor for Magento Web Api requests. */ -class WebapiExecutor extends AbstractExecutor implements CurlInterface +class WebApiExecutor implements CurlInterface { /** - * Curl transport protocol. + * Curl transport protocol * * @var CurlTransport */ private $transport; /** - * Api headers. + * Rest request headers * - * @var array + * @var string[] */ private $headers = [ 'Accept: application/json', @@ -34,33 +35,14 @@ class WebapiExecutor extends AbstractExecutor implements CurlInterface ]; /** - * Response data. - * - * @var string - */ - private $response; - - /** - * Admin authentication url. - */ - const ADMIN_AUTH_URL = '/V1/integration/admin/token'; - - /** - * Store code in api request. + * Store code in API request * * @var string */ private $storeCode; /** - * Admin user auth token. - * - * @var string - */ - private $authToken; - - /** - * WebapiExecutor Constructor. + * WebApiExecutor Constructor * * @param string $storeCode * @throws TestFrameworkException @@ -68,59 +50,22 @@ class WebapiExecutor extends AbstractExecutor implements CurlInterface public function __construct($storeCode = null) { $this->storeCode = $storeCode; - $this->authToken = null; $this->transport = new CurlTransport(); $this->authorize(); } /** - * Returns base URL for Magento Web API instance - * @return string - * @throws TestFrameworkException - */ - public function getBaseUrl(): string - { - $webapiHost = getenv('MAGENTO_RESTAPI_SERVER_HOST'); - $webapiPort = getenv("MAGENTO_RESTAPI_SERVER_PORT"); - $webapiProtocol = getenv("MAGENTO_RESTAPI_SERVER_PROTOCOL"); - - if ($webapiHost && $webapiProtocol) { - $baseUrl = UrlFormatter::format( - sprintf('%s://%s', $webapiProtocol, $webapiHost), - false - ); - } elseif ($webapiHost) { - $baseUrl = UrlFormatter::format(sprintf('%s', $webapiProtocol, $webapiHost), false); - } - - if (!isset($baseUrl)) { - $baseUrl = rtrim(parent::getBaseUrl(), '/'); - } - - if ($webapiPort) { - $baseUrl .= ':' . $webapiPort; - } - - return $baseUrl . '/'; - } - - /** - * Acquire and store the authorization token needed for REST requests. + * Acquire and store the authorization token needed for REST requests * * @return void * @throws TestFrameworkException */ protected function authorize() { - $authUrl = $this->getFormattedUrl(self::ADMIN_AUTH_URL); - $authCreds = [ - 'username' => getenv('MAGENTO_ADMIN_USERNAME'), - 'password' => getenv('MAGENTO_ADMIN_PASSWORD') - ]; - - $this->transport->write($authUrl, json_encode($authCreds), CurlInterface::POST, $this->headers); - $this->authToken = str_replace('"', "", $this->read()); - $this->headers = array_merge(['Authorization: Bearer ' . $this->authToken], $this->headers); + $this->headers = array_merge( + ['Authorization: Bearer ' . WebApiAuth::getAdminToken()], + $this->headers + ); } /** @@ -154,8 +99,7 @@ public function write($url, $data = [], $method = CurlInterface::POST, $headers */ public function read($successRegex = null, $returnRegex = null, $returnIndex = null) { - $this->response = $this->transport->read(); - return $this->response; + return $this->transport->read(); } /** @@ -181,29 +125,19 @@ public function close() } /** - * Builds and returns URL for request, appending storeCode if needed. + * Builds and returns URL for request, appending storeCode if needed + * * @param string $resource * @return string * @throws TestFrameworkException */ - public function getFormattedUrl($resource) + protected function getFormattedUrl($resource) { - $urlResult = $this->getBaseUrl() . 'rest/'; + $urlResult = MftfGlobals::getWebApiBaseUrl(); if ($this->storeCode != null) { $urlResult .= $this->storeCode . '/'; } $urlResult .= trim($resource, '/'); return $urlResult; } - - /** - * Return admin auth token. - * - * @return string - * @throws TestFrameworkException - */ - public function getAuthToken() - { - return $this->authToken; - } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiNoAuthExecutor.php b/src/Magento/FunctionalTestingFramework/DataTransport/WebApiNoAuthExecutor.php similarity index 74% rename from src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiNoAuthExecutor.php rename to src/Magento/FunctionalTestingFramework/DataTransport/WebApiNoAuthExecutor.php index c54bc60b9..066c676f2 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/Curl/WebapiNoAuthExecutor.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/WebApiNoAuthExecutor.php @@ -4,12 +4,12 @@ * See COPYING.txt for license details. */ -namespace Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl; +namespace Magento\FunctionalTestingFramework\DataTransport; /** * Curl executor for Magento Web Api requests that do not require authorization. */ -class WebapiNoAuthExecutor extends WebapiExecutor +class WebApiNoAuthExecutor extends WebApiExecutor { /** * No authorization is needed and just return. diff --git a/src/Magento/FunctionalTestingFramework/Extension/PageReadinessExtension.php b/src/Magento/FunctionalTestingFramework/Extension/PageReadinessExtension.php deleted file mode 100644 index 2dfcbec1a..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/PageReadinessExtension.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension; - -use Codeception\Event\StepEvent; -use Codeception\Event\TestEvent; -use Codeception\Step; -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; -use Magento\FunctionalTestingFramework\Extension\ReadinessMetrics\AbstractMetricCheck; -use Facebook\WebDriver\Exception\TimeOutException; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Monolog\Logger; - -/** - * Class PageReadinessExtension - */ -class PageReadinessExtension extends BaseExtension -{ - /** - * List of action types that should bypass metric checks - * shouldSkipCheck() also checks for the 'Comment' step type, which doesn't follow the $step->getAction() pattern - * - * @var array - */ - private $ignoredActions = [ - 'saveScreenshot', - 'skipReadinessCheck', - 'wait' - ]; - - /** - * @var Logger - */ - private $logger; - - /** - * Logger verbosity - * - * @var boolean - */ - private $verbose; - - /** - * Array of readiness metrics, initialized during beforeTest event - * - * @var AbstractMetricCheck[] - */ - private $readinessMetrics; - - /** - * The name of the active test - * - * @var string - */ - private $testName; - - /** - * Initialize local vars - * - * @return void - * @throws \Exception - */ - public function _initialize() - { - $this->logger = LoggingUtil::getInstance()->getLogger(get_class($this)); - $this->verbose = MftfApplicationConfig::getConfig()->verboseEnabled(); - parent::_initialize(); - } - - /** - * Initialize the readiness metrics for the test - * - * @param TestEvent $e - * @return void - * @throws \Exception - */ - public function beforeTest(TestEvent $e) - { - parent::beforeTest($e); - if (isset($this->config['resetFailureThreshold'])) { - $failThreshold = intval($this->config['resetFailureThreshold']); - } else { - $failThreshold = 3; - } - - $this->testName = $e->getTest()->getMetadata()->getName(); - - $this->getDriver()->_setConfig(['skipReadiness' => false]); - - $metrics = []; - foreach ($this->config['readinessMetrics'] as $metricClass) { - $metrics[] = new $metricClass($this, $failThreshold); - } - - $this->readinessMetrics = $metrics; - } - - /** - * Waits for busy page flags to disappear before executing a step - * - * @param StepEvent $e - * @return void - * @throws \Exception - */ - public function beforeStep(StepEvent $e) - { - $step = $e->getStep(); - $manualSkip = $this->getDriver()->_getConfig()['skipReadiness']; - if ($this->shouldSkipCheck($step, $manualSkip)) { - return; - } - - $this->resetMetricTracker($step); - - $metrics = $this->readinessMetrics; - - $this->waitForReadiness($metrics); - - /** @var AbstractMetricCheck $metric */ - foreach ($metrics as $metric) { - $metric->finalizeForStep($step); - } - } - - /** - * Check if page has changed, if so reset metric tracking - * - * @param Step $step - * @return void - */ - private function resetMetricTracker($step) - { - if ($this->pageChanged($step)) { - $this->logDebug( - 'Page URI changed; resetting readiness metric failure tracking', - [ - 'step' => $step->__toString(), - 'newUri' => $this->getUri() - ] - ); - /** @var AbstractMetricCheck $metric */ - foreach ($this->readinessMetrics as $metric) { - $metric->resetTracker(); - } - } - } - - /** - * Wait for page readiness. - * @param array $metrics - * @return void - * @throws \Codeception\Exception\ModuleRequireException - * @throws \Facebook\WebDriver\Exception\NoSuchElementException - */ - private function waitForReadiness($metrics) - { - // todo: Implement step parameter to override global timeout configuration - if (isset($this->config['timeout'])) { - $timeout = intval($this->config['timeout']); - } else { - $timeout = $this->getDriver()->_getConfig()['pageload_timeout']; - } - - try { - $this->getDriver()->webDriver->wait($timeout)->until( - function () use ($metrics) { - $passing = true; - - /** @var AbstractMetricCheck $metric */ - foreach ($metrics as $metric) { - try { - if (!$metric->runCheck()) { - $passing = false; - } - } catch (UnexpectedAlertOpenException $exception) { - } - } - return $passing; - } - ); - } catch (TimeoutException $exception) { - } - } - - /** - * Gets the name of the active test - * - * @return string - */ - public function getTestName() - { - return $this->testName; - } - - /** - * Should the given step bypass the readiness checks - * todo: Implement step parameter to bypass specific metrics (or all) instead of basing on action type - * - * @param Step $step - * @param boolean $manualSkip - * @return boolean - */ - private function shouldSkipCheck($step, $manualSkip) - { - if ($step instanceof Step\Comment || in_array($step->getAction(), $this->ignoredActions) || $manualSkip) { - return true; - } - return false; - } - - /** - * If verbose, log the given message to logger->debug including test context information - * - * @param string $message - * @param array $context - * @return void - * @SuppressWarnings(PHPMD) - */ - private function logDebug($message, $context = []) - { - if ($this->verbose) { - $logContext = [ - 'test' => $this->testName, - 'uri' => $this->getUri() - ]; - foreach ($this->readinessMetrics as $metric) { - $logContext[$metric->getName()] = $metric->getStoredValue(); - $logContext[$metric->getName() . '.failCount'] = $metric->getFailureCount(); - } - $context = array_merge($logContext, $context); - //TODO REMOVE THIS LINE, UNCOMMENT LOGGER - //$this->logger->info($message, $context); - } - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/AbstractMetricCheck.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/AbstractMetricCheck.php deleted file mode 100644 index 8b611283d..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/AbstractMetricCheck.php +++ /dev/null @@ -1,364 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -use Codeception\Exception\ModuleRequireException; -use Codeception\Module\WebDriver; -use Codeception\Step; -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; -use Magento\FunctionalTestingFramework\Extension\PageReadinessExtension; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Monolog\Logger; - -/** - * Class AbstractMetricCheck - */ -abstract class AbstractMetricCheck -{ - /** - * Extension being used to verify this metric passes before test metrics - * - * @var PageReadinessExtension - */ - protected $extension; - - /** - * Current state of the value the metric tracks - * - * @var mixed; - */ - protected $currentValue; - - /** - * Most recent saved state of the value the metric tracks - * Updated when the metric passes or is finalized - * - * @var mixed; - */ - protected $storedValue; - - /** - * Current count of sequential identical failures - * - * @var integer; - */ - protected $failCount; - - /** - * Number of sequential identical failures before force-resetting the metric - * - * @var integer - */ - protected $resetFailureThreshold; - - /** - * @var Logger - */ - protected $logger; - - /** - * @var boolean - */ - protected $verbose; - - /** - * Constructor, called from the beforeTest event - * - * @param PageReadinessExtension $extension - * @param integer $resetFailureThreshold - * @throws \Exception - */ - public function __construct($extension, $resetFailureThreshold) - { - $this->extension = $extension; - $this->logger = LoggingUtil::getInstance()->getLogger(get_class($this)); - $this->verbose = MftfApplicationConfig::getConfig()->verboseEnabled(); - - // If the clearFailureOnPage() method is overridden, use the configured failure threshold - // If not, the default clearFailureOnPage() method does nothing so don't worry about resetting failures - $reflector = new \ReflectionMethod($this, 'clearFailureOnPage'); - if ($reflector->getDeclaringClass()->getName() === get_class($this)) { - $this->resetFailureThreshold = $resetFailureThreshold; - } else { - $this->resetFailureThreshold = -1; - } - - $this->resetTracker(); - } - - /** - * Does the given value pass the readiness metric - * - * @param mixed $value - * @return boolean - */ - abstract protected function doesMetricPass($value); - - /** - * Retrieve the active value for the metric to check from the page - * - * @return mixed - * @throws UnexpectedAlertOpenException - */ - abstract protected function fetchValueFromPage(); - - /** - * Override this method to reset the actual state of the page to make the metric pass - * This method is called when too many identical failures were encountered in a row - * - * @return void - */ - protected function clearFailureOnPage() - { - return; - } - - /** - * Get the base class name of the metric implementation - * - * @return string - */ - public function getName() - { - $clazz = get_class($this); - $namespaceBreak = strrpos($clazz, '\\'); - if ($namespaceBreak !== false) { - $clazz = substr($clazz, $namespaceBreak + 1); - } - return $clazz; - } - - /** - * Fetches a new value for the metric and checks if it passes, clearing the failure tracking if so - * - * Even on a success, the readiness check will continue to be run until all metrics pass at the same time in order - * to catch cases where a slow request of one metric can trigger calls for other metrics that were previously - * thought ready - * - * @return boolean - * @throws UnexpectedAlertOpenException - */ - public function runCheck() - { - if ($this->doesMetricPass($this->getCurrentValue(true))) { - $this->setTracker($this->getCurrentValue(), 0); - return true; - } - - return false; - } - - /** - * Update the state of the metric including tracked failure state and checking if a failing value is stuck and - * needs to be reset so future checks can be accurate - * - * Called when the readiness check is finished (either all metrics pass or the check has timed out) - * - * @param Step $step - * @return void - */ - public function finalizeForStep($step) - { - try { - $currentValue = $this->getCurrentValue(); - } catch (UnexpectedAlertOpenException $exception) { - $this->debugLog( - 'An alert is open, bypassing javascript-based metric check', - ['step' => $step->__toString()] - ); - return; - } - - if ($this->doesMetricPass($currentValue)) { - $this->setTracker($currentValue, 0); - } else { - // If failure happened on the same value as before, increment the fail count, otherwise set at 1 - if (!isset($this->storedValue) || $currentValue !== $this->getStoredValue()) { - $failCount = 1; - } else { - $failCount = $this->getFailureCount() + 1; - } - $this->setTracker($currentValue, $failCount); - - $this->errorLog('Failed readiness check', ['step' => $step->__toString()]); - - if ($this->resetFailureThreshold >= 0 && $failCount >= $this->resetFailureThreshold) { - $this->debugLog( - 'Too many failures, assuming metric is stuck and resetting state', - ['step' => $step->__toString()] - ); - $this->resetMetric(); - } - } - } - - /** - * Helper function to retrieve the driver being used to run the test - * - * @return WebDriver - * @throws ModuleRequireException - */ - protected function getDriver() - { - return $this->extension->getDriver(); - } - - /** - * Helper function to execute javascript code, see WebDriver::executeJs for more information - * - * @param string $script - * @param array $arguments - * @return mixed - * @throws ModuleRequireException - */ - protected function executeJs($script, $arguments = []) - { - return $this->extension->getDriver()->executeJS($script, $arguments); - } - - /** - * Gets the current state of the given variable - * Fetches an updated value if not known or $refresh is true - * - * @param boolean $refresh - * @return mixed - * @throws UnexpectedAlertOpenException - */ - private function getCurrentValue($refresh = false) - { - if ($refresh) { - unset($this->currentValue); - } - if (!isset($this->currentValue)) { - $this->currentValue = $this->fetchValueFromPage(); - } - return $this->currentValue; - } - - /** - * Returns the value of the given variable for the previous check - * - * @return mixed - */ - public function getStoredValue() - { - return $this->storedValue ?? null; - } - - /** - * The current count of sequential identical failures - * Used to detect potentially stuck metrics - * - * @return integer - */ - public function getFailureCount() - { - return $this->failCount; - } - - /** - * Update the state of the page to pass the metric and clear the saved failure state - * Called when a failure is found to be stuck - * - * @return void - */ - private function resetMetric() - { - $this->clearFailureOnPage(); - $this->resetTracker(); - } - - /** - * Tracks the most recent value and the number of identical failures in a row - * - * @param mixed $value - * @param integer $failCount - * @return void - */ - public function setTracker($value, $failCount) - { - unset($this->currentValue); - $this->storedValue = $value; - $this->failCount = $failCount; - } - - /** - * Resets the tracked metric values on a new page or stuck failure - * - * @return void - */ - public function resetTracker() - { - unset($this->currentValue); - unset($this->storedValue); - $this->failCount = 0; - } - - /** - * Log the given message to logger->error including context information - * - * @param string $message - * @param array $context - * @return void - * @SuppressWarnings(PHPMD) - */ - protected function errorLog($message, $context = []) - { - $context = array_merge($this->getLogContext(), $context); - //TODO REMOVE THIS LINE, UNCOMMENT LOGGER - //$this->logger->error($message, $context); - } - - /** - * Log the given message to logger->info including context information - * - * @param string $message - * @param array $context - * @return void - * @SuppressWarnings(PHPMD) - */ - protected function infoLog($message, $context = []) - { - $context = array_merge($this->getLogContext(), $context); - //TODO REMOVE THIS LINE, UNCOMMENT LOGGER - //$this->logger->info($message, $context); - } - - /** - * If verbose, log the given message to logger->debug including context information - * - * @param string $message - * @param array $context - * @return void - * @SuppressWarnings(PHPMD) - */ - protected function debugLog($message, $context = []) - { - if ($this->verbose) { - $context = array_merge($this->getLogContext(), $context); - //TODO REMOVE THIS LINE, UNCOMMENT LOGGER - //$this->logger->debug($message, $context); - } - } - - /** - * Base context information to include in all log messages: test name, current URI, metric state - * Reports most recent stored value, not current value, so call setTracker() first to update - * - * @return array - */ - private function getLogContext() - { - return [ - 'test' => $this->extension->getTestName(), - 'uri' => $this->extension->getUri(), - $this->getName() => $this->getStoredValue(), - $this->getName() . '.failCount' => $this->getFailureCount() - ]; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/DocumentReadyState.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/DocumentReadyState.php deleted file mode 100644 index 26cf91aa7..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/DocumentReadyState.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -/** - * Class DocumentReadyState - */ - -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; - -/** - * Class DocumentReadyState - * - * Looks for document.readyState == 'complete' before passing the readiness check - */ -class DocumentReadyState extends AbstractMetricCheck -{ - /** - * Metric passes when document.readyState == 'complete' - * - * @param string $value - * @return boolean - */ - protected function doesMetricPass($value) - { - return $value === 'complete'; - } - - /** - * Retrieve document.readyState - * - * @return string - * @throws UnexpectedAlertOpenException - */ - protected function fetchValueFromPage() - { - return $this->executeJS('return document.readyState;'); - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/JQueryAjaxRequests.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/JQueryAjaxRequests.php deleted file mode 100644 index c005923d3..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/JQueryAjaxRequests.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; - -/** - * Class JQueryAjaxRequests - * - * Looks for all active jQuery ajax requests to finish before passing the readiness check - */ -class JQueryAjaxRequests extends AbstractMetricCheck -{ - /** - * Metric passes once there are no remaining active requests - * - * @param integer $value - * @return boolean - */ - protected function doesMetricPass($value) - { - return $value == 0; - } - - /** - * Grabs the number of active jQuery ajax requests if available - * - * @return integer - * @throws UnexpectedAlertOpenException - */ - protected function fetchValueFromPage() - { - return intval( - $this->executeJS( - 'if (!!window.jQuery) { - return window.jQuery.active; - } - return 0;' - ) - ); - } - - /** - * Active request count can get stuck above zero if an exception is thrown during a callback, causing the - * ajax handler method to fail before decrementing the request count - * - * @return void - * @throws UnexpectedAlertOpenException - */ - protected function clearFailureOnPage() - { - $this->executeJS('if (!!window.jQuery) { window.jQuery.active = 0; };'); - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/MagentoLoadingMasks.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/MagentoLoadingMasks.php deleted file mode 100644 index 4f15524ba..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/MagentoLoadingMasks.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -use Facebook\WebDriver\Exception\NoSuchElementException; -use Facebook\WebDriver\Exception\StaleElementReferenceException; -use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; -use WebDriverBy; - -/** - * Class MagentoLoadingMasks - * - * Looks for all loading masks to disappear before passing the readiness check - */ -class MagentoLoadingMasks extends AbstractMetricCheck -{ - /** - * Metric passes once all loading masks are absent or invisible - * - * @param string|null $value - * @return boolean - */ - protected function doesMetricPass($value) - { - return $value === null; - } - - /** - * Get the locator and ID for the first active loading mask or null if there are none visible - * - * @return string|null - */ - protected function fetchValueFromPage() - { - foreach (MagentoWebDriver::$loadingMasksLocators as $maskLocator) { - $driverLocator = WebDriverBy::xpath($maskLocator); - $maskElements = $this->getDriver()->webDriver->findElements($driverLocator); - foreach ($maskElements as $element) { - try { - if ($element->isDisplayed()) { - return "$maskLocator : " . $element ->getID(); - } - } catch (NoSuchElementException $e) { - } catch (StaleElementReferenceException $e) { - } - } - } - return null; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/PrototypeAjaxRequests.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/PrototypeAjaxRequests.php deleted file mode 100644 index 2fc8f70cb..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/PrototypeAjaxRequests.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; - -/** - * Class PrototypeAjaxRequests - * - * Looks for all active prototype ajax requests to finish before passing the readiness check - */ -class PrototypeAjaxRequests extends AbstractMetricCheck -{ - /** - * Metric passes once there are no remaining active requests - * - * @param integer $value - * @return boolean - */ - protected function doesMetricPass($value) - { - return $value == 0; - } - - /** - * Grabs the number of active prototype ajax requests if available - * - * @return integer - * @throws UnexpectedAlertOpenException - */ - protected function fetchValueFromPage() - { - return intval( - $this->executeJS( - 'if (!!window.Prototype) { - return window.Ajax.activeRequestCount; - } - return 0;' - ) - ); - } - - /** - * Active request count can get stuck above zero if an exception is thrown during a callback, causing the - * ajax handler method to fail before decrementing the request count - * - * @return void - * @throws UnexpectedAlertOpenException - */ - protected function clearFailureOnPage() - { - $this->executeJS('if (!!window.Prototype) { window.Ajax.activeRequestCount = 0; };'); - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/RequireJsDefinitions.php b/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/RequireJsDefinitions.php deleted file mode 100644 index 6df470123..000000000 --- a/src/Magento/FunctionalTestingFramework/Extension/ReadinessMetrics/RequireJsDefinitions.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Extension\ReadinessMetrics; - -use Facebook\WebDriver\Exception\UnexpectedAlertOpenException; - -/** - * Class RequireJsDefinitions - * - * Looks for all active require.js module definitions to complete before passing the readiness check - */ -class RequireJsDefinitions extends AbstractMetricCheck -{ - /** - * Metric passes once there are no enabled modules waiting in the registry queue - * - * @param string|null $value - * @return boolean - */ - protected function doesMetricPass($value) - { - return $value === null; - } - - /** - * Retrieve the name of the first enabled module still waiting in the require.js registry queue - * - * @return string|null - * @throws UnexpectedAlertOpenException - */ - protected function fetchValueFromPage() - { - $script = - 'if (!window.requirejs) { - return null; - } - var contexts = window.requirejs.s.contexts; - for (var label in contexts) { - if (contexts.hasOwnProperty(label)) { - var registry = contexts[label].registry; - for (var module in registry) { - if (registry.hasOwnProperty(module) && registry[module].enabled) { - return module; - } - } - } - } - return null;'; - - $moduleInProgress = $this->executeJS($script); - if ($moduleInProgress === 'null') { - $moduleInProgress = null; - } - return $moduleInProgress; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Extension/TestContextExtension.php b/src/Magento/FunctionalTestingFramework/Extension/TestContextExtension.php index c50156f08..e4f433a2a 100644 --- a/src/Magento/FunctionalTestingFramework/Extension/TestContextExtension.php +++ b/src/Magento/FunctionalTestingFramework/Extension/TestContextExtension.php @@ -32,6 +32,12 @@ class TestContextExtension extends BaseExtension */ public static $events; + /** + * The name of the currently running test + * @var string + */ + public $currentTest; + /** * Initialize local vars * @@ -55,8 +61,20 @@ public function _initialize() * @throws \Exception * @return void */ - public function testStart() + public function testStart(\Codeception\Event\TestEvent $e) { + if (getenv('ENABLE_CODE_COVERAGE') === 'true') { + // Curl against test.php and pass in the test name. Used when gathering code coverage. + $this->currentTest = $e->getTest()->getMetadata()->getName(); + $cURLConnection = curl_init(); + curl_setopt_array($cURLConnection, [ + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_URL => getenv('MAGENTO_BASE_URL') . "/test.php?test=" . $this->currentTest, + ]); + curl_exec($cURLConnection); + curl_close($cURLConnection); + } + PersistedObjectHandler::getInstance()->clearHookObjects(); PersistedObjectHandler::getInstance()->clearTestObjects(); } @@ -181,9 +199,13 @@ public function beforeStep(\Codeception\Event\StepEvent $e) */ public function afterStep(\Codeception\Event\StepEvent $e) { - $browserLog = $this->getDriver()->webDriver->manage()->getLog("browser"); + $browserLog = []; + try { + $browserLog = $this->getDriver()->webDriver->manage()->getLog("browser"); + } catch (\Exception $exception) { + } if (getenv('ENABLE_BROWSER_LOG') === 'true') { - foreach (explode(',', getenv('BROWSER_LOG_BLACKLIST')) as $source) { + foreach (explode(',', getenv('BROWSER_LOG_BLOCKLIST')) as $source) { $browserLog = BrowserLogUtil::filterLogsOfType($browserLog, $source); } if (!empty($browserLog)) { diff --git a/src/Magento/FunctionalTestingFramework/Helper/Acceptance.php b/src/Magento/FunctionalTestingFramework/Helper/Acceptance.php deleted file mode 100644 index fafe167af..000000000 --- a/src/Magento/FunctionalTestingFramework/Helper/Acceptance.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Helper; - -use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; -use Codeception\Module; - -/** - * Class Acceptance - * - * Define global actions - * All public methods declared in helper class will be available in $I - */ -class Acceptance extends Module -{ - /** - * Reconfig WebDriver. - * - * @param string $config - * @param string $value - * @return void - */ - public function changeConfiguration($config, $value) - { - $this->getModule(MagentoWebDriver::class)->_reconfigure([$config => $value]); - } - - /** - * Get WebDriver configuration. - * - * @param string $config - * @return string - */ - public function getConfiguration($config) - { - return $this->getModule(MagentoWebDriver::class)->_getConfig($config); - } -} diff --git a/src/Magento/FunctionalTestingFramework/Helper/AdminUrlList.php b/src/Magento/FunctionalTestingFramework/Helper/AdminUrlList.php deleted file mode 100644 index ca96033dc..000000000 --- a/src/Magento/FunctionalTestingFramework/Helper/AdminUrlList.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Helper; - -/** - * Class AdminUrlList - * @SuppressWarnings(PHPMD) - */ -// @codingStandardsIgnoreFile -class AdminUrlList -{ - public static $adminLoginPage = '/admin/admin/'; - public static $adminLogoutPage = '/admin/admin/auth/logout/'; - public static $adminForgotYourPasswordPage = '/admin/admin/auth/forgotpassword/'; - - public static $adminDashboardPage = '/admin/admin/dashboard/'; - - public static $adminOrdersGrid = '/admin/sales/order/'; - public static $adminOrderByIdPage = '/admin/sales/order/view/order_id/'; - public static $adminAddOrderPage = '/admin/sales/order_create/index/'; - public static $adminAddOrderForCustomerIdPage = '/admin/sales/order_create/index/customer_id/'; - public static $adminInvoicesGrid = '/admin/sales/invoice/'; - public static $adminAddInvoiceForOrderIdPage = '/admin/sales/order_invoice/new/order_id/'; - public static $adminShipmentsGrid = '/admin/sales/shipment/'; - public static $adminShipmentForIdPage = '/admin/sales/shipment/view/shipment_id/'; - public static $adminCreditMemosGrid = '/admin/sales/creditmemo/'; - public static $adminCreditMemoForIdPage = '/admin/sales/creditmemo/view/creditmemo_id/'; - public static $adminBillingAgreementsGrid = '/admin/paypal/billing_agreement/'; - // TODO: Determine the correct address for Billing Agreements for Billing Agreement ID page URL. - public static $adminTransactionsGrid = '/admin/sales/transactions/'; - // TODO: Determine the correct address for Transactions for Transaction ID page URL. - - public static $adminCatalogGrid = '/admin/catalog/product/'; - public static $adminProductForIdPage = '/admin/catalog/product/edit/id/'; - public static $adminAddSimpleProductPage = '/admin/catalog/product/new/set/4/type/simple/'; - public static $adminAddConfigurableProductPage = '/admin/catalog/product/new/set/4/type/configurable/'; - public static $adminAddGroupedProductPage = '/admin/catalog/product/new/set/4/type/grouped/'; - public static $adminAddVirtualProductPage = '/admin/catalog/product/new/set/4/type/virtual/'; - public static $adminAddBundleProductPage = '/admin/catalog/product/new/set/4/type/bundle/'; - public static $adminAddDownloadableProductPage = '/admin/catalog/product/new/set/4/type/downloadable/'; - - public static $adminCategoriesPage = '/admin/catalog/category/'; - public static $adminCategoryForIdPage = '/admin/catalog/category/edit/id/'; - public static $adminAddRootCategoryPage = '/admin/catalog/category/add/store/0/parent/1'; - public static $adminAddSubCategoryPage = '/admin/catalog/category/add/store/0/parent/2'; - - public static $adminAllCustomersGrid = '/admin/customer/index/'; - public static $adminCustomersNowOnlineGrid = '/admin/customer/online/'; - public static $adminCustomerForCustomerIdPage = '/admin/customer/index/edit/id/'; - public static $adminAddCustomerPage = '/admin/customer/index/new/'; - - public static $adminCatalogPriceRuleGrid = '/admin/catalog_rule/promo_catalog/'; - public static $adminCatalogPriceRuleForIdPage = '/admin/catalog_rule/promo_catalog/edit/id/'; - public static $adminAddCatalogPriceRulePage = '/admin/catalog_rule/promo_catalog/new/'; - public static $adminCartPriceRulesGrid = '/admin/sales_rule/promo_quote/'; - public static $adminCartPriceRuleForIdPage = '/admin/sales_rule/promo_quote/edit/id/'; - public static $adminAddCartPriceRulePage = '/admin/sales_rule/promo_quote/new/'; - public static $adminEmailTemplatesGrid = '/admin/admin/email_template/'; - public static $adminEmailTemplateForIdPage = '/admin/admin/email_template/edit/id/'; - public static $adminAddEmailTemplatePage = '/admin/admin/email_template/new/'; - public static $adminNewsletterTemplateGrid = '/admin/newsletter/template/'; - public static $adminNewsletterTemplateForIdPage = '/admin/newsletter/template/edit/id/'; - public static $adminAddNewsletterTemplatePage = '/admin/newsletter/template/new/'; - public static $adminNewsletterQueueGrid = '/admin/newsletter/queue/'; - // TODO: Determine if there is a Details page for the Newsletter Queue. - public static $adminNewsletterSubscribersGrid = '/admin/newsletter/subscriber/'; - public static $adminURLRewritesGrid = '/admin/admin/url_rewrite/index/'; - public static $adminURLRewriteForIdPage = '/admin/admin/url_rewrite/edit/id/'; - public static $adminAddURLRewritePage = '/admin/admin/url_rewrite/edit/id'; // If you don't list an ID it drops you on the Add page. - public static $adminSearchTermsGrid = '/admin/search/term/index/'; - public static $adminSearchTermForIdPage = '/admin/search/term/edit/id/'; - public static $adminAddSearchTermPage = '/admin/search/term/new/'; - public static $adminSearchSynonymsGrid = '/admin/search/synonyms/index/'; - public static $adminSearchSynonymGroupForIdPage = '/admin/search/synonyms/edit/group_id/'; - public static $adminAddSearchSynonymGroupPage = '/admin/search/synonyms/new/'; - public static $adminSiteMapGrid = '/admin/admin/sitemap/'; - public static $adminSiteMapForIdPage = '/admin/admin/sitemap/edit/sitemap_id/'; - public static $adminAddSiteMapPage = '/admin/admin/sitemap/new/'; - public static $adminReviewsGrid = '/admin/review/product/index/'; - public static $adminReviewByIdPage = '/admin/review/product/edit/id/'; - public static $adminAddReviewPage = '/admin/review/product/new/'; - - public static $adminPagesGrid = '/admin/cms/page/'; - public static $adminPageForIdPage = '/admin/cms/page/edit/page_id/'; - public static $adminAddPagePage = '/admin/cms/page/new/'; - public static $adminBlocksGrid = '/admin/cms/block/'; - public static $adminBlockForIdPage = '/admin/cms/block/edit/block_id/'; - public static $adminAddBlockPage = '/admin/cms/block/new/'; - public static $adminWidgetsGrid = '/admin/admin/widget_instance/'; - // TODO: Determine how the Edit Widget URLs are generated. - public static $adminAddWidgetPage = '/admin/admin/widget_instance/new/'; - public static $adminDesignConfigurationGrid = '/admin/theme/design_config/'; - // TODO: Determine how the Design Configuration URLs are generated. - public static $adminThemesGrid = '/admin/admin/system_design_theme/'; - public static $adminThemeByIdPage = '/admin/admin/system_design_theme/edit/id/'; - public static $adminStoreContentScheduleGrid = '/admin/admin/system_design/'; - public static $adminStoreContentScheduleForIdPage = '/admin/admin/system_design/edit/id/'; - public static $adminAddStoreDesignChangePage = '/admin/admin/system_design/new/'; - - public static $adminProductsInCartGrid = '/admin/reports/report_shopcart/product/'; - public static $adminSearchTermsReportGrid = '/admin/search/term/report/'; - public static $adminAbandonedCartsGrid = '/admin/reports/report_shopcart/abandoned/'; - public static $adminNewsletterProblemsReportGrid = '/admin/newsletter/problem/'; - public static $adminCustomerReviewsReportGrid = '/admin/reports/report_review/customer/'; - public static $adminProductReviewsReportGrid = '/admin/reports/report_review/product/'; - public static $adminProductReviewsForProductIdPage = '/admin/review/product/index/productId/'; - public static $adminOrdersReportGrid = '/admin/reports/report_sales/sales/'; - public static $adminTaxReportGrid = '/admin/reports/report_sales/tax/'; - public static $adminInvoiceReportGrid = '/admin/reports/report_sales/invoiced/'; - public static $adminShippingReportGrid = '/admin/reports/report_sales/shipping/'; - public static $adminRefundsReportGrid = '/admin/reports/report_sales/refunded/'; - public static $adminCouponsReportGrid = '/admin/reports/report_sales/coupons/'; - public static $adminPayPalSettlementReportsGrid = '/admin/paypal/paypal_reports/'; - public static $adminBraintreeSettlementReportGrid = '/admin/braintree/report/'; - public static $adminOrderTotalReportGrid = '/admin/reports/report_customer/totals/'; - public static $adminOrderCountReportGrid = '/admin/reports/report_customer/orders/'; - public static $adminNewAccountsReportGrid = '/admin/reports/report_customer/accounts/'; - public static $adminProductViewsReportGrid = '/admin/reports/report_product/viewed/'; - public static $adminBestsellersReportGrid = '/admin/reports/report_sales/bestsellers/'; - public static $adminLowStockReportGrid = '/admin/reports/report_product/lowstock/'; - public static $adminOrderedProductsReportGrid = '/admin/reports/report_product/sold/'; - public static $adminDownloadsReportGrid = '/admin/reports/report_product/downloads/'; - public static $adminRefreshStatisticsGrid = '/admin/reports/report_statistics/'; - - public static $adminAllStoresGrid = '/admin/admin/system_store/'; - public static $adminCreateStoreViewPage = '/admin/admin/system_store/newStore/'; - public static $adminCreateStorePage = '/admin/admin/system_store/newGroup/'; - public static $adminCreateWebsitePage = '/admin/admin/system_store/newWebsite/'; - public static $adminWebsiteByIdPage = '/admin/admin/system_store/editWebsite/website_id/'; - public static $adminStoreViewByIdPage = '/admin/admin/system_store/editStore/store_id/'; - public static $adminStoreByIdPage = '/admin/admin/system_store/editGroup/group_id/'; - public static $adminConfigurationGrid = '/admin/admin/system_config/'; - public static $adminTermsAndConditionsGrid = '/admin/checkout/agreement/'; - public static $adminTermsAndConditionByIdPage = '/admin/checkout/agreement/edit/id/'; - public static $adminAddNewTermsAndConditionPage = '/admin/checkout/agreement/new/'; - public static $adminOrderStatusGrid = '/admin/sales/order_status/'; - public static $adminAddOrderStatusPage = '/admin/sales/order_status/new/'; - // TODO: Determine how the Order Status URLs are generated. - public static $adminTaxRulesGrid = '/admin/tax/rule/'; - public static $adminTaxRuleByIdPage = '/admin/tax/rule/edit/rule/'; - public static $adminAddTaxRulePage = '/admin/tax/rule/new/'; - public static $adminTaxZonesAndRatesGrid = '/admin/tax/rate/'; - public static $adminTaxZoneAndRateByIdPage = '/admin/tax/rate/edit/rate/'; - public static $adminAddTaxZoneAndRatePage = '/admin/tax/rate/add/'; - public static $adminCurrencyRatesPage = '/admin/admin/system_currency/'; - public static $adminCurrencySymbolsPage = '/admin/admin/system_currencysymbol/'; - public static $adminProductAttributesGrid = '/admin/catalog/product_attribute/'; - public static $adminProductAttributeForIdPage = '/admin/catalog/product_attribute/edit/attribute_id/'; - public static $adminAddProductAttributePage = '/admin/catalog/product_attribute/new/'; - public static $adminAttributeSetsGrid = '/admin/catalog/product_set/'; - public static $adminAttributeSetByIdPage = '/admin/catalog/product_set/edit/id/'; - public static $adminAddAttributeSetPage = '/admin/catalog/product_set/add/'; - public static $adminRatingsGrid = '/admin/review/rating/'; - public static $adminRatingForIdPage = '/admin/review/rating/edit/id/'; - public static $adminAddRatingPage = '/admin/review/rating/new/'; - public static $adminCustomerGroupsGrid = '/admin/customer/group/'; - public static $adminCustomerGroupByIdPage = '/admin/customer/group/edit/id/'; - public static $adminAddCustomerGroupPage = '/admin/customer/group/new/'; - - public static $adminImportPage = '/admin/admin/import/'; - public static $adminExportPage = '/admin/admin/export/'; - public static $adminImportAndExportTaxRatesPage = '/admin/tax/rate/importExport/'; - public static $adminImportHistoryGrid = '/admin/admin/history/'; - public static $adminIntegrationsGrid = '/admin/admin/integration/'; - public static $adminIntegrationByIdPage = '/admin/admin/integration/edit/id/'; - public static $adminAddIntegrationPage = '/admin/admin/integration/new/'; - public static $adminCacheManagementGrid = '/admin/admin/cache/'; - public static $adminBackupsGrid = '/admin/backup/index/'; - public static $adminIndexManagementGrid = '/admin/indexer/indexer/list/'; - public static $adminWebSetupWizardPage = '/setup/'; - public static $adminAllUsersGrid = '/admin/admin/user/'; - public static $adminUserByIdPage = '/admin/admin/user/edit/user_id/'; - public static $adminAddNewUserPage = '/admin/admin/user/new/'; - public static $adminLockedUsersGrid = '/admin/admin/locks/'; - public static $adminUserRolesGrid = '/admin/admin/user_role/'; - public static $adminUserRoleByIdPage = '/admin/admin/user_role/editrole/rid/'; - public static $adminAddUserRolePage = '/admin/admin/user_role/editrole/'; - public static $adminNotificationsGrid = '/admin/admin/notification/'; - public static $adminCustomVariablesGrid = '/admin/admin/system_variable/'; - public static $adminCustomVariableByIdPage = '/admin/admin/system_variable/edit/variable_id/'; - public static $adminAddCustomVariablePage = '/admin/admin/system_variable/new/'; - public static $adminEncryptionKeyPage = '/admin/admin/crypt_key/'; - - public static $adminFindPartnersAndExtensions = '/admin/marketplace/index/'; -} \ No newline at end of file diff --git a/src/Magento/FunctionalTestingFramework/Helper/Code/ClassReader.php b/src/Magento/FunctionalTestingFramework/Helper/Code/ClassReader.php new file mode 100644 index 000000000..146a3d6a9 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Helper/Code/ClassReader.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Helper\Code; + +/** + * Class ClassReader + * + * @internal + */ +class ClassReader +{ + /** + * Read class method signature + * + * @param string $className + * @param string $method + * @return array|null + * @throws \ReflectionException + */ + public function getParameters($className, $method) + { + $class = new \ReflectionClass($className); + $result = null; + $method = $class->getMethod($method); + if ($method) { + $result = []; + /** @var $parameter \ReflectionParameter */ + foreach ($method->getParameters() as $parameter) { + try { + $result[$parameter->getName()] = [ + 'type' => $parameter->getType() === null ? null : $parameter->getType()->getName(), + 'variableName' => $parameter->getName(), + 'isOptional' => $parameter->isOptional(), + 'optionalValue' => $parameter->isOptional() ? + $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null : + null + ]; + } catch (\ReflectionException $e) { + $message = $e->getMessage(); + throw new \ReflectionException($message, 0, $e); + } + } + } + + return $result; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Helper/EntityRESTApiHelper.php b/src/Magento/FunctionalTestingFramework/Helper/EntityRESTApiHelper.php deleted file mode 100644 index 521ddc9ee..000000000 --- a/src/Magento/FunctionalTestingFramework/Helper/EntityRESTApiHelper.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Helper; - -use GuzzleHttp\Client; - -/** - * Class EntityRESTApiHelper - * @package Magento\FunctionalTestingFramework\Helper - */ -class EntityRESTApiHelper -{ - /** - * Integration admin token uri. - */ - const INTEGRATION_ADMIN_TOKEN_URI = '/rest/V1/integration/admin/token'; - - /** - * Application json header. - */ - const APPLICATION_JSON_HEADER = ['Content-Type' => 'application/json']; - - /** - * Rest API client. - * - * @var Client - */ - private $guzzle_client; - - /** - * EntityRESTApiHelper constructor. - * @param string $host - * @param string $port - */ - public function __construct($host, $port) - { - $this->guzzle_client = new Client([ - 'base_uri' => "http://{$host}:{$port}", - 'timeout' => 5.0, - ]); - } - - /** - * Submit Auth API Request. - * - * @param string $apiMethod - * @param string $requestURI - * @param string $jsonBody - * @param array $headers - * @return \Psr\Http\Message\ResponseInterface - */ - public function submitAuthAPIRequest($apiMethod, $requestURI, $jsonBody, $headers) - { - $allHeaders = $headers; - $authTokenVal = $this->getAuthToken(); - $authToken = ['Authorization' => 'Bearer ' . $authTokenVal]; - $allHeaders = array_merge($allHeaders, $authToken); - - return $this->submitAPIRequest($apiMethod, $requestURI, $jsonBody, $allHeaders); - } - - /** - * Function that sends a REST call to the integration endpoint for an authorization token. - * - * @return string - */ - private function getAuthToken() - { - $jsonArray = json_encode(['username' => 'admin', 'password' => 'admin123']); - - $response = $this->submitAPIRequest( - 'POST', - self::INTEGRATION_ADMIN_TOKEN_URI, - $jsonArray, - self::APPLICATION_JSON_HEADER - ); - - if ($response->getStatusCode() != 200) { - throwException($response->getReasonPhrase() .' Could not get admin token from service, please check logs.'); - } - - $authToken = str_replace('"', "", $response->getBody()->getContents()); - return $authToken; - } - - /** - * Function that submits an api request from the guzzle client using the following parameters: - * - * @param string $apiMethod - * @param string $requestURI - * @param string $jsonBody - * @param array $headers - * @return \Psr\Http\Message\ResponseInterface - */ - private function submitAPIRequest($apiMethod, $requestURI, $jsonBody, $headers) - { - $response = $this->guzzle_client->request( - $apiMethod, - $requestURI, - [ - 'headers' => $headers, - 'body' => $jsonBody - ] - ); - - return $response; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Helper/Helper.php b/src/Magento/FunctionalTestingFramework/Helper/Helper.php new file mode 100644 index 000000000..e47aca32b --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Helper/Helper.php @@ -0,0 +1,15 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Helper; + +/** + * Class Helper to abstract Codeception module class and make possible to add own functionality if needed. + */ +class Helper extends \Codeception\Module +{ + // +} diff --git a/src/Magento/FunctionalTestingFramework/Helper/HelperContainer.php b/src/Magento/FunctionalTestingFramework/Helper/HelperContainer.php new file mode 100644 index 000000000..f3b5852b8 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Helper/HelperContainer.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +declare(strict_types = 1); + +namespace Magento\FunctionalTestingFramework\Helper; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; + +/** + * Class HelperContainer + */ +class HelperContainer extends \Codeception\Module +{ + /** + * @var Helper[] + */ + private $helpers = []; + + /** + * Create custom helper class. + * + * @param string $helperClass + * @return Helper + * @throws \Exception + */ + public function create(string $helperClass): Helper + { + if (get_parent_class($helperClass) !== Helper::class) { + throw new \Exception("Helper class must extend " . Helper::class); + } + if (!isset($this->helpers[$helperClass])) { + $this->helpers[$helperClass] = $this->moduleContainer->create($helperClass); + } + + return $this->helpers[$helperClass]; + } + + /** + * Returns helper object by it's class name. + * + * @param string $className + * @return Helper + * @throws TestFrameworkException + */ + public function get(string $className): Helper + { + if ($this->has($className)) { + return $this->helpers[$className]; + } + throw new TestFrameworkException('Custom helper ' . $className . 'not found.'); + } + + /** + * Verifies that helper object exist. + * + * @param string $className + * @return boolean + */ + public function has(string $className): bool + { + return array_key_exists($className, $this->helpers); + } +} diff --git a/src/Magento/FunctionalTestingFramework/Helper/MagentoFakerData.php b/src/Magento/FunctionalTestingFramework/Helper/MagentoFakerData.php deleted file mode 100644 index 9c28a3531..000000000 --- a/src/Magento/FunctionalTestingFramework/Helper/MagentoFakerData.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Helper; - -/** - * Class MagentoFakerData - */ -class MagentoFakerData extends \Codeception\Module -{ - /** - * Get Customer data. - * - * @param array $additional - * @return array - */ - public function getCustomerData(array $additional = []) - { - $faker = \Faker\Factory::create(); - $customerData = [ - 'prefix' => $faker->title, - 'firstname' => $faker->firstName, - 'middlename' => $faker->firstName, - 'lastname' => $faker->lastName, - 'suffix' => \Faker\Provider\en_US\Person::suffix(), - 'email' => $faker->email, - 'dateOfBirth' => $faker->date('m/d/Y', 'now'), - 'gender' => rand(0, 1), - 'group_id' => 1, - 'store_id' => 1, - 'website_id' => 1, - 'taxVatNumber' => \Faker\Provider\at_AT\Payment::vat(), - 'company' => $faker->company, - 'phoneNumber' => $faker->phoneNumber, - 'address' => [ - 'address1' => $faker->streetAddress, - 'address2' => $faker->streetAddress, - 'city' => $faker->city, - 'country' => 'United States', - 'state' => \Faker\Provider\en_US\Address::state(), - 'zipCode' => $faker->postcode - ] - ]; - return array_merge($customerData, $additional); - } - - /** - * Get category data. - * - * @return array - */ - public function getCategoryData() - { - $faker = \Faker\Factory::create(); - - return [ - 'enableCategory' => $faker->boolean(), - 'includeInMenu' => $faker->boolean(), - 'categoryName' => $faker->md5, - 'categoryImage' => '', - 'description' => $faker->sentence(10, true), - 'addCMSBlock' => '', - - 'urlKey' => $faker->uuid, - 'metaTitle' => $faker->word, - 'metaKeywords' => $faker->sentence(5, true), - 'metaDescription' => $faker->sentence(10, true), - ]; - } - - /** - * Get simple product data. - * - * @return array - */ - public function getProductData() - { - $faker = \Faker\Factory::create(); - return [ - 'enableProduct' => $faker->boolean(), - 'attributeSet' => '', - 'productName' => $faker->text(20), - 'sku' => \Faker\Provider\DateTime::unixTime('now'), - 'price' => $faker->randomFloat(2, 0, 999), - 'quantity' => $faker->numberBetween(1, 999), - - 'urlKey' => $faker->uuid, - 'metaTitle' => $faker->word, - 'metaKeywords' => $faker->sentence(5, true), - 'metaDescription' => $faker->sentence(10, true) - ]; - } - - /** - * Get Content Page Data. - * - * @return array - */ - public function getContentPage() - { - $faker = \Faker\Factory::create(); - - $pageContent = [ - 'pageTitle' => $faker->sentence(3, true), - 'contentHeading' => $faker->sentence(3, true), - 'contentBody' => $faker->sentence(10, true), - 'urlKey' => $faker->uuid, - 'metaTitle' => $faker->word, - 'metaKeywords' => $faker->sentence(5, true), - 'metaDescription' => $faker->sentence(10, true), - 'from' => $faker->date($format = 'm/d/Y', 'now'), - 'to' => $faker->date($format = 'm/d/Y') - ]; - $pageContent['layoutUpdateXml'] = "<note><to>Tove</to><from>Jani</from><heading>Reminder</heading>"; - $pageContent['layoutUpdateXml'] .= "<body>Don't forget me this weekend!</body></note>"; - - return $pageContent; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Helper/views/TestInjectMethod.mustache b/src/Magento/FunctionalTestingFramework/Helper/views/TestInjectMethod.mustache new file mode 100644 index 000000000..36f2f8bf6 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Helper/views/TestInjectMethod.mustache @@ -0,0 +1,15 @@ + /** + * @var \Magento\FunctionalTestingFramework\Helper\HelperContainer + */ + private $helperContainer; + + /** + * Special method which automatically creates the respective objects. + */ + public function _inject(\Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer) + { + $this->helperContainer = $helperContainer; + {{#arguments}} + $this->helperContainer->create("{{type}}"); + {{/arguments}} + } diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 26c66acd1..984881e4e 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -6,6 +6,7 @@ namespace Magento\FunctionalTestingFramework\Module; +use Codeception\Lib\Actor\Shared\Pause; use Codeception\Module\WebDriver; use Codeception\Test\Descriptor; use Codeception\TestInterface; @@ -14,18 +15,17 @@ use Codeception\Exception\ModuleConfigException; use Codeception\Exception\ModuleException; use Codeception\Util\Uri; +use Magento\FunctionalTestingFramework\DataTransport\WebApiExecutor; +use Magento\FunctionalTestingFramework\DataTransport\Auth\WebApiAuth; +use Magento\FunctionalTestingFramework\DataTransport\Auth\Tfa\OTP; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlInterface; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Persist\Curl\WebapiExecutor; use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlInterface; use Magento\FunctionalTestingFramework\Util\ConfigSanitizerUtil; use Yandex\Allure\Adapter\AllureException; -use Magento\FunctionalTestingFramework\Util\Protocol\CurlTransport; +use Magento\FunctionalTestingFramework\DataTransport\Protocol\CurlTransport; use Yandex\Allure\Adapter\Support\AttachmentSupport; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Facebook\WebDriver\Remote\RemoteWebDriver; -use Facebook\WebDriver\Exception\WebDriverCurlException; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; /** @@ -48,10 +48,12 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.ExcessivePublicCount) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class MagentoWebDriver extends WebDriver { use AttachmentSupport; + use Pause; const MAGENTO_CRON_INTERVAL = 60; const MAGENTO_CRON_COMMAND = 'cron:run'; @@ -256,7 +258,7 @@ public function dontSeeInCurrentUrl($needle) $actualUrl = $this->webDriver->getCurrentURL(); $comparison = "Expected: $needle\nActual: $actualUrl"; AllureHelper::addAttachmentToCurrentStep($comparison, 'Comparison'); - $this->assertNotContains($needle, $actualUrl); + $this->assertStringNotContainsString($needle, $actualUrl); } /** @@ -325,7 +327,7 @@ public function seeInCurrentUrl($needle) $actualUrl = $this->webDriver->getCurrentURL(); $comparison = "Expected: $needle\nActual: $actualUrl"; AllureHelper::addAttachmentToCurrentStep($comparison, 'Comparison'); - $this->assertContains($needle, $actualUrl); + $this->assertStringContainsString($needle, $actualUrl); } /** @@ -450,19 +452,26 @@ public function waitForLoadingMaskToDisappear($timeout = null) } /** - * @param float $money + * Format input to specified currency in locale specified + * @link https://php.net/manual/en/numberformatter.formatcurrency.php + * + * @param float $value * @param string $locale - * @return array + * @param string $currency + * @return string + * @throws TestFrameworkException */ - public function formatMoney(float $money, $locale = 'en_US.UTF-8') + public function formatCurrency(float $value, $locale, $currency) { - $this->mSetLocale(LC_MONETARY, $locale); - $money = money_format('%.2n', $money); - $this->mResetLocale(); - $prefix = substr($money, 0, 1); - $number = substr($money, 1); + $formatter = \NumberFormatter::create($locale, \NumberFormatter::CURRENCY); + if ($formatter && !empty($formatter)) { + $result = $formatter->formatCurrency($value, $currency); + if ($result) { + return $result; + } + } - return ['prefix' => $prefix, 'number' => $number]; + throw new TestFrameworkException('Invalid attributes used in formatCurrency.'); } /** @@ -542,12 +551,11 @@ public function magentoCLI($command, $timeout = null, $arguments = null) false ); - $restExecutor = new WebapiExecutor(); $executor = new CurlTransport(); $executor->write( $apiURL, [ - 'token' => $restExecutor->getAuthToken(), + 'token' => WebApiAuth::getAdminToken(), getenv('MAGENTO_CLI_COMMAND_PARAMETER') => $command, 'arguments' => $arguments, 'timeout' => $timeout, @@ -556,7 +564,6 @@ public function magentoCLI($command, $timeout = null, $arguments = null) [] ); $response = $executor->read(); - $restExecutor->close(); $executor->close(); return $response; @@ -644,7 +651,7 @@ private function getCronWait(array $cronGroups = [], int $cronInterval = self::M */ public function deleteEntityByUrl($url) { - $executor = new WebapiExecutor(null); + $executor = new WebApiExecutor(null); $executor->write($url, [], CurlInterface::DELETE, []); $response = $executor->read(); $executor->close(); @@ -708,7 +715,7 @@ public function assertElementContainsAttribute($selector, $attribute, $value) // When an "attribute" is blank or null it returns "true" so we assert that "true" is present. $this->assertEquals($attributes, 'true'); } else { - $this->assertContains($value, $attributes); + $this->assertStringContainsString($value, $attributes); } } @@ -738,23 +745,24 @@ public function _before(TestInterface $test) */ public function dragAndDrop($source, $target, $xOffset = null, $yOffset = null) { - if ($xOffset !== null || $yOffset !== null) { - $snodes = $this->matchFirstOrFail($this->baseElement, $source); - $tnodes = $this->matchFirstOrFail($this->baseElement, $target); + $snodes = $this->matchFirstOrFail($this->baseElement, $source); + $tnodes = $this->matchFirstOrFail($this->baseElement, $target); + $action = new WebDriverActions($this->webDriver); + if ($xOffset !== null || $yOffset !== null) { $targetX = intval($tnodes->getLocation()->getX() + $xOffset); $targetY = intval($tnodes->getLocation()->getY() + $yOffset); $travelX = intval($targetX - $snodes->getLocation()->getX()); $travelY = intval($targetY - $snodes->getLocation()->getY()); - - $action = new WebDriverActions($this->webDriver); - $action->moveToElement($snodes)->perform(); - $action->clickAndHold($snodes)->perform(); - $action->moveByOffset($travelX, $travelY)->perform(); + $action->moveToElement($snodes); + $action->clickAndHold($snodes); + $action->moveByOffset($travelX, $travelY); $action->release()->perform(); } else { - parent::dragAndDrop($source, $target); + $action->clickAndHold($snodes); + $action->moveToElement($tnodes); + $action->release($tnodes)->perform(); } } @@ -860,18 +868,6 @@ public function amOnPage($page) $this->waitForPageLoad(); } - /** - * Turn Readiness check on or off - * - * @param boolean $check - * @return void - * @throws \Exception - */ - public function skipReadinessCheck($check) - { - $this->config['skipReadiness'] = $check; - } - /** * Clean Javascript errors in internal array * @@ -947,6 +943,17 @@ public function makeScreenshot($name = null) AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot'); } + /** + * Return OTP based on a shared secret + * + * @return string + * @throws TestFrameworkException + */ + public function getOTP() + { + return OTP::getOTP(); + } + /** * Create an entity * TODO: move this function to MagentoActionProxies after MQE-1904 @@ -1092,4 +1099,25 @@ private function executeCronjobs($cronGroups, $timeout, $arguments): string return sprintf('%s (wait: %ss, execution: %ss)', $cronResult, $waitFor, round($timeEnd - $timeStart, 2)); } + + /** + * Switch to another frame on the page by name, ID, CSS or XPath. + * + * @param string|null $locator + * @return void + * @throws \Exception + */ + public function switchToIFrame($locator = null) + { + try { + parent::switchToIFrame($locator); + } catch (\Exception $e) { + $els = $this->_findElements("#$locator"); + if (!count($els)) { + $this->debug('Failed to find locator by ID: ' . $e->getMessage()); + throw new \Exception("IFrame with $locator was not found."); + } + $this->webDriver->switchTo()->frame($els[0]); + } + } } diff --git a/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php b/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php index 94147dc08..8bde3b96d 100644 --- a/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php +++ b/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php @@ -24,7 +24,7 @@ public static function getInstance(); * Function to return a single object by name * * @param string $objectName - * @return object + * @return mixed */ public function getObject($objectName); diff --git a/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php b/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php index 989209461..14b9b65e5 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php +++ b/src/Magento/FunctionalTestingFramework/Page/Config/Dom.php @@ -12,6 +12,7 @@ use Magento\FunctionalTestingFramework\Config\Dom\NodePathMatcher; use Magento\FunctionalTestingFramework\Util\ModulePathExtractor; use Magento\FunctionalTestingFramework\Util\Validation\DuplicateNodeValidationUtil; +use Magento\FunctionalTestingFramework\Util\Validation\SingleNodePerFileValidationUtil; /** * MFTF page.xml configuration XML DOM utility @@ -36,6 +37,12 @@ class Dom extends \Magento\FunctionalTestingFramework\Config\MftfDom */ private $validationUtil; + /** SingleNodePerFileValidationUtil + * + * @var SingleNodePerFileValidationUtil + */ + private $singleNodePerFileValidationUtil; + /** * Page Dom constructor. * @param string $xml @@ -57,6 +64,7 @@ public function __construct( ) { $this->modulePathExtractor = new ModulePathExtractor(); $this->validationUtil = new DuplicateNodeValidationUtil('name', $exceptionCollector); + $this->singleNodePerFileValidationUtil = new SingleNodePerFileValidationUtil($exceptionCollector); parent::__construct( $xml, $filename, @@ -79,31 +87,44 @@ public function initDom($xml, $filename = null) { $dom = parent::initDom($xml, $filename); - $pagesNode = $dom->getElementsByTagName('pages')->item(0); - $this->validationUtil->validateChildUniqueness( - $pagesNode, - $filename, - $pagesNode->getAttribute(self::PAGE_META_NAME_ATTRIBUTE) - ); - $pageNodes = $dom->getElementsByTagName('page'); - $currentModule = - $this->modulePathExtractor->getExtensionPath($filename) - . '_' - . $this->modulePathExtractor->extractModuleName($filename); - foreach ($pageNodes as $pageNode) { - $pageModule = $pageNode->getAttribute("module"); - $pageName = $pageNode->getAttribute("name"); - if ($pageModule !== $currentModule) { - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - print( - "Page Module does not match path Module. " . - "(Page, Module): ($pageName, $pageModule) - Path Module: $currentModule" . - PHP_EOL - ); + if ($dom->getElementsByTagName('pages')->length > 0) { + /** @var \DOMElement $pagesNode */ + $pagesNode = $dom->getElementsByTagName('pages')[0]; + $this->validationUtil->validateChildUniqueness( + $pagesNode, + $filename, + $pagesNode->getAttribute(self::PAGE_META_NAME_ATTRIBUTE) + ); + + // Validate single page node per file + $this->singleNodePerFileValidationUtil->validateSingleNodeForTag( + $dom, + 'page', + $filename + ); + + if ($dom->getElementsByTagName('page')->length > 0) { + /** @var \DOMElement $pageNode */ + $pageNode = $dom->getElementsByTagName('page')[0]; + $currentModule = + $this->modulePathExtractor->getExtensionPath($filename) + . '_' + . $this->modulePathExtractor->extractModuleName($filename); + $pageModule = $pageNode->getAttribute("module"); + $pageName = $pageNode->getAttribute("name"); + if ($pageModule !== $currentModule) { + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + print( + "Page Module does not match path Module. " . + "(Page, Module): ($pageName, $pageModule) - Path Module: $currentModule" . + PHP_EOL + ); + } } + $pageNode->setAttribute(self::PAGE_META_FILENAME_ATTRIBUTE, $filename); } - $pageNode->setAttribute(self::PAGE_META_FILENAME_ATTRIBUTE, $filename); } + return $dom; } } diff --git a/src/Magento/FunctionalTestingFramework/Page/Config/SectionDom.php b/src/Magento/FunctionalTestingFramework/Page/Config/SectionDom.php index b7f5d5db9..5875f0ac1 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Config/SectionDom.php +++ b/src/Magento/FunctionalTestingFramework/Page/Config/SectionDom.php @@ -12,6 +12,7 @@ use Magento\FunctionalTestingFramework\Config\Dom\NodePathMatcher; use Magento\FunctionalTestingFramework\Util\ModulePathExtractor; use Magento\FunctionalTestingFramework\Util\Validation\DuplicateNodeValidationUtil; +use Magento\FunctionalTestingFramework\Util\Validation\SingleNodePerFileValidationUtil; /** * MFTF section.xml configuration XML DOM utility @@ -28,6 +29,12 @@ class SectionDom extends \Magento\FunctionalTestingFramework\Config\MftfDom */ private $validationUtil; + /** SingleNodePerFileValidationUtil + * + * @var SingleNodePerFileValidationUtil + */ + private $singleNodePerFileValidationUtil; + /** * Entity Dom constructor. * @param string $xml @@ -48,6 +55,7 @@ public function __construct( $errorFormat = self::ERROR_FORMAT_DEFAULT ) { $this->validationUtil = new DuplicateNodeValidationUtil('name', $exceptionCollector); + $this->singleNodePerFileValidationUtil = new SingleNodePerFileValidationUtil($exceptionCollector); parent::__construct( $xml, $filename, @@ -69,15 +77,26 @@ public function __construct( public function initDom($xml, $filename = null) { $dom = parent::initDom($xml, $filename); - $sectionNodes = $dom->getElementsByTagName('section'); - foreach ($sectionNodes as $sectionNode) { - $sectionNode->setAttribute(self::SECTION_META_FILENAME_ATTRIBUTE, $filename); - $this->validationUtil->validateChildUniqueness( - $sectionNode, - $filename, - $sectionNode->getAttribute(self::SECTION_META_NAME_ATTRIBUTE) + + if ($dom->getElementsByTagName('sections')->length > 0) { + // Validate single section node per file + $this->singleNodePerFileValidationUtil->validateSingleNodeForTag( + $dom, + 'section', + $filename ); + if ($dom->getElementsByTagName('section')->length > 0) { + /** @var \DOMElement $sectionNode */ + $sectionNode = $dom->getElementsByTagName('section')[0]; + $sectionNode->setAttribute(self::SECTION_META_FILENAME_ATTRIBUTE, $filename); + $this->validationUtil->validateChildUniqueness( + $sectionNode, + $filename, + $sectionNode->getAttribute(self::SECTION_META_NAME_ATTRIBUTE) + ); + } } + return $dom; } } diff --git a/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php b/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php index c310b9bef..73695c182 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php @@ -10,6 +10,7 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Page\Objects\PageObject; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; use Magento\FunctionalTestingFramework\XmlParser\PageParser; use Magento\FunctionalTestingFramework\Exceptions\XmlException; @@ -22,7 +23,7 @@ class PageObjectHandler implements ObjectHandlerInterface const PARAMETERIZED = 'parameterized'; const AREA = 'area'; const FILENAME = 'filename'; - const NAME_BLACKLIST_ERROR_MSG = "Page names cannot contain non alphanumeric characters.\tPage='%s'"; + const NAME_BLOCKLIST_ERROR_MSG = "Page names cannot contain non alphanumeric characters.\tPage='%s'"; /** * The singleton instance of this class @@ -54,10 +55,14 @@ private function __construct() return; } + $pageNameValidator = new NameValidationUtil(); foreach ($parserOutput as $pageName => $pageData) { if (preg_match('/[^a-zA-Z0-9_]/', $pageName)) { - throw new XmlException(sprintf(self::NAME_BLACKLIST_ERROR_MSG, $pageName)); + throw new XmlException(sprintf(self::NAME_BLOCKLIST_ERROR_MSG, $pageName)); } + + $filename = $pageData[self::FILENAME] ?? null; + $pageNameValidator->validateAffixes($pageName, NameValidationUtil::PAGE, $filename); $area = $pageData[self::AREA] ?? null; $url = $pageData[self::URL] ?? null; @@ -67,7 +72,8 @@ private function __construct() $module = $pageData[self::MODULE] ?? null; $sectionNames = array_keys($pageData[self::SECTION] ?? []); - $parameterized = $pageData[self::PARAMETERIZED] ?? false; + $urlContainsMustaches = strpos($url, "{{") !== false && strpos($url, "}}") !== false; + $parameterized = $pageData[self::PARAMETERIZED] ?? $urlContainsMustaches ?? false; $filename = $pageData[self::FILENAME] ?? null; $deprecated = $pageData[self::OBJ_DEPRECATED] ?? null; @@ -81,6 +87,7 @@ private function __construct() $this->pageObjects[$pageName] = new PageObject($pageName, $url, $module, $sectionNames, $parameterized, $area, $filename, $deprecated); } + $pageNameValidator->summarize(NameValidationUtil::PAGE . " name"); } /** diff --git a/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php b/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php index 2736100fd..5d658bac0 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php @@ -10,8 +10,8 @@ use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; -use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; use Magento\FunctionalTestingFramework\XmlParser\SectionParser; use Magento\FunctionalTestingFramework\Exceptions\XmlException; @@ -58,6 +58,8 @@ private function __construct() return; } + $sectionNameValidator = new NameValidationUtil(); + $elementNameValidator = new NameValidationUtil(); foreach ($parserOutput as $sectionName => $sectionData) { $elements = []; @@ -65,11 +67,20 @@ private function __construct() throw new XmlException(sprintf(self::SECTION_NAME_ERROR_MSG, $sectionName)); } + $filename = $sectionData[self::FILENAME] ?? null; + $sectionNameValidator->validateAffixes($sectionName, NameValidationUtil::SECTION, $filename); + try { foreach ($sectionData[SectionObjectHandler::ELEMENT] as $elementName => $elementData) { if (preg_match('/[^a-zA-Z0-9_]/', $elementName)) { throw new XmlException(sprintf(self::ELEMENT_NAME_ERROR_MSG, $elementName, $sectionName)); } + + $elementNameValidator->validateCamelCase( + $elementName, + NameValidationUtil::SECTION_ELEMENT_NAME, + $filename + ); $elementType = $elementData[SectionObjectHandler::TYPE] ?? null; $elementSelector = $elementData[SectionObjectHandler::SELECTOR] ?? null; $elementLocatorFunc = $elementData[SectionObjectHandler::LOCATOR_FUNCTION] ?? null; @@ -96,7 +107,6 @@ private function __construct() throw new XmlException($exception->getMessage() . " in Section '{$sectionName}'"); } - $filename = $sectionData[self::FILENAME] ?? null; $sectionDeprecated = $sectionData[self::OBJ_DEPRECATED] ?? null; if ($sectionDeprecated !== null) { @@ -113,6 +123,8 @@ private function __construct() $sectionDeprecated ); } + $sectionNameValidator->summarize(NameValidationUtil::SECTION . " name"); + $elementNameValidator->summarize(NameValidationUtil::SECTION_ELEMENT_NAME); } /** diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd index 65ac8290d..7b857a235 100644 --- a/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd +++ b/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd @@ -7,19 +7,10 @@ --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:annotation> - <xs:documentation>The definition of a page object.</xs:documentation> - </xs:annotation> - - <xs:element name="pages"> - <xs:annotation> - <xs:documentation> - The root element for configuration data. - </xs:documentation> - </xs:annotation> - <xs:complexType> + <xs:redefine schemaLocation="mergedPageObject.xsd"> + <xs:complexType name="PageType"> <xs:sequence> - <xs:element ref="page" maxOccurs="unbounded" minOccurs="1"> + <xs:element ref="page" maxOccurs="1" minOccurs="1"> <xs:annotation> <xs:documentation> Contains sequence of ui sections in a page. @@ -28,89 +19,5 @@ </xs:element> </xs:sequence> </xs:complexType> - </xs:element> - - <xs:element name="page"> - <xs:complexType> - <xs:sequence> - <xs:element ref="section" maxOccurs="unbounded" minOccurs="0"> - <xs:annotation> - <xs:documentation> - Contains sequence of ui elements. - </xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - <xs:attribute type="notEmptyType" name="name" use="required"> - <xs:annotation> - <xs:documentation> - Unique page name identifier. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="deprecated"> - <xs:annotation> - <xs:documentation> - Message and flag which shows that entity is deprecated. - </xs:documentation> - </xs:annotation> - </xs:attribute> - - <xs:attribute type="notEmptyType" name="url" use="required"> - <xs:annotation> - <xs:documentation> - URL for the page. Do not include the hostname. For example: "/admin/customer/index/" - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="notEmptyType" name="module" use="required"> - <xs:annotation> - <xs:documentation> - The name of the module to which the page belongs. For example: "Magento_Catalog". - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:boolean" name="parameterized" use="optional"/> - <xs:attribute type="pageArea" name="area" use="required"/> - <xs:attributeGroup ref="removeAttribute"/> - <xs:attribute type="xs:string" name="filename"/> - </xs:complexType> - </xs:element> - - <xs:element name="section"> - <xs:complexType> - <xs:attribute type="notEmptyType" name="name" use="required"> - <xs:annotation> - <xs:documentation> - Unique section name identifier. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attributeGroup ref="removeAttribute"/> - </xs:complexType> - </xs:element> - - <xs:simpleType name="notEmptyType"> - <xs:restriction base="xs:string"> - <xs:minLength value="1" /> - </xs:restriction> - </xs:simpleType> - - <xs:attributeGroup name="removeAttribute"> - <xs:attribute type="xs:boolean" name="remove" use="optional" default="false"> - <xs:annotation> - <xs:documentation> - Set to true to remove this element during parsing. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> - - <xs:simpleType name="pageArea" final="restriction" > - <xs:restriction base="xs:string"> - <xs:enumeration value="admin" /> - <xs:enumeration value="storefront" /> - <xs:enumeration value="external" /> - </xs:restriction> - </xs:simpleType> + </xs:redefine> </xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd index 1b5b44ddd..2267ed09b 100644 --- a/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd +++ b/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd @@ -7,15 +7,10 @@ --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="sections"> - <xs:annotation> - <xs:documentation> - The root element for configuration data. - </xs:documentation> - </xs:annotation> - <xs:complexType> + <xs:redefine schemaLocation="mergedSectionObject.xsd"> + <xs:complexType name="SectionType"> <xs:sequence> - <xs:element ref="section" maxOccurs="unbounded" minOccurs="1"> + <xs:element ref="section" maxOccurs="1" minOccurs="1"> <xs:annotation> <xs:documentation> Contains sequence of ui elements in a section of a page. @@ -24,126 +19,5 @@ </xs:element> </xs:sequence> </xs:complexType> - </xs:element> - - <xs:element name="section"> - <xs:complexType> - <xs:sequence> - <xs:element ref="element" maxOccurs="unbounded" minOccurs="1"> - <xs:annotation> - <xs:documentation> - Contains information of an ui element. - </xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - <xs:attribute type="notEmptyType" name="name" use="required"> - <xs:annotation> - <xs:documentation> - Unique section name identifier. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="deprecated"> - <xs:annotation> - <xs:documentation> - Message and flag which shows that entity is deprecated. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attributeGroup ref="removeAttribute"/> - <xs:attribute type="xs:string" name="filename"/> - </xs:complexType> - </xs:element> - - <xs:element name="element"> - <xs:complexType> - <xs:attribute type="notEmptyType" name="name" use="required"> - <xs:annotation> - <xs:documentation> - Element name. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="deprecated"> - <xs:annotation> - <xs:documentation> - Message and flag which shows that entity is deprecated. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="uiElementType" name="type" use="required"> - <xs:annotation> - <xs:documentation> - The type of the element, e.g. select, radio, etc. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="notEmptyType" name="selector" use="optional"> - <xs:annotation> - <xs:documentation> - Selector of the element. Optional due to being able to use either this or locatorFunction. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="notEmptyType" name="locatorFunction" use="optional"> - <xs:annotation> - <xs:documentation> - LocatorFunction of an element, substitute for a selector. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="timeoutType" name="timeout" use="optional"> - <xs:annotation> - <xs:documentation> - Optional timeout value in second to wait for the operation on the element. use "-" for default value. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:boolean" name="parameterized" use="optional"/> - <xs:attributeGroup ref="removeAttribute"/> - </xs:complexType> - </xs:element> - - <xs:simpleType name="uiElementType"> - <xs:restriction base="xs:string"> - <xs:enumeration value="text"/> - <xs:enumeration value="textarea"/> - <xs:enumeration value="input"/> - <xs:enumeration value="button"/> - <xs:enumeration value="checkbox"/> - <xs:enumeration value="radio"/> - <xs:enumeration value="checkboxset"/> - <xs:enumeration value="radioset"/> - <xs:enumeration value="date"/> - <xs:enumeration value="file"/> - <xs:enumeration value="select"/> - <xs:enumeration value="multiselect"/> - <xs:enumeration value="wysiwyg"/> - <xs:enumeration value="iframe"/> - <xs:enumeration value="block"/> - </xs:restriction> - </xs:simpleType> - - <xs:simpleType name="notEmptyType"> - <xs:restriction base="xs:string"> - <xs:minLength value="1" /> - </xs:restriction> - </xs:simpleType> - - <xs:simpleType name="timeoutType"> - <xs:restriction base="xs:string"> - <xs:pattern value="([0-9])+|-"/> - </xs:restriction> - </xs:simpleType> - - <xs:attributeGroup name="removeAttribute"> - <xs:attribute type="xs:boolean" name="remove" use="optional" default="false"> - <xs:annotation> - <xs:documentation> - Set to true to remove this element during parsing. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> + </xs:redefine> </xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/mergedPageObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/mergedPageObject.xsd new file mode 100644 index 000000000..65ac8290d --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Page/etc/mergedPageObject.xsd @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:annotation> + <xs:documentation>The definition of a page object.</xs:documentation> + </xs:annotation> + + <xs:element name="pages"> + <xs:annotation> + <xs:documentation> + The root element for configuration data. + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element ref="page" maxOccurs="unbounded" minOccurs="1"> + <xs:annotation> + <xs:documentation> + Contains sequence of ui sections in a page. + </xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="page"> + <xs:complexType> + <xs:sequence> + <xs:element ref="section" maxOccurs="unbounded" minOccurs="0"> + <xs:annotation> + <xs:documentation> + Contains sequence of ui elements. + </xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + <xs:attribute type="notEmptyType" name="name" use="required"> + <xs:annotation> + <xs:documentation> + Unique page name identifier. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="deprecated"> + <xs:annotation> + <xs:documentation> + Message and flag which shows that entity is deprecated. + </xs:documentation> + </xs:annotation> + </xs:attribute> + + <xs:attribute type="notEmptyType" name="url" use="required"> + <xs:annotation> + <xs:documentation> + URL for the page. Do not include the hostname. For example: "/admin/customer/index/" + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="notEmptyType" name="module" use="required"> + <xs:annotation> + <xs:documentation> + The name of the module to which the page belongs. For example: "Magento_Catalog". + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:boolean" name="parameterized" use="optional"/> + <xs:attribute type="pageArea" name="area" use="required"/> + <xs:attributeGroup ref="removeAttribute"/> + <xs:attribute type="xs:string" name="filename"/> + </xs:complexType> + </xs:element> + + <xs:element name="section"> + <xs:complexType> + <xs:attribute type="notEmptyType" name="name" use="required"> + <xs:annotation> + <xs:documentation> + Unique section name identifier. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="removeAttribute"/> + </xs:complexType> + </xs:element> + + <xs:simpleType name="notEmptyType"> + <xs:restriction base="xs:string"> + <xs:minLength value="1" /> + </xs:restriction> + </xs:simpleType> + + <xs:attributeGroup name="removeAttribute"> + <xs:attribute type="xs:boolean" name="remove" use="optional" default="false"> + <xs:annotation> + <xs:documentation> + Set to true to remove this element during parsing. + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:attributeGroup> + + <xs:simpleType name="pageArea" final="restriction" > + <xs:restriction base="xs:string"> + <xs:enumeration value="admin" /> + <xs:enumeration value="storefront" /> + <xs:enumeration value="external" /> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/mergedSectionObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/mergedSectionObject.xsd new file mode 100644 index 000000000..1b5b44ddd --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Page/etc/mergedSectionObject.xsd @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="sections"> + <xs:annotation> + <xs:documentation> + The root element for configuration data. + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element ref="section" maxOccurs="unbounded" minOccurs="1"> + <xs:annotation> + <xs:documentation> + Contains sequence of ui elements in a section of a page. + </xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + + <xs:element name="section"> + <xs:complexType> + <xs:sequence> + <xs:element ref="element" maxOccurs="unbounded" minOccurs="1"> + <xs:annotation> + <xs:documentation> + Contains information of an ui element. + </xs:documentation> + </xs:annotation> + </xs:element> + </xs:sequence> + <xs:attribute type="notEmptyType" name="name" use="required"> + <xs:annotation> + <xs:documentation> + Unique section name identifier. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="deprecated"> + <xs:annotation> + <xs:documentation> + Message and flag which shows that entity is deprecated. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="removeAttribute"/> + <xs:attribute type="xs:string" name="filename"/> + </xs:complexType> + </xs:element> + + <xs:element name="element"> + <xs:complexType> + <xs:attribute type="notEmptyType" name="name" use="required"> + <xs:annotation> + <xs:documentation> + Element name. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="deprecated"> + <xs:annotation> + <xs:documentation> + Message and flag which shows that entity is deprecated. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="uiElementType" name="type" use="required"> + <xs:annotation> + <xs:documentation> + The type of the element, e.g. select, radio, etc. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="notEmptyType" name="selector" use="optional"> + <xs:annotation> + <xs:documentation> + Selector of the element. Optional due to being able to use either this or locatorFunction. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="notEmptyType" name="locatorFunction" use="optional"> + <xs:annotation> + <xs:documentation> + LocatorFunction of an element, substitute for a selector. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="timeoutType" name="timeout" use="optional"> + <xs:annotation> + <xs:documentation> + Optional timeout value in second to wait for the operation on the element. use "-" for default value. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:boolean" name="parameterized" use="optional"/> + <xs:attributeGroup ref="removeAttribute"/> + </xs:complexType> + </xs:element> + + <xs:simpleType name="uiElementType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="text"/> + <xs:enumeration value="textarea"/> + <xs:enumeration value="input"/> + <xs:enumeration value="button"/> + <xs:enumeration value="checkbox"/> + <xs:enumeration value="radio"/> + <xs:enumeration value="checkboxset"/> + <xs:enumeration value="radioset"/> + <xs:enumeration value="date"/> + <xs:enumeration value="file"/> + <xs:enumeration value="select"/> + <xs:enumeration value="multiselect"/> + <xs:enumeration value="wysiwyg"/> + <xs:enumeration value="iframe"/> + <xs:enumeration value="block"/> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="notEmptyType"> + <xs:restriction base="xs:string"> + <xs:minLength value="1" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="timeoutType"> + <xs:restriction base="xs:string"> + <xs:pattern value="([0-9])+|-"/> + </xs:restriction> + </xs:simpleType> + + <xs:attributeGroup name="removeAttribute"> + <xs:attribute type="xs:boolean" name="remove" use="optional" default="false"> + <xs:annotation> + <xs:documentation> + Set to true to remove this element during parsing. + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:attributeGroup> +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php index 32c7661fe..8b95fb9d5 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php @@ -6,14 +6,14 @@ namespace Magento\FunctionalTestingFramework\StaticCheck; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Symfony\Component\Console\Input\InputInterface; -use Magento\FunctionalTestingFramework\Util\ModuleResolver; use Symfony\Component\Finder\Finder; use Exception; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Finder\SplFileInfo; +use DOMElement; /** * Class ActionGroupArgumentsCheck @@ -21,11 +21,7 @@ */ class ActionGroupArgumentsCheck implements StaticCheckInterface { - - const ACTIONGROUP_XML_REGEX_PATTERN = '/<actionGroup\sname=(?: (?!<\/actionGroup>).)*/mxs'; - const ACTIONGROUP_ARGUMENT_REGEX_PATTERN = '/<argument[^\/>]*name="([^"\']*)/mxs'; const ACTIONGROUP_NAME_REGEX_PATTERN = '/<actionGroup name=["\']([^\'"]*)/'; - const ERROR_LOG_FILENAME = 'mftf-arguments-checks'; const ERROR_LOG_MESSAGE = 'MFTF Action Group Unused Arguments Check'; @@ -41,6 +37,13 @@ class ActionGroupArgumentsCheck implements StaticCheckInterface */ private $output; + /** + * ScriptUtil instance + * + * @var ScriptUtil + */ + private $scriptUtil; + /** * Checks unused arguments in action groups and prints out error to file. * @@ -50,26 +53,19 @@ class ActionGroupArgumentsCheck implements StaticCheckInterface */ public function execute(InputInterface $input) { - MftfApplicationConfig::create( - true, - MftfApplicationConfig::UNIT_TEST_PHASE, - false, - MftfApplicationConfig::LEVEL_NONE, - true - ); - - $allModules = ModuleResolver::getInstance()->getModulesPath(); + $this->scriptUtil = new ScriptUtil(); + $allModules = $this->scriptUtil->getAllModulePaths(); - $actionGroupXmlFiles = StaticCheckHelper::buildFileList( + $actionGroupXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope( $allModules, DIRECTORY_SEPARATOR . 'ActionGroup' . DIRECTORY_SEPARATOR ); $this->errors = $this->findErrorsInFileSet($actionGroupXmlFiles); - $this->output = StaticCheckHelper::printErrorsToFile( + $this->output = $this->scriptUtil->printErrorsToFile( $this->errors, - self::ERROR_LOG_FILENAME, + StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt', self::ERROR_LOG_MESSAGE ); } @@ -100,61 +96,87 @@ public function getOutput() private function findErrorsInFileSet($files) { $actionGroupErrors = []; + /** @var SplFileInfo $filePath */ foreach ($files as $filePath) { - $contents = file_get_contents($filePath); - preg_match_all(self::ACTIONGROUP_XML_REGEX_PATTERN, $contents, $actionGroups); - $actionGroupToArguments = $this->buildUnusedArgumentList($actionGroups[0]); - $actionGroupErrors += $this->setErrorOutput($actionGroupToArguments, $filePath); + $actionGroupToArguments = []; + $contents = $filePath->getContents(); + /** @var DOMElement $actionGroup */ + $actionGroup = $this->getActionGroupDomElement($contents); + $arguments = $this->extractActionGroupArguments($actionGroup); + $unusedArguments = $this->findUnusedArguments($arguments, $contents); + if (!empty($unusedArguments)) { + $actionGroupToArguments[$actionGroup->getAttribute('name')] = $unusedArguments; + $actionGroupErrors += $this->setErrorOutput($actionGroupToArguments, $filePath); + } } return $actionGroupErrors; } /** - * Builds array of action group => unused arguments - * @param array $actionGroups - * @return array $actionGroupToArguments + * Extract actionGroup DomElement from xml file + * @param string $contents + * @return \DOMElement */ - private function buildUnusedArgumentList($actionGroups) + public function getActionGroupDomElement($contents) { - $actionGroupToArguments = []; + $domDocument = new \DOMDocument(); + $domDocument->loadXML($contents); + return $domDocument->getElementsByTagName('actionGroup')[0]; + } - foreach ($actionGroups as $actionGroupXml) { - preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); - $unusedArguments = $this->findUnusedArguments($actionGroupXml); - if (!empty($unusedArguments)) { - $actionGroupToArguments[$actionGroupName[1]] = $unusedArguments; + /** + * Get list of action group arguments declared in an action group + * @param \DOMElement $actionGroup + * @return array $arguments + */ + public function extractActionGroupArguments($actionGroup) + { + $arguments = []; + $argumentsNodes = $actionGroup->getElementsByTagName('arguments'); + if ($argumentsNodes->length > 0) { + $argumentNodes = $argumentsNodes[0]->getElementsByTagName('argument'); + foreach ($argumentNodes as $argumentNode) { + $arguments[] = $argumentNode->getAttribute('name'); } } - return $actionGroupToArguments; + return $arguments; } /** * Returns unused arguments in an action group - * @param string $actionGroupXml + * @param array $arguments + * @param string $contents * @return array */ - private function findUnusedArguments($actionGroupXml) + public function findUnusedArguments($arguments, $contents) { $unusedArguments = []; - - preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $actionGroupXml, $arguments); - preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); + preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $contents, $actionGroupName); + $validActionGroup = false; try { $actionGroup = ActionGroupObjectHandler::getInstance()->getObject($actionGroupName[1]); - } catch (XmlException $e) { + if ($actionGroup) { + $validActionGroup = true; + } + } catch (Exception $e) { } - foreach ($arguments[1] as $argument) { + + if (!$validActionGroup) { + return $unusedArguments; + } + + foreach ($arguments as $argument) { //pattern to match all argument references $patterns = [ '(\{{2}' . $argument . '(\.[a-zA-Z0-9_\[\]\(\).,\'\/ ]+)?}{2})', '([(,\s\'$$]' . $argument . '(\.[a-zA-Z0-9_$\[\]]+)?[),\s\'])' ]; // matches entity references - if (preg_match($patterns[0], $actionGroupXml)) { + if (preg_match($patterns[0], $contents)) { continue; } //matches parametrized references - if (preg_match($patterns[1], $actionGroupXml)) { + if (preg_match($patterns[1], $contents)) { continue; } //for extending action groups, exclude arguments that are also defined in parent action group @@ -190,8 +212,8 @@ private function isParentActionGroupArgument($argument, $actionGroup) /** * Builds and returns error output for violating references * - * @param array $actionGroupToArguments - * @param string $path + * @param array $actionGroupToArguments + * @param SplFileInfo $path * @return mixed */ private function setErrorOutput($actionGroupToArguments, $path) diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/AnnotationsCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/AnnotationsCheck.php new file mode 100644 index 000000000..b27c23d84 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/AnnotationsCheck.php @@ -0,0 +1,252 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\StaticCheck; + +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; +use Magento\FunctionalTestingFramework\Test\Objects\TestObject; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Exception; + +/** + * Class AnnotationsCheck + * @package Magento\FunctionalTestingFramework\StaticCheck + */ +class AnnotationsCheck implements StaticCheckInterface +{ + const ERROR_LOG_FILENAME = 'mftf-annotations-static-check'; + const ERROR_LOG_MESSAGE = 'MFTF Annotations Static Check'; + + /** + * Array containing all errors found after running the execute() function. + * @var array + */ + private $errors = []; + + /** + * String representing the output summary found after running the execute() function. + * @var string + */ + private $output; + + /** + * Array containing + * key = Story appended to Title + * value = test names that have that pair + * @var array + */ + private $storiesTitlePairs = []; + + /** + * Array containing + * key = testCaseId appended to Title + * value = test names that have that pair + * @var array + */ + private $testCaseIdTitlePairs = []; + + /** + * Validates test annotations + * + * @param InputInterface $input + * @return void + * @throws Exception + */ + public function execute(InputInterface $input) + { + // Set MFTF to the UNIT_TEST_PHASE to mute the default DEPRECATION warnings from the TestObjectHandler. + MftfApplicationConfig::create( + true, + MftfApplicationConfig::UNIT_TEST_PHASE, + false, + MftfApplicationConfig::LEVEL_DEFAULT, + true + ); + $allTests = TestObjectHandler::getInstance(false)->getAllObjects(); + + foreach ($allTests as $test) { + if ($this->validateSkipIssueId($test)) { + //if test is skipped ignore other checks + continue; + } + $this->validateRequiredAnnotations($test); + $this->aggregateStoriesTitlePairs($test); + $this->aggregateTestCaseIdTitlePairs($test); + } + + $this->validateStoriesTitlePairs(); + $this->validateTestCaseIdTitlePairs(); + + $scriptUtil = new ScriptUtil(); + $this->output = $scriptUtil->printErrorsToFile( + $this->errors, + StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt', + self::ERROR_LOG_MESSAGE + ); + } + + /** + * Return array containing all errors found after running the execute() function. + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + /** + * Return string of a short human readable result of the check. For example: "No Dependency errors found." + * @return string + */ + public function getOutput() + { + return $this->output; + } + + /** + * Validates that the test has the following annotations: + * stories + * title + * description + * severity + * + * @param TestObject $test + * @return void + */ + private function validateRequiredAnnotations($test) + { + $annotations = $test->getAnnotations(); + $missing = []; + + $stories = $annotations['stories'] ?? null; + if ($stories === null) { + $missing[] = "stories"; + } + + $title = $annotations['title'] ?? null; + if ($title === null) { + $missing[] = "title"; + } + + $description = $annotations['description']['main'] ?? null; + if ($description === null) { + $missing[] = "description"; + } + + $severity = $annotations['severity'] ?? null; + if ($severity === null) { + $missing[] = "severity"; + } + + $allMissing = join(", ", $missing); + if (strlen($allMissing) > 0) { + $this->errors[][] = "Test {$test->getName()} is missing the required annotations: " . $allMissing; + } + } + + /** + * Validates that if the test is skipped, that it has an issueId value. + * + * @param TestObject $test + * @return boolean + */ + private function validateSkipIssueId($test) + { + $validateSkipped = false; + $annotations = $test->getAnnotations(); + + $skip = $annotations['skip'] ?? null; + if ($skip !== null) { + $validateSkipped = true; + if ((!isset($skip[0]) || strlen($skip[0]) == 0) + && (!isset($skip['issueId']) || strlen($skip['issueId']) == 0)) { + $this->errors[][] = "Test {$test->getName()} is skipped but the issueId is empty."; + } + } + return $validateSkipped; + } + + /** + * Add the key = "stories appended to title", value = test name, to the class variable. + * + * @param TestObject $test + * @return void + */ + private function aggregateStoriesTitlePairs($test) + { + $annotations = $test->getAnnotations(); + $stories = $annotations['stories'][0] ?? null; + $title = $this->getTestTitleWithoutPrefix($test); + if ($stories !== null && $title !== null) { + $this->storiesTitlePairs[$stories . $title][] = $test->getName(); + } + } + + /** + * Add the key = "testCaseId appended to title", value = test name, to the class variable. + * + * @param TestObject $test + * @return void + */ + private function aggregateTestCaseIdTitlePairs($test) + { + $annotations = $test->getAnnotations(); + $testCaseId = $annotations['testCaseId'][0] ?? null; + $title = $this->getTestTitleWithoutPrefix($test); + if ($testCaseId !== null && $title !== null) { + $this->testCaseIdTitlePairs[$testCaseId . $title][] = $test->getName(); + } + } + + /** + * Strip away the testCaseId prefix that was automatically added to the test title + * so that way we have just the raw title from the XML file. + * + * @param TestObject $test + * @return string|null + */ + private function getTestTitleWithoutPrefix($test) + { + $annotations = $test->getAnnotations(); + $title = $annotations['title'][0] ?? null; + if ($title === null) { + return null; + } else { + $testCaseId = $annotations['testCaseId'][0] ?? "[NO TESTCASEID]"; + return substr($title, strlen($testCaseId . ": ")); + } + } + + /** + * Adds an error if any story+title pairs are used by more than one test. + * + * @return void + */ + private function validateStoriesTitlePairs() + { + foreach ($this->storiesTitlePairs as $pair) { + if (sizeof($pair) > 1) { + $this->errors[][] = "Stories + title combination must be unique: " . join(", ", $pair); + } + } + } + + /** + * Adds an error if any testCaseId+title pairs are used by more than one test. + * + * @return void + */ + private function validateTestCaseIdTitlePairs() + { + foreach ($this->testCaseIdTitlePairs as $pair) { + if (sizeof($pair) > 1) { + $this->errors[][] = "testCaseId + title combination must be unique: " . join(", ", $pair); + } + } + } +} diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/DeprecatedEntityUsageCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/DeprecatedEntityUsageCheck.php new file mode 100644 index 000000000..5da16ec6a --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/DeprecatedEntityUsageCheck.php @@ -0,0 +1,701 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\StaticCheck; + +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use InvalidArgumentException; +use Exception; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Exceptions\XmlException; +use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; +use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; +use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; +use Magento\FunctionalTestingFramework\Page\Objects\PageObject; +use Magento\FunctionalTestingFramework\Test\Objects\TestObject; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Finder\Finder; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; +use Magento\FunctionalTestingFramework\DataGenerator\Objects\OperationDefinitionObject; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; +use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; +use Symfony\Component\Finder\SplFileInfo; +use DOMNodeList; +use DOMElement; + +/** + * Class DeprecatedEntityUsageCheck + * @package Magento\FunctionalTestingFramework\StaticCheck + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class DeprecatedEntityUsageCheck implements StaticCheckInterface +{ + const EXTENDS_REGEX_PATTERN = '/extends=["\']([^\'"]*)/'; + const ACTIONGROUP_REGEX_PATTERN = '/ref=["\']([^\'"]*)/'; + + const ERROR_LOG_FILENAME = 'mftf-deprecated-entity-usage-checks'; + const ERROR_LOG_MESSAGE = 'MFTF Deprecated Entity Usage Check'; + + /** + * Array containing all errors found after running the execute() function + * + * @var array + */ + private $errors = []; + + /** + * String representing the output summary found after running the execute() function + * + * @var string + */ + private $output; + + /** + * ScriptUtil instance + * + * @var ScriptUtil + */ + private $scriptUtil; + + /** + * Data operations + * + * @var array + */ + private $dataOperations = ['create', 'update', 'get', 'delete']; + + /** + * Test xml files to scan + * + * @var Finder|array + */ + private $testXmlFiles = []; + + /** + * Action group xml files to scan + * + * @var Finder|array + */ + private $actionGroupXmlFiles = []; + + /** + * Suite xml files to scan + * + * @var Finder|array + */ + private $suiteXmlFiles = []; + + /** + * Root suite xml files to scan + * + * @var Finder|array + */ + private $rootSuiteXmlFiles = []; + + /** + * Data xml files to scan + * + * @var Finder|array + */ + private $dataXmlFiles = []; + + /** + * Checks test dependencies, determined by references in tests versus the dependencies listed in the Magento module + * + * @param InputInterface $input + * @return void + * @throws Exception + */ + public function execute(InputInterface $input) + { + $this->scriptUtil = new ScriptUtil(); + $this->loadAllXmlFiles($input); + + $this->errors = []; + $this->errors += $this->findReferenceErrorsInActionFiles($this->testXmlFiles); + $this->errors += $this->findReferenceErrorsInActionFiles($this->actionGroupXmlFiles); + $this->errors += $this->findReferenceErrorsInActionFiles($this->suiteXmlFiles, true); + if (!empty($this->rootSuiteXmlFiles)) { + $this->errors += $this->findReferenceErrorsInActionFiles($this->rootSuiteXmlFiles, true); + } + $this->errors += $this->findReferenceErrorsInDataFiles($this->dataXmlFiles); + + // Hold on to the output and print any errors to a file + $this->output = $this->scriptUtil->printErrorsToFile( + $this->errors, + StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt', + self::ERROR_LOG_MESSAGE + ); + } + + /** + * Return array containing all errors found after running the execute() function + * + * @return array + */ + public function getErrors() + { + return $this->errors; + } + + /** + * Return string of a short human readable result of the check. For example: "No Dependency errors found." + * + * @return string + */ + public function getOutput() + { + return $this->output; + } + + /** + * Read all XML files for scanning + * + * @param InputInterface $input + * @return void + * @throws Exception + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function loadAllXmlFiles($input) + { + $modulePaths = []; + $includeRootPath = true; + $path = $input->getOption('path'); + if ($path) { + if (!realpath($path)) { + throw new InvalidArgumentException('Invalid --path option: ' . $path); + } + MftfApplicationConfig::create( + true, + MftfApplicationConfig::UNIT_TEST_PHASE, + false, + MftfApplicationConfig::LEVEL_DEFAULT, + true + ); + putenv('CUSTOM_MODULE_PATHS=' . realpath($path)); + $modulePaths[] = realpath($path); + $includeRootPath = false; + } else { + $modulePaths = $this->scriptUtil->getAllModulePaths(); + } + + // These files can contain references to other entities + $this->testXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Test'); + $this->actionGroupXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'ActionGroup'); + $this->suiteXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Suite'); + if ($includeRootPath) { + $this->rootSuiteXmlFiles = $this->scriptUtil->getRootSuiteXmlFiles(); + } + $this->dataXmlFiles= $this->scriptUtil->getModuleXmlFilesByScope($modulePaths, 'Data'); + + if (empty($this->thistestXmlFiles) + && empty($this->actionGroupXmlFiles) + && empty($this->suiteXmlFiles) + && empty($this->dataXmlFiles) + ) { + if ($path) { + throw new InvalidArgumentException( + 'Invalid --path option: ' + . $path + . PHP_EOL + . 'Please make sure --path points to a valid MFTF Test Module.' + ); + } elseif (empty($this->rootSuiteXmlFiles)) { + throw new TestFrameworkException('No xml file to scan.'); + } + } + } + + /** + * Find reference errors in set of action files + * + * @param Finder $files + * @param boolean $checkTestRef + * @return array + * @throws XmlException + */ + private function findReferenceErrorsInActionFiles($files, $checkTestRef = false) + { + $testErrors = []; + /** @var SplFileInfo $filePath */ + foreach ($files as $filePath) { + $contents = file_get_contents($filePath); + preg_match_all(ActionObject::ACTION_ATTRIBUTE_VARIABLE_REGEX_PATTERN, $contents, $braceReferences); + preg_match_all(self::ACTIONGROUP_REGEX_PATTERN, $contents, $actionGroupReferences); + preg_match_all(self::EXTENDS_REGEX_PATTERN, $contents, $extendReferences); + + $domDocument = new \DOMDocument(); + $domDocument->load($filePath); + $createdDataReferences = $this->getAttributesFromDOMNodeList( + $domDocument->getElementsByTagName('createData'), + 'entity' + ); + $updatedDataReferences = $this->getAttributesFromDOMNodeList( + $domDocument->getElementsByTagName('updateData'), + 'entity' + ); + $getDataReferences = $this->getAttributesFromDOMNodeList( + $domDocument->getElementsByTagName('getData'), + 'entity' + ); + + // Remove Duplicates + $actionGroupReferences[1] = array_unique($actionGroupReferences[1]); + $extendReferences[1] = array_unique($extendReferences[1]); + $braceReferences[0] = array_unique($braceReferences[0]); + $braceReferences[2] = array_filter(array_unique($braceReferences[2])); + $createdDataReferences = array_unique($createdDataReferences); + $updatedDataReferences = array_unique($updatedDataReferences); + $getDataReferences = array_unique($getDataReferences); + + // Resolve entity references + $entityReferences = $this->scriptUtil->resolveEntityReferences($braceReferences[0], $contents, true); + // Resolve parameterized references + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveParametrizedReferences($braceReferences[2], $contents, true) + ); + // Resolve action group entity by names + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveEntityByNames($actionGroupReferences[1]) + ); + // Resolve extends entity by names + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveEntityByNames($extendReferences[1]) + ); + // Resolve create data entity by names + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveEntityByNames($createdDataReferences) + ); + // Resolve update data entity by names + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveEntityByNames($updatedDataReferences) + ); + // Resolve get data entity by names + $entityReferences = array_merge( + $entityReferences, + $this->scriptUtil->resolveEntityByNames($getDataReferences) + ); + // Find test references if needed + if ($checkTestRef) { + $entityReferences = array_merge($entityReferences, $this->resolveTestEntityInSuite($domDocument)); + } + + // Find violating references + $violatingReferences = $this->findViolatingReferences($entityReferences); + + // Find metadata references from persist data + $metadataReferences = $this->getMetadataFromData($createdDataReferences, 'create'); + $metadataReferences = array_merge_recursive( + $metadataReferences, + $this->getMetadataFromData($updatedDataReferences, 'update') + ); + $metadataReferences = array_merge_recursive( + $metadataReferences, + $this->getMetadataFromData($getDataReferences, 'get') + ); + + // Find violating references + $violatingReferences = array_merge( + $violatingReferences, + $this->findViolatingMetadataReferences($metadataReferences) + ); + + // Set error output + $testErrors = array_merge($testErrors, $this->setErrorOutput($violatingReferences, $filePath)); + } + return $testErrors; + } + + /** + * Find reference errors in a set of data files + * + * @param Finder $files + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function findReferenceErrorsInDataFiles($files) + { + $testErrors = []; + /** @var SplFileInfo $filePath */ + foreach ($files as $filePath) { + $dataReferences = []; + $metadataReferences = []; + $domDocument = new \DOMDocument(); + $domDocument->load($filePath); + $entities = $domDocument->getElementsByTagName('entity'); + foreach ($entities as $entity) { + /** @var DOMElement $entity */ + $entityName = $entity->getAttribute('name'); + $metadataType = $entity->getAttribute('type'); + $parentEntityName = $entity->getAttribute('extends'); + if (!empty($metadataType && !isset($metadataReferences[$entityName][$metadataType]))) { + $metadataReferences[$entityName][$metadataType] = 'all'; + } + if (!empty($parentEntityName)) { + $dataReferences[$entityName][] = $parentEntityName; + } + // Find metadata reference in `var` elements + $varElements = $entity->getElementsByTagName('var'); + foreach ($varElements as $varElement) { + /** @var DOMElement $varElement */ + $metadataType = $varElement->getAttribute('entityType'); + if (!empty($metadataType) && !isset($metadataReferences[$entityName][$metadataType])) { + $metadataReferences[$entityName][$metadataType] = 'all'; + } + } + // Find metadata reference in `requiredEntity` elements, and + // Find data references in `requiredEntity` elements + $requiredElements = $entity->getElementsByTagName('requiredEntity'); + foreach ($requiredElements as $requiredElement) { + /** @var DOMElement $requiredElement */ + $metadataType = $requiredElement->getAttribute('type'); + if (!empty($metadataType) && !isset($metadataReferences[$entityName][$metadataType])) { + $metadataReferences[$entityName][$metadataType] = 'all'; + } + $dataReferences[$entityName][] = $requiredElement->nodeValue; + } + } + + // Find violating references + // Metadata references is unique + $violatingReferences = $this->findViolatingMetadataReferences($metadataReferences); + // Data references is not unique + $violatingReferences = array_merge_recursive( + $violatingReferences, + $this->findViolatingDataReferences($this->twoDimensionArrayUnique($dataReferences)) + ); + + // Set error output + $testErrors = array_merge($testErrors, $this->setErrorOutput($violatingReferences, $filePath)); + } + return $testErrors; + } + + /** + * Trim duplicate values from two-dimensional array. Dimension 1 array key is unique. + * + * @param array $inArray + * @return array + */ + private function twoDimensionArrayUnique($inArray) + { + $outArray = []; + foreach ($inArray as $key => $arr) { + $outArray[$key] = array_unique($arr); + } + return $outArray; + } + + /** + * Return attribute value for each node in DOMNodeList as an array + * + * @param DOMNodeList $nodes + * @param string $attributeName + * @return array + */ + private function getAttributesFromDOMNodeList($nodes, $attributeName) + { + $attributes = []; + /** @var DOMElement $node */ + foreach ($nodes as $node) { + $attributeValue = $node->getAttribute($attributeName); + if (!empty($attributeValue)) { + $attributes[] = $attributeValue; + } + } + return $attributes; + } + + /** + * Find metadata from data array + * + * @param array $references + * @param string $type + * @return array + */ + private function getMetadataFromData($references, $type) + { + $metaDataReferences = []; + try { + foreach ($references as $dataName) { + /** @var EntityDataObject $dataEntity */ + $dataEntity = $this->scriptUtil->findEntity($dataName); + if ($dataEntity) { + $metadata = $dataEntity->getType(); + if (!empty($metadata)) { + $metaDataReferences[$dataName][$metadata] = $type; + } + } + } + } catch (Exception $e) { + } + return $metaDataReferences; + } + + /** + * Find violating metadata references. Input array format is either + * + * [ + * $dataName1 => [ + * $metaDataName1 = [ + * 'create', + * 'update', + * ], + * ], + * $dataName2 => [ + * $metaDataName2 => 'create', + * ], + * $dataName3 => [ + * $metaDataName3 = [ + * 'get', + * 'create', + * 'update', + * ], + * ], + * ... + * ] + * + * or + * + * [ + * $dataName1 => [ + * $metaDataName1 => 'all', + * $metaDataName2 => 'all', + * ... + * ], + * $dataName2 => [ + * $metaDataName2 => 'all', + * ... + * ], + * $dataName5 => [ + * $metaDataName5 => 'all', + * $metaDataName4 => 'all', + * $metaDataName1 => 'all', + * ... + * ], + * ... + * ] + * + * @param array $references + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function findViolatingMetadataReferences($references) + { + $allObjects = OperationDefinitionObjectHandler::getInstance()->getAllObjects(); + + // Find Violations + $violatingReferences = []; + foreach ($references as $dataName => $metadataArray) { + foreach ($metadataArray as $metadata => $types) { + $operations = []; + $strict = true; + if (is_array($types)) { + $operations = $types; + } elseif ($types === 'all') { + $operations = $this->dataOperations; + $strict = false; + } else { + $operations = [$types]; + } + + $deprecated = null; + $exists = false; + foreach ($operations as $operation) { + if (array_key_exists($operation . $metadata, $allObjects)) { + $exists = true; + /** @var OperationDefinitionObject $entity */ + $entity = $allObjects[$operation . $metadata]; + // When not strictly checking, it's not deprecated as long as we found one that's not deprecated + if (!$strict && empty($entity->getDeprecated())) { + $deprecated = false; + break; + } + // When strictly checking, it's deprecated as long as we found one that's deprecated + if ($strict && !empty($entity->getDeprecated())) { + $deprecated = true; + break; + } + } + } + if ($exists && !$strict && $deprecated !== false) { + $deprecated = true; + } + if ($strict && $deprecated !== true) { + $deprecated = false; + } + + if ($deprecated) { + $violatingReferences["\"{$dataName}\" references deprecated"][] = [ + 'name' => $metadata, + // TODO add filename in OperationDefinitionObject + 'file' => 'metadata xml file', + ]; + } + } + } + return $violatingReferences; + } + + /** + * Find violating data references. Input array format is + * + * [ + * $dataName1 => [ $requiredDataName1, $requiredDataName2, $requiredDataName3], + * $dataName2 => [ $requiredDataName2, $requiredDataName5, $requiredDataName7], + * ... + * ] + * + * @param array $references + * @return array + */ + private function findViolatingDataReferences($references) + { + // Find Violations + $violatingReferences = []; + foreach ($references as $dataName => $requiredDataNames) { + foreach ($requiredDataNames as $requiredDataName) { + try { + /** @var EntityDataObject $requiredData */ + $requiredData = DataObjectHandler::getInstance()->getObject($requiredDataName); + if ($requiredData && $requiredData->getDeprecated()) { + $violatingReferences["\"{$dataName}\" references deprecated"][] = [ + 'name' => $requiredDataName, + 'file' => $requiredData->getFilename(), + ]; + } + } catch (Exception $e) { + } + } + } + return $violatingReferences; + } + + /** + * Find violating references. Input array format is + * + * [ + * 'actionGroupName' => $actionGroupEntity, + * 'dataGroupName' => $dataEntity, + * 'testName' => $testEntity, + * 'pageName' => $pageEntity, + * 'section.field' => $fieldElementEntity, + * ... + * ] + * + * @param array $references + * @return array + */ + private function findViolatingReferences($references) + { + // Find Violations + $violatingReferences = []; + foreach ($references as $key => $entity) { + if ($entity->getDeprecated()) { + $classType = get_class($entity); + $name = $entity->getName(); + if ($classType === ElementObject::class) { + $name = $key; + list($section,) = explode('.', $key, 2); + /** @var SectionObject $references[$section] */ + $file = $references[$section]->getFilename(); + } else { + $file = $entity->getFilename(); + } + $violatingReferences[$this->getSubjectFromClassType($classType)][] = [ + 'name' => $name, + 'file' => $file, + ]; + } + } + return $violatingReferences; + } + + /** + * Build and return error output for violating references + * + * @param array $violatingReferences + * @param SplFileInfo $path + * @return mixed + */ + private function setErrorOutput($violatingReferences, $path) + { + $testErrors = []; + + if (!empty($violatingReferences)) { + // Build error output + $errorOutput = "\nFile \"{$path->getRealPath()}\" contains:\n"; + foreach ($violatingReferences as $subject => $data) { + $errorOutput .= "\t- {$subject}:\n"; + foreach ($data as $item) { + $errorOutput .= "\t\t\"" . $item['name'] . "\" in " . $item['file'] . "\n"; + } + } + $testErrors[$path->getRealPath()][] = $errorOutput; + } + + return $testErrors; + } + + /** + * Resolve test entity in suite + * + * @param \DOMDocument $domDocument + * @return array + */ + private function resolveTestEntityInSuite($domDocument) + { + $testReferences = $this->getAttributesFromDOMNodeList( + $domDocument->getElementsByTagName('test'), + 'name' + ); + + // Remove Duplicates + $testReferences = array_unique($testReferences); + + // Resolve test entity by names + try { + return $this->scriptUtil->resolveEntityByNames($testReferences); + } catch (XmlException $e) { + return []; + } + } + + /** + * Return subject string for a class name + * + * @param string $classname + * @return string|null + */ + private function getSubjectFromClassType($classname) + { + $subject = null; + if ($classname === ActionGroupObject::class) { + $subject = 'Deprecated ActionGroup(s)'; + } elseif ($classname === TestObject::class) { + $subject = 'Deprecated Test(s)'; + } elseif ($classname === SectionObject::class) { + $subject = 'Deprecated Section(s)'; + } elseif ($classname === PageObject::class) { + $subject = 'Deprecated Page(s)'; + } elseif ($classname === ElementObject::class) { + $subject = 'Deprecated Element(s)'; + } elseif ($classname === EntityDataObject::class) { + $subject = 'Deprecated Data(s)'; + } elseif ($classname === OperationDefinitionObject::class) { + $subject = 'Deprecated Metadata(s)'; + } + return $subject; + } +} diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php deleted file mode 100644 index f534544fc..000000000 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\FunctionalTestingFramework\StaticCheck; - -use Symfony\Component\Finder\Finder; - -class StaticCheckHelper -{ - /** - * Prints out given errors to file, and returns summary result string - * @param array $errors - * @param string $filename - * @param string $message - * @return string - */ - public static function printErrorsToFile($errors, $filename, $message) - { - if (empty($errors)) { - return $message . ": No errors found."; - } - - $outputPath = getcwd() . DIRECTORY_SEPARATOR . $filename . ".txt"; - $fileResource = fopen($outputPath, 'w'); - - foreach ($errors as $test => $error) { - fwrite($fileResource, $error[0] . PHP_EOL); - } - - fclose($fileResource); - $errorCount = count($errors); - $output = $message . ": Errors found across {$errorCount} file(s). Error details output to {$outputPath}"; - - return $output; - } - - /** - * Builds list of all XML files in given modulePaths + path given - * @param array $modulePaths - * @param string $path - * @return Finder - */ - public static function buildFileList($modulePaths, $path) - { - $finder = new Finder(); - foreach ($modulePaths as $modulePath) { - if (!realpath($modulePath . $path)) { - continue; - } - $finder->files()->in($modulePath . $path)->name("*.xml"); - } - return $finder->files(); - } -} diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php index ffa63389d..7cd894e00 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php @@ -7,12 +7,18 @@ namespace Magento\FunctionalTestingFramework\StaticCheck; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; + /** * Class StaticChecksList has a list of static checks to run on test xml * @codingStandardsIgnoreFile */ class StaticChecksList implements StaticCheckListInterface { + const DEPRECATED_ENTITY_USAGE_CHECK_NAME = 'deprecatedEntityUsage'; + const STATIC_RESULTS = 'tests' . DIRECTORY_SEPARATOR .'_output' . DIRECTORY_SEPARATOR . 'static-results'; + /** * Property contains all static check scripts. * @@ -20,17 +26,32 @@ class StaticChecksList implements StaticCheckListInterface */ private $checks; + /** + * Directory path for static checks error files + * + * @var string + */ + private static $errorFilesPath = null; + /** * Constructor * * @param array $checks + * @throws TestFrameworkException */ public function __construct(array $checks = []) { $this->checks = [ 'testDependencies' => new TestDependencyCheck(), 'actionGroupArguments' => new ActionGroupArgumentsCheck(), + self::DEPRECATED_ENTITY_USAGE_CHECK_NAME => new DeprecatedEntityUsageCheck(), + 'annotations' => new AnnotationsCheck() ] + $checks; + + // Static checks error files directory + if (null === self::$errorFilesPath) { + self::$errorFilesPath = FilePathFormatter::format(TESTS_BP) . self::STATIC_RESULTS; + } } /** @@ -40,4 +61,12 @@ public function getStaticChecks() { return $this->checks; } + + /** + * Return the directory path for the static check error files + */ + public static function getErrorFilesPath() + { + return self::$errorFilesPath; + } } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php index 3c3ed6a37..6bfe17219 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php @@ -6,31 +6,22 @@ namespace Magento\FunctionalTestingFramework\StaticCheck; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; -use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use Magento\FunctionalTestingFramework\Exceptions\XmlException; -use Magento\FunctionalTestingFramework\Page\Handlers\PageObjectHandler; -use Magento\FunctionalTestingFramework\Page\Handlers\SectionObjectHandler; -use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; -use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; -use Magento\FunctionalTestingFramework\Util\ModuleResolver; -use Magento\FunctionalTestingFramework\Util\TestGenerator; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Finder\Finder; use Exception; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; /** * Class TestDependencyCheck * @package Magento\FunctionalTestingFramework\StaticCheck - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TestDependencyCheck implements StaticCheckInterface { const EXTENDS_REGEX_PATTERN = '/extends=["\']([^\'"]*)/'; const ACTIONGROUP_REGEX_PATTERN = '/ref=["\']([^\'"]*)/'; - const ACTIONGROUP_ARGUMENT_REGEX_PATTERN = '/<argument[^\/>]*name="([^"\']*)/'; const ERROR_LOG_FILENAME = 'mftf-dependency-checks'; const ERROR_LOG_MESSAGE = 'MFTF File Dependency Check'; @@ -83,42 +74,44 @@ class TestDependencyCheck implements StaticCheckInterface */ private $allEntities = []; + /** + * ScriptUtil instance + * + * @var ScriptUtil + */ + private $scriptUtil; + /** * Checks test dependencies, determined by references in tests versus the dependencies listed in the Magento module * * @param InputInterface $input - * @return string - * @throws Exception; + * @return void + * @throws Exception */ public function execute(InputInterface $input) { - MftfApplicationConfig::create( - true, - MftfApplicationConfig::UNIT_TEST_PHASE, - false, - MftfApplicationConfig::LEVEL_NONE, - true - ); + $this->scriptUtil = new ScriptUtil(); + $allModules = $this->scriptUtil->getAllModulePaths(); - ModuleResolver::getInstance()->getModulesPath(); if (!class_exists('\Magento\Framework\Component\ComponentRegistrar')) { - return "TEST DEPENDENCY CHECK ABORTED: MFTF must be attached or pointing to Magento codebase."; + throw new TestFrameworkException( + "TEST DEPENDENCY CHECK ABORTED: MFTF must be attached or pointing to Magento codebase." + ); } $registrar = new \Magento\Framework\Component\ComponentRegistrar(); $this->moduleNameToPath = $registrar->getPaths(\Magento\Framework\Component\ComponentRegistrar::MODULE); $this->moduleNameToComposerName = $this->buildModuleNameToComposerName($this->moduleNameToPath); $this->flattenedDependencies = $this->buildComposerDependencyList(); - $allModules = ModuleResolver::getInstance()->getModulesPath(); $filePaths = [ DIRECTORY_SEPARATOR . 'Test' . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR . 'ActionGroup' . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR . 'Data' . DIRECTORY_SEPARATOR, ]; // These files can contain references to other modules. - $testXmlFiles = StaticCheckHelper::buildFileList($allModules, $filePaths[0]); - $actionGroupXmlFiles = StaticCheckHelper::buildFileList($allModules, $filePaths[1]); - $dataXmlFiles= StaticCheckHelper::buildFileList($allModules, $filePaths[2]); + $testXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($allModules, $filePaths[0]); + $actionGroupXmlFiles = $this->scriptUtil->getModuleXmlFilesByScope($allModules, $filePaths[1]); + $dataXmlFiles= $this->scriptUtil->getModuleXmlFilesByScope($allModules, $filePaths[2]); $this->errors = []; $this->errors += $this->findErrorsInFileSet($testXmlFiles); @@ -126,9 +119,9 @@ public function execute(InputInterface $input) $this->errors += $this->findErrorsInFileSet($dataXmlFiles); // hold on to the output and print any errors to a file - $this->output = StaticCheckHelper::printErrorsToFile( + $this->output = $this->scriptUtil->printErrorsToFile( $this->errors, - self::ERROR_LOG_FILENAME, + StaticChecksList::getErrorFilesPath() . DIRECTORY_SEPARATOR . self::ERROR_LOG_FILENAME . '.txt', self::ERROR_LOG_MESSAGE ); } @@ -155,17 +148,16 @@ public function getOutput() * Finds all reference errors in given set of files * @param Finder $files * @return array - * @throws TestReferenceException * @throws XmlException */ private function findErrorsInFileSet($files) { $testErrors = []; foreach ($files as $filePath) { - $modulePath = dirname(dirname(dirname(dirname($filePath)))); - $moduleFullName = array_search($modulePath, $this->moduleNameToPath) ?? null; + $this->allEntities = []; + $moduleName = $this->getModuleName($filePath); // Not a module, is either dev/tests/acceptance or loose folder with test materials - if ($moduleFullName == null) { + if ($moduleName == null) { continue; } @@ -180,108 +172,37 @@ private function findErrorsInFileSet($files) $braceReferences[1] = array_unique($braceReferences[1]); $braceReferences[2] = array_filter(array_unique($braceReferences[2])); - // resolve data entity references - $this->resolveDataEntityReferences($braceReferences[0], $contents); + // resolve entity references + $this->allEntities = array_merge( + $this->allEntities, + $this->scriptUtil->resolveEntityReferences($braceReferences[0], $contents) + ); - //resolve entity references - $this->resolveParametrizedReferences($braceReferences[2], $contents); + // resolve parameterized references + $this->allEntities = array_merge( + $this->allEntities, + $this->scriptUtil->resolveParametrizedReferences($braceReferences[2], $contents) + ); - // Check actionGroup references - $this->resolveEntityReferences($actionGroupReferences[1]); + // resolve entity by names + $this->allEntities = array_merge( + $this->allEntities, + $this->scriptUtil->resolveEntityByNames($actionGroupReferences[1]) + ); - // Check extended objects - $this->resolveEntityReferences($extendReferences[1]); + // resolve entity by names + $this->allEntities = array_merge( + $this->allEntities, + $this->scriptUtil->resolveEntityByNames($extendReferences[1]) + ); // Find violating references and set error output - $violatingReferences = $this->findViolatingReferences($moduleFullName); - $testErrors = $this->setErrorOutput($violatingReferences, $filePath); + $violatingReferences = $this->findViolatingReferences($moduleName); + $testErrors = array_merge($testErrors, $this->setErrorOutput($violatingReferences, $filePath)); } return $testErrors; } - /** - * Drill down into params in {{ref.params('string', $data.key$, entity.reference)}} - * and resolve references. - * - * @param array $braceReferences - * @param string $contents - * @return void - * @throws XmlException - */ - private function resolveParametrizedReferences($braceReferences, $contents) - { - foreach ($braceReferences as $parameterizedReference) { - preg_match( - ActionObject::ACTION_ATTRIBUTE_VARIABLE_REGEX_PARAMETER, - $parameterizedReference, - $arguments - ); - $splitArguments = explode(',', ltrim(rtrim($arguments[0], ")"), "(")); - foreach ($splitArguments as $argument) { - // Do nothing for 'string' or $persisted.data$ - if (preg_match(ActionObject::STRING_PARAMETER_REGEX, $argument)) { - continue; - } elseif (preg_match(TestGenerator::PERSISTED_OBJECT_NOTATION_REGEX, $argument)) { - continue; - } - // trim `data.field` to `data` - preg_match('/([^.]+)/', $argument, $entityName); - // Double check that {{data.field}} isn't an argument for an ActionGroup - $entity = $this->findEntity($entityName[1]); - preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $contents, $possibleArgument); - if (array_search($entityName[1], $possibleArgument[1]) !== false) { - continue; - } - if ($entity !== null) { - $this->allEntities[$entity->getName()] = $entity; - } - } - } - } - - /** - * Check `data` entities in {{data.field}} or {{data.field('param')}} and resolve references - * - * @param array $braceReferences - * @param string $contents - * @return void - * @throws XmlException - - */ - private function resolveDataEntityReferences($braceReferences, $contents) - { - foreach ($braceReferences as $reference) { - // trim `{{data.field}}` to `data` - preg_match('/{{([^.]+)/', $reference, $entityName); - // Double check that {{data.field}} isn't an argument for an ActionGroup - $entity = $this->findEntity($entityName[1]); - preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $contents, $possibleArgument); - if (array_search($entityName[1], $possibleArgument[1]) !== false) { - continue; - } - if ($entity !== null) { - $this->allEntities[$entity->getName()] = $entity; - } - } - } - - /** - * Resolve entity references - * - * @param array $references - * @return void - * @throws XmlException - */ - private function resolveEntityReferences($references) - { - foreach ($references as $reference) { - $entity = $this->findEntity($reference); - if ($entity !== null) { - $this->allEntities[$entity->getName()] = $entity; - } - } - } - /** * Find violating references * @@ -359,7 +280,10 @@ private function buildComposerDependencyList() $flattenedDependencies = []; foreach ($this->moduleNameToPath as $moduleName => $pathToModule) { - $composerData = json_decode(file_get_contents($pathToModule . DIRECTORY_SEPARATOR . "composer.json"), true); + $composerData = json_decode( + file_get_contents($pathToModule . DIRECTORY_SEPARATOR . "composer.json"), + true + ); $this->allDependencies[$moduleName] = $composerData['require']; } foreach ($this->allDependencies as $moduleName => $dependencies) { @@ -411,43 +335,31 @@ private function getModuleDependenciesFromReferences($array) // Should it append ALL filenames, including merges? $allFiles = explode(",", $item->getFilename()); foreach ($allFiles as $file) { - $modulePath = dirname(dirname(dirname(dirname($file)))); - $fullModuleName = array_search($modulePath, $this->moduleNameToPath); - $composerModuleName = $this->moduleNameToComposerName[$fullModuleName]; - $filenames[$item->getName()][] = $composerModuleName; + $moduleName = $this->getModuleName($file); + if (isset($this->moduleNameToComposerName[$moduleName])) { + $composerModuleName = $this->moduleNameToComposerName[$moduleName]; + $filenames[$item->getName()][] = $composerModuleName; + } } } return $filenames; } /** - * Attempts to find any MFTF entity by its name. Returns null if none are found. - * @param string $name - * @return mixed - * @throws XmlException + * Return module name for a file path + * + * @param string $filePath + * @return string|null */ - private function findEntity($name) + private function getModuleName($filePath) { - if ($name == '_ENV' || $name == '_CREDS') { - return null; - } - - if (DataObjectHandler::getInstance()->getObject($name)) { - return DataObjectHandler::getInstance()->getObject($name); - } elseif (PageObjectHandler::getInstance()->getObject($name)) { - return PageObjectHandler::getInstance()->getObject($name); - } elseif (SectionObjectHandler::getInstance()->getObject($name)) { - return SectionObjectHandler::getInstance()->getObject($name); - } - - try { - return ActionGroupObjectHandler::getInstance()->getObject($name); - } catch (TestReferenceException $e) { - } - try { - return TestObjectHandler::getInstance()->getObject($name); - } catch (TestReferenceException $e) { + $moduleName = null; + foreach ($this->moduleNameToPath as $name => $path) { + if (strpos($filePath, $path) !== false) { + $moduleName = $name; + break; + } } - return null; + return $moduleName; } } diff --git a/src/Magento/FunctionalTestingFramework/Step/Backend/AdminStep.php b/src/Magento/FunctionalTestingFramework/Step/Backend/AdminStep.php deleted file mode 100644 index 5ae74a076..000000000 --- a/src/Magento/FunctionalTestingFramework/Step/Backend/AdminStep.php +++ /dev/null @@ -1,2316 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Step\Backend; - -require_once __DIR__ . '/../../Helper/AdminUrlList.php'; - -/** - * Class AdminStep - * @SuppressWarnings(PHPMD) - * @codingStandardsIgnoreFile - */ -class AdminStep extends \Magento\FunctionalTestingFramework\AcceptanceTester -{ - public static $adminPageTitle = '.page-title'; - - public function openNewTabGoToVerify($url) - { - $I = $this; - $I->openNewTab(); - $I->amOnPage($url); - $I->waitForPageLoad(); - $I->seeInCurrentUrl($url); - } - - public function closeNewTab() - { - $I = $this; - $I->closeTab(); - } - - // Key Admin Pages - public function goToRandomAdminPage() - { - $I = $this; - - $admin_url_list = array( - "/admin/admin/dashboard/", - "/admin/sales/order/", - "/admin/sales/invoice/", - "/admin/sales/shipment/", - "/admin/sales/creditmemo/", - "/admin/paypal/billing_agreement/", - "/admin/sales/transactions/", - "/admin/catalog/product/", - "/admin/catalog/category/", - "/admin/customer/index/", - "/admin/customer/online/", - "/admin/catalog_rule/promo_catalog/", - "/admin/sales_rule/promo_quote/", - "/admin/admin/email_template/", - "/admin/newsletter/template/", - "/admin/newsletter/queue/", - "/admin/newsletter/subscriber/", - "/admin/admin/url_rewrite/index/", - "/admin/search/term/index/", - "/admin/search/synonyms/index/", - "/admin/admin/sitemap/", - "/admin/review/product/index/", - "/admin/cms/page/", - "/admin/cms/block/", - "/admin/admin/widget_instance/", - "/admin/theme/design_config/", - "/admin/admin/system_design_theme/", - "/admin/admin/system_design/", - "/admin/reports/report_shopcart/product/", - "/admin/search/term/report/", - "/admin/reports/report_shopcart/abandoned/", - "/admin/newsletter/problem/", - "/admin/reports/report_review/customer/", - "/admin/reports/report_review/product/", - "/admin/reports/report_sales/sales/", - "/admin/reports/report_sales/tax/", - "/admin/reports/report_sales/invoiced/", - "/admin/reports/report_sales/shipping/", - "/admin/reports/report_sales/refunded/", - "/admin/reports/report_sales/coupons/", - "/admin/paypal/paypal_reports/", - "/admin/braintree/report/", - "/admin/reports/report_customer/totals/", - "/admin/reports/report_customer/orders/", - "/admin/reports/report_customer/accounts/", - "/admin/reports/report_product/viewed/", - "/admin/reports/report_sales/bestsellers/", - "/admin/reports/report_product/lowstock/", - "/admin/reports/report_product/sold/", - "/admin/reports/report_product/downloads/", - "/admin/reports/report_statistics/", - "/admin/admin/system_store/", - "/admin/admin/system_config/", - "/admin/checkout/agreement/", - "/admin/sales/order_status/", - "/admin/tax/rule/", - "/admin/tax/rate/", - "/admin/admin/system_currency/", - "/admin/admin/system_currencysymbol/", - "/admin/catalog/product_attribute/", - "/admin/catalog/product_set/", - "/admin/review/rating/", - "/admin/customer/group/", - "/admin/admin/import/", - "/admin/admin/export/", - "/admin/tax/rate/importExport/", - "/admin/admin/history/", - "/admin/admin/integration/", - "/admin/admin/cache/", - "/admin/backup/index/", - "/admin/indexer/indexer/list/", - "/admin/admin/user/", - "/admin/admin/locks/", - "/admin/admin/user_role/", - "/admin/admin/notification/", - "/admin/admin/system_variable/", - "/admin/admin/crypt_key/" - ); - - $random_admin_url = array_rand($admin_url_list, 1); - - $I->amOnPage($admin_url_list[$random_admin_url]); - $I->waitForPageLoad(); - - return $admin_url_list[$random_admin_url]; - } - - public function goToTheAdminLoginPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLoginPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminLogoutPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLogoutPage); - } - - // Sales - public function goToTheAdminOrdersGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrdersGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrderForIdPage($orderId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderByIdPage . $orderId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddOrderPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddOrderForCustomerIdPage($customerId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderForCustomerIdPage . $customerId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminInvoicesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminInvoicesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddInvoiceForOrderIdPage($orderId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddInvoiceForOrderIdPage . $orderId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminShipmentsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShipmentsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminShipmentForIdPage($shipmentId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShipmentForIdPage . $shipmentId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminCreditMemosGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreditMemosGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCreditMemoForIdPage($creditMemoId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreditMemoForIdPage . $creditMemoId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminBillingAgreementsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBillingAgreementsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTransactionsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTransactionsGrid); - $I->waitForPageLoad(); - } - - // Products - public function goToTheAdminCatalogPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductForIdPage($productId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductForIdPage . $productId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddSimpleProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSimpleProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddConfigurableProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddConfigurableProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddGroupedProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddGroupedProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddVirtualProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddVirtualProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddBundledProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddBundleProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddDownloadableProductPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddDownloadableProductPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCategoriesPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCategoriesPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCategoryForIdPage($categoryId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCategoryForIdPage . $categoryId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddRootCategoryForStoreIdPage($storeId) - { - $I = $this; - $I->amOnPage(('/admin/catalog/category/add/store/' . $storeId . '/parent/1')); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddSubCategoryForStoreIdPage($storeId) - { - $I = $this; - $I->amOnPage(('/admin/catalog/category/add/store/' . $storeId . '/parent/2')); - $I->waitForPageLoad(); - } - - // Customers - public function goToTheAdminAllCustomersGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllCustomersGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomersNowOnlineGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomersNowOnlineGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomerForIdPage($customerId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerForCustomerIdPage . $customerId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddCustomerPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomerPage); - $I->waitForPageLoad(); - } - - // Marketing - public function goToTheAdminCatalogPriceRuleGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogPriceRuleGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCatalogPriceRuleForIdPage($catalogPriceRuleId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogPriceRuleForIdPage . $catalogPriceRuleId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddCatalogPriceRulePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCatalogPriceRulePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCartPriceRulesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCartPriceRulesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCartPriceRuleForIdPage($cartPriceRuleId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCartPriceRuleForIdPage . $cartPriceRuleId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddCartPriceRulePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCartPriceRulePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminEmailTemplatesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEmailTemplatesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminEmailTemplateForIdPage($emailTemplateId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEmailTemplateForIdPage . $emailTemplateId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddEmailTemplatePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddEmailTemplatePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewsletterTemplateGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterTemplateGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewsletterTemplateByIdPage($newsletterTemplateId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterTemplateForIdPage . $newsletterTemplateId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddNewsletterTemplatePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewsletterTemplatePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewsletterQueueGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterQueueGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewsletterSubscribersGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterSubscribersGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminURLRewritesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminURLRewritesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminURLRewriteForId($urlRewriteId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminURLRewriteForIdPage . $urlRewriteId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddURLRewritePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddURLRewritePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminSearchTermsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminSearchTermForIdPage($searchTermId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermForIdPage . $searchTermId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddSearchTermPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSearchTermPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminSearchSynonymsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchSynonymsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminSearchSynonymGroupByIdPage($searchSynonymId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchSynonymGroupForIdPage . $searchSynonymId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddSearchSynonymGroupPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSearchSynonymGroupPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminSiteMapGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSiteMapGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminSiteMapForIdPage($siteMapId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSiteMapForIdPage . $siteMapId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddSiteMapPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSiteMapPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminReviewsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminReviewsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminReviewForIdPage($reviewId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminReviewByIdPage . $reviewId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddReviewPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddReviewPage); - $I->waitForPageLoad(); - } - - // Content - public function goToTheAdminPagesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPagesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminPageForIdPage($pageId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPageForIdPage . $pageId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddPagePage() - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddPagePage)); - $I->waitForPageLoad(); - } - - public function goToTheAdminBlocksGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBlocksGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminBlockForIdPage($blockId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBlockForIdPage . $blockId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddBlockPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddBlockPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminWidgetsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWidgetsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddWidgetPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddWidgetPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminDesignConfigurationGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminDesignConfigurationGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminThemesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminThemesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminThemeByIdPage($themeId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminThemeByIdPage . $themeId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminStoreContentScheduleGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreContentScheduleGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminStoreContentScheduleForIdPage($storeContentScheduleId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreContentScheduleForIdPage . $storeContentScheduleId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddStoreDesignChangePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddStoreDesignChangePage); - $I->waitForPageLoad(); - } - - // Reports - public function goToTheAdminProductsInCartGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductsInCartGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminSearchTermsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminAbandonedCartsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAbandonedCartsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewsletterProblemsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterProblemsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomerReviewsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerReviewsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductReviewsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductReviewsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductReviewsForProductIdPage($productId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductReviewsForProductIdPage . $productId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductReviewIdForProductIdPage($productReviewId, $productId) - { - $I = $this; - $I->amOnPage(('/admin/review/product/edit/id/' . $productReviewId . '/productId/' . $productId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrdersReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrdersReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTaxReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminInvoiceReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminInvoiceReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminShippingReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShippingReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminRefundsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRefundsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCouponsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCouponsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminPayPalSettlementReportsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPayPalSettlementReportsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminBraintreeSettlementReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBraintreeSettlementReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrderTotalReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderTotalReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrderCountReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderCountReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminNewAccountsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewAccountsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductViewsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductViewsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminBestsellersReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBestsellersReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminLowStockReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLowStockReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrderedProductsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderedProductsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminDownloadsReportGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminDownloadsReportGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminRefreshStatisticsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRefreshStatisticsGrid); - $I->waitForPageLoad(); - } - - // Stores - public function goToTheAdminAllStoresGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllStoresGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCreateStoreViewPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateStoreViewPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCreateStorePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateStorePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCreateWebsitePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateWebsitePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminWebsiteForIdPage($websiteId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWebsiteByIdPage . $websiteId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminStoreViewForIdPage($storeViewId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreViewByIdPage . $storeViewId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminStoreForIdPage($storeId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreByIdPage . $storeId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminConfigurationGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminConfigurationGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTermsAndConditionsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTermsAndConditionsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTermsAndConditionForIdPage($termsAndConditionsId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTermsAndConditionByIdPage . $termsAndConditionsId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddNewTermsAndConditionsPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewTermsAndConditionPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminOrderStatusGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderStatusGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddOrderStatusPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderStatusPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminTaxRulesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxRulesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTaxRuleForIdPage($taxRuleId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxRuleByIdPage . $taxRuleId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddTaxRulePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddTaxRulePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminTaxZonesAndRatesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxZonesAndRatesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminTaxZoneAndRateForIdPage($taxZoneAndRateId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxZoneAndRateByIdPage . $taxZoneAndRateId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddTaxZoneAndRatePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddTaxZoneAndRatePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCurrencyRatesPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCurrencyRatesPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCurrencySymbolsPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCurrencySymbolsPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductAttributesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductAttributesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminProductAttributeForIdPage($productAttributeId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductAttributeForIdPage . $productAttributeId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddProductAttributePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddProductAttributePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAttributeSetGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAttributeSetsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminAttributeSetByIdPage($attributeSetId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAttributeSetByIdPage . $attributeSetId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddAttributeSetPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddAttributeSetPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminRatingGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRatingsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminRatingForIdPage($ratingId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRatingForIdPage . $ratingId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddRatingPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddRatingPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomerGroupsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerGroupsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomerGroupForIdPage($customerGroupId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerGroupByIdPage . $customerGroupId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddCustomerGroupPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomerGroupPage); - $I->waitForPageLoad(); - } - - // System - public function goToTheAdminImportPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminExportPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminExportPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminImportAndExportTaxRatesPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportAndExportTaxRatesPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminImportHistoryGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportHistoryGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminIntegrationsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIntegrationsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminIntegrationForIdPage($integrationId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIntegrationByIdPage . $integrationId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddIntegrationPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddIntegrationPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminCacheManagementGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCacheManagementGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminBackupsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBackupsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminIndexManagementGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIndexManagementGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminWebSetupWizardPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWebSetupWizardPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminAllUsersGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllUsersGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminUserForIdPage($userId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserByIdPage . $userId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddUserPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewUserPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminLockedUsersGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLockedUsersGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminUserRolesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserRolesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminUserRoleForIdPage($userRoleId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserRoleByIdPage . $userRoleId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddUserRolePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddUserRolePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminNotificationsGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNotificationsGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomVariablesGrid() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomVariablesGrid); - $I->waitForPageLoad(); - } - - public function goToTheAdminCustomVariableForId($customVariableId) - { - $I = $this; - $I->amOnPage((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomVariableByIdPage . $customVariableId)); - $I->waitForPageLoad(); - } - - public function goToTheAdminAddCustomVariablePage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomVariablePage); - $I->waitForPageLoad(); - } - - public function goToTheAdminEncryptionKeyPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEncryptionKeyPage); - $I->waitForPageLoad(); - } - - public function goToTheAdminFindPartnersAndExtensionsPage() - { - $I = $this; - $I->amOnPage(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminFindPartnersAndExtensions); - $I->waitForPageLoad(); - } - - // Key Admin Pages - public function shouldBeOnTheAdminLoginPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLoginPage); - } - - public function shouldBeOnTheAdminDashboardPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminDashboardPage); - $I->see('Dashboard', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminForgotYourPasswordPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminForgotYourPasswordPage); - } - - // Sales - public function shouldBeOnTheAdminOrdersGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrdersGrid); - $I->see('Orders', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrderForIdPage($orderId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderByIdPage . $orderId)); - $I->see($orderId, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddOrderPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderPage); - $I->see('Create New Order', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddOrderForCustomerIdPage($customerId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderForCustomerIdPage . $customerId)); - $I->see('Create New Order', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminInvoicesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminInvoicesGrid); - $I->see('Invoices', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddInvoiceForOrderIdPage($orderId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddInvoiceForOrderIdPage . $orderId)); - $I->see('New Invoice', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminShipmentsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShipmentsGrid); - $I->see('Shipments', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminShipmentForIdPage($shipmentId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShipmentForIdPage . $shipmentId)); - $I->see('New Shipment'); - } - - public function shouldBeOnTheAdminCreditMemosGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreditMemosGrid); - $I->see('Credit Memos', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCreditMemoForIdPage($creditMemoId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreditMemoForIdPage . $creditMemoId)); - $I->see('View Memo', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBillingAgreementsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBillingAgreementsGrid); - $I->see('Billing Agreements', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTransactionsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTransactionsGrid); - $I->see('Transactions', self::$adminPageTitle); - } - - // Products - public function shouldBeOnTheAdminCatalogGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogGrid); - $I->see('Catalog', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductForIdPage($productId, $productName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductForIdPage . $productId)); - $I->see($productName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddSimpleProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSimpleProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddConfigurableProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddConfigurableProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddGroupedProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddGroupedProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddVirtualProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddVirtualProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddBundledProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddBundleProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddDownloadableProductPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddDownloadableProductPage); - $I->see('New Product', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCategoriesPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCategoriesPage); - $I->see('Default Category', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCategoryForIdPage($categoryId, $categoryName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCategoryForIdPage . $categoryId)); - $I->see($categoryName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddRootCategoryForStoreIdPage($storeId) - { - $I = $this; - $I->seeInCurrentUrl(('/admin/catalog/category/add/store/' . $storeId . '/parent/1')); - $I->see('New Category', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddSubCategoryForStoreIdPage($storeId) - { - $I = $this; - $I->seeInCurrentUrl(('/admin/catalog/category/add/store/' . $storeId . '/parent/2')); - $I->see('New Category', self::$adminPageTitle); - } - - // Customers - public function shouldBeOnTheAdminAllCustomersGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllCustomersGrid); - $I->see('Customers', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomersNowOnlineGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomersNowOnlineGrid); - $I->see('Customers Now Online', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomerForIdPage($customerId, $customerName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerForCustomerIdPage . $customerId)); - $I->see($customerName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddCustomerPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomerPage); - $I->see('New Customer', self::$adminPageTitle); - } - - // Marketing - public function shouldBeOnTheAdminCatalogPriceRuleGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogPriceRuleGrid); - $I->see('Catalog Price Rule', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCatalogPriceRuleForIdPage($catalogPriceRuleId, $catalogPriceRuleName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCatalogPriceRuleForIdPage . $catalogPriceRuleId)); - $I->see($catalogPriceRuleName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddCatalogPriceRulePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCatalogPriceRulePage); - $I->see('New Catalog Price Rule', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCartPriceRulesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCartPriceRulesGrid); - $I->see('Cart Price Rules', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCartPriceRuleForIdPage($cartPriceRuleId, $cartPriceRuleName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCartPriceRuleForIdPage . $cartPriceRuleId)); - $I->see($cartPriceRuleName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddCartPriceRulePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCartPriceRulePage); - $I->see('New Cart Price Rule', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminEmailTemplatesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEmailTemplatesGrid); - $I->see('Email Templates', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminEmailTemplateForIdPage($emailTemplateId, $templateName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEmailTemplateForIdPage . $emailTemplateId)); - $I->see($templateName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddEmailTemplatePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddEmailTemplatePage); - $I->see('New Template', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewsletterTemplateGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterTemplateGrid); - $I->see('Newsletter Templates', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewsletterTemplateByIdPage($newsletterTemplateId, $templateName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterTemplateForIdPage . $newsletterTemplateId)); - $I->see($templateName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddNewsletterTemplatePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewsletterTemplatePage); - $I->see('New Template', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewsletterQueueGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterQueueGrid); - $I->see('Newsletter Queue', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewsletterSubscribersGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterSubscribersGrid); - $I->see('Newsletter Subscribers', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminURLRewritesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminURLRewritesGrid); - $I->see('URL Rewrites', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminURLRewriteForId($urlRewriteId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminURLRewriteForIdPage . $urlRewriteId)); - $I->see('Edit URL Rewrite for a', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddURLRewritePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddURLRewritePage); - $I->see('Add New URL Rewrite', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSearchTermsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermsGrid); - $I->see('Search Terms', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSearchTermForIdPage($searchTermId, $searchQuery) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermForIdPage . $searchTermId)); - $I->see($searchQuery, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddSearchTermPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSearchTermPage); - $I->see('New Search', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSearchSynonymsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchSynonymsGrid); - $I->see('Search Synonyms', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSearchSynonymGroupByIdPage($searchSynonymId, $synonyms) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchSynonymGroupForIdPage . $searchSynonymId)); - $I->see($synonyms, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddSearchSynonymGroupPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSearchSynonymGroupPage); - $I->see('New Synonym Group', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSiteMapGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSiteMapGrid); - $I->see('Site Map', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSiteMapForIdPage($siteMapId, $fileName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSiteMapForIdPage . $siteMapId)); - $I->see($fileName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddSiteMapPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddSiteMapPage); - $I->see('New Site Map', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminReviewsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminReviewsGrid); - $I->see('Reviews', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminReviewForIdPage($reviewId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminReviewByIdPage . $reviewId)); - $I->see('Edit Review', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddReviewPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddReviewPage); - $I->see('New Review', self::$adminPageTitle); - } - - // Content - public function shouldBeOnTheAdminPagesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPagesGrid); - $I->see('Pages', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminPageForIdPage($pageId, $pageTitle) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPageForIdPage . $pageId)); - $I->see($pageTitle, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddPagePage() - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddPagePage)); - $I->see('New Page', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBlocksGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBlocksGrid); - $I->see('Blocks', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBlockForIdPage($blockId, $blockTitle) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBlockForIdPage . $blockId)); - $I->see($blockTitle, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddBlockPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddBlockPage); - $I->see('New Block', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminWidgetsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWidgetsGrid); - $I->see('Widgets', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddWidgetPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddWidgetPage); - $I->see('Widgets', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminDesignConfigurationGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminDesignConfigurationGrid); - $I->see('Design Configuration', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminThemesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminThemesGrid); - $I->see('Themes', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminThemeByIdPage($themeId, $themeTitle) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminThemeByIdPage . $themeId)); - $I->see($themeTitle); - } - - public function shouldBeOnTheAdminStoreContentScheduleGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreContentScheduleGrid); - $I->see('Store Design Schedule', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminStoreContentScheduleForIdPage($storeContentScheduleId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreContentScheduleForIdPage . $storeContentScheduleId)); - $I->see('Edit Store Design Change', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddStoreDesignChangePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddStoreDesignChangePage); - $I->see('New Store Design Change'); - } - - // Reports - public function shouldBeOnTheAdminProductsInCartGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductsInCartGrid); - $I->see('Products in Carts', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminSearchTermsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminSearchTermsReportGrid); - $I->see('Search Terms Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAbandonedCartsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAbandonedCartsGrid); - $I->see('Abandoned Carts', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewsletterProblemsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewsletterProblemsReportGrid); - $I->see('Newsletter Problems Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomerReviewsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerReviewsReportGrid); - $I->see('Customer Reviews Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductReviewsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductReviewsReportGrid); - $I->see('Product Reviews Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductReviewsForProductIdPage($productId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductReviewsForProductIdPage . $productId)); - $I->see('Reviews', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductReviewIdForProductIdPage($productReviewId, $productId) - { - $I = $this; - $I->seeInCurrentUrl(('/admin/review/product/edit/id/' . $productReviewId . '/productId/' . $productId)); - $I->see('Edit Review', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrdersReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrdersReportGrid); - $I->see('Orders Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTaxReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxReportGrid); - $I->see('Tax Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminInvoiceReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminInvoiceReportGrid); - $I->see('Invoice Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminShippingReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminShippingReportGrid); - $I->see('Shipping Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminRefundsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRefundsReportGrid); - $I->see('Refunds Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCouponsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCouponsReportGrid); - $I->see('Coupons Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminPayPalSettlementReportsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminPayPalSettlementReportsGrid); - $I->see('PayPal Settlement Reports', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBraintreeSettlementReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBraintreeSettlementReportGrid); - $I->see('Braintree Settlement Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrderTotalReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderTotalReportGrid); - $I->see('Order Total Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrderCountReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderCountReportGrid); - $I->see('Order Count Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNewAccountsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNewAccountsReportGrid); - $I->see('New Accounts Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductViewsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductViewsReportGrid); - $I->see('Product Views Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBestsellersReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBestsellersReportGrid); - $I->see('Bestsellers Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminLowStockReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLowStockReportGrid); - $I->see('Low Stock Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrderedProductsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderedProductsReportGrid); - $I->see('Ordered Products Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminDownloadsReportGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminDownloadsReportGrid); - $I->see('Downloads Report', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminRefreshStatisticsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRefreshStatisticsGrid); - $I->see('Refresh Statistics', self::$adminPageTitle); - } - - // Stores - public function shouldBeOnTheAdminAllStoresGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllStoresGrid); - $I->see('Stores', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCreateStoreViewPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateStoreViewPage); - $I->see('Stores', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCreateStorePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateStorePage); - $I->see('Stores', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCreateWebsitePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCreateWebsitePage); - $I->see('Stores'); - } - - public function shouldBeOnTheAdminWebsiteForIdPage($websiteId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWebsiteByIdPage . $websiteId)); - } - - public function shouldBeOnTheAdminStoreViewForIdPage($storeViewId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreViewByIdPage . $storeViewId)); - } - - public function shouldBeOnTheAdminStoreForIdPage($storeId) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminStoreByIdPage . $storeId)); - } - - public function shouldBeOnTheAdminConfigurationGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminConfigurationGrid); - $I->see('Configuration', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTermsAndConditionsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTermsAndConditionsGrid); - $I->see('Terms and Conditions', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTermsAndConditionForIdPage($termsAndConditionsId, $conditionName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTermsAndConditionByIdPage . $termsAndConditionsId)); - $I->see($conditionName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddNewTermsAndConditionsPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewTermsAndConditionPage); - $I->see('New Condition', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminOrderStatusGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminOrderStatusGrid); - $I->see('Order Status', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddOrderStatusPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddOrderStatusPage); - $I->see('Create New Order Status', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTaxRulesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxRulesGrid); - $I->see('Tax Rules', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTaxRuleForIdPage($taxRuleId, $taxRuleName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxRuleByIdPage . $taxRuleId)); - $I->see($taxRuleName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddTaxRulePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddTaxRulePage); - $I->see('New Tax Rule', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTaxZonesAndRatesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxZonesAndRatesGrid); - $I->see('Tax Zones and Rates', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminTaxZoneAndRateForIdPage($taxZoneAndRateId, $taxIdentifier) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminTaxZoneAndRateByIdPage . $taxZoneAndRateId)); - $I->see($taxIdentifier, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddTaxZoneAndRatePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddTaxZoneAndRatePage); - $I->see('New Tax Rate', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCurrencyRatesPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCurrencyRatesPage); - $I->see('Currency Rates', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCurrencySymbolsPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCurrencySymbolsPage); - $I->see('Currency Symbols', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductAttributesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductAttributesGrid); - $I->see('Product Attributes', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminProductAttributeForIdPage($productAttributeId, $productAttributeDefaultLabel) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminProductAttributeForIdPage . $productAttributeId)); - $I->see($productAttributeDefaultLabel, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddProductAttributePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddProductAttributePage); - $I->see('New Product Attribute', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAttributeSetsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAttributeSetsGrid); - $I->see('Attribute Sets', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAttributeSetByIdPage($attributeSetId, $attributeSetName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAttributeSetByIdPage . $attributeSetId)); - $I->see($attributeSetName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddAttributeSetPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddAttributeSetPage); - $I->see('New Attribute Set', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminRatingsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRatingsGrid); - $I->see('Ratings', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminRatingForIdPage($ratingId, $ratingDefaultValue) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminRatingForIdPage . $ratingId)); - $I->see($ratingDefaultValue, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddRatingPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddRatingPage); - $I->see('New Rating', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomerGroupsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerGroupsGrid); - $I->see('Customer Groups', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomerGroupForIdPage($customerGroupId, $customerGroupName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomerGroupByIdPage . $customerGroupId)); - $I->see($customerGroupName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddCustomerGroupPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomerGroupPage); - $I->see('New Customer Group', self::$adminPageTitle); - } - - // System - public function shouldBeOnTheAdminImportPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportPage); - $I->see('Import', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminExportPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminExportPage); - $I->see('Export', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminImportAndExportTaxRatesPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportAndExportTaxRatesPage); - $I->see('Import and Export Tax Rates', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminImportHistoryGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminImportHistoryGrid); - $I->see('Import History', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminIntegrationsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIntegrationsGrid); - $I->see('Integrations', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminIntegrationForIdPage($integrationId, $integrationName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIntegrationByIdPage . $integrationId)); - $I->see('Edit', self::$adminPageTitle); - $I->see($integrationName, self::$adminPageTitle); - $I->see('Integration', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddIntegrationPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddIntegrationPage); - $I->see('New Integration', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCacheManagementGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCacheManagementGrid); - $I->see('Cache Management', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminBackupsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminBackupsGrid); - $I->see('Backups', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminIndexManagementGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminIndexManagementGrid); - $I->see('Index Management', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminWebSetupWizardPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminWebSetupWizardPage); - $I->see('Setup Wizard', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAllUsersGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAllUsersGrid); - $I->see('Users', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminUserForIdPage($userId, $userFirstAndLastName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserByIdPage . $userId)); - $I->see($userFirstAndLastName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddUserPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddNewUserPage); - $I->see('New User', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminLockedUsersGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminLockedUsersGrid); - $I->see('Locked Users', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminUserRolesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserRolesGrid); - $I->see('Roles', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminUserRoleForIdPage($userRoleId, $userRoleName) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminUserRoleByIdPage . $userRoleId)); - $I->see($userRoleName, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddUserRolePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddUserRolePage); - $I->see('New Role', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminNotificationsGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminNotificationsGrid); - $I->see('Notifications', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomVariablesGrid() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomVariablesGrid); - $I->see('Custom Variables', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminCustomVariableForId($customVariableId, $customVariableCode) - { - $I = $this; - $I->seeInCurrentUrl((\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminCustomVariableByIdPage . $customVariableId)); - $I->see($customVariableCode, self::$adminPageTitle); - } - - public function shouldBeOnTheAdminAddCustomVariablePage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminAddCustomVariablePage); - $I->see('New Custom Variable', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminEncryptionKeyPage() - { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminEncryptionKeyPage); - $I->see('Encryption Key', self::$adminPageTitle); - } - - public function shouldBeOnTheAdminFindPartnersAndExtensionsPage() { - $I = $this; - $I->seeInCurrentUrl(\Magento\FunctionalTestingFramework\Helper\AdminUrlList::$adminFindPartnersAndExtensions); - $I->see('Magento Marketplace', self::$adminPageTitle); - } -} diff --git a/src/Magento/FunctionalTestingFramework/Suite/Config/SuiteDom.php b/src/Magento/FunctionalTestingFramework/Suite/Config/SuiteDom.php new file mode 100644 index 000000000..c06c62024 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Suite/Config/SuiteDom.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Suite\Config; + +use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; +use Magento\FunctionalTestingFramework\Util\Validation\SingleNodePerFileValidationUtil; + +/** + * MFTF suite.xml configuration XML DOM utility + * @package Magento\FunctionalTestingFramework\Suite\Config + */ +class SuiteDom extends \Magento\FunctionalTestingFramework\Config\MftfDom +{ + const SUITE_META_FILENAME_ATTRIBUTE = "filename"; + + /** SingleNodePerFileValidationUtil + * + * @var SingleNodePerFileValidationUtil + */ + private $singleNodePerFileValidationUtil; + + /** + * Entity Dom constructor. + * @param string $xml + * @param string $filename + * @param ExceptionCollector $exceptionCollector + * @param array $idAttributes + * @param string $typeAttributeName + * @param string $schemaFile + * @param string $errorFormat + */ + public function __construct( + $xml, + $filename, + $exceptionCollector, + array $idAttributes = [], + $typeAttributeName = null, + $schemaFile = null, + $errorFormat = self::ERROR_FORMAT_DEFAULT + ) { + $this->singleNodePerFileValidationUtil = new SingleNodePerFileValidationUtil($exceptionCollector); + parent::__construct( + $xml, + $filename, + $exceptionCollector, + $idAttributes, + $typeAttributeName, + $schemaFile, + $errorFormat + ); + } + + /** + * Takes a dom element from xml and appends the filename based on location + * + * @param string $xml + * @param string|null $filename + * @return \DOMDocument + */ + public function initDom($xml, $filename = null) + { + $dom = parent::initDom($xml, $filename); + + if ($dom->getElementsByTagName('suites')->length > 0) { + // Validate single suite node per file + $this->singleNodePerFileValidationUtil->validateSingleNodeForTag( + $dom, + 'suite', + $filename + ); + if ($dom->getElementsByTagName('suite')->length > 0) { + /** @var \DOMElement $suiteNode */ + $suiteNode = $dom->getElementsByTagName('suite')[0]; + $suiteNode->setAttribute(self::SUITE_META_FILENAME_ATTRIBUTE, $filename); + } + } + + return $dom; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php b/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php index 415d884b6..67930f09a 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php @@ -131,14 +131,18 @@ private function buildHookMustacheArray($hookObj) { $actions = []; $mustacheHookArray['actions'][] = ['webDriverInit' => true]; + $mustacheHookArray['helpers'] = []; foreach ($hookObj->getActions() as $action) { /** @var ActionObject $action */ $index = count($actions); + if ($action->getType() === ActionObject::ACTION_TYPE_HELPER) { + $mustacheHookArray['helpers'][] = $action->getCustomActionAttributes()['class']; + } //deleteData contains either url or createDataKey, if it contains the former it needs special formatting if ($action->getType() !== "createData" && !array_key_exists(TestGenerator::REQUIRED_ENTITY_REFERENCE, $action->getCustomActionAttributes())) { - $actions = $this->buildWebDriverActionsMustacheArray($action, $actions, $index); + $actions = $this->buildWebDriverActionsMustacheArray($action, $actions); continue; } diff --git a/src/Magento/FunctionalTestingFramework/Suite/Objects/SuiteObject.php b/src/Magento/FunctionalTestingFramework/Suite/Objects/SuiteObject.php index 7168d9556..64820cf09 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/Objects/SuiteObject.php +++ b/src/Magento/FunctionalTestingFramework/Suite/Objects/SuiteObject.php @@ -44,19 +44,28 @@ class SuiteObject */ private $hooks; + /** + * Filename of where the suite came from + * + * @var string + */ + private $filename; + /** * SuiteObject constructor. * @param string $name * @param TestObject[] $includeTests * @param TestObject[] $excludeTests * @param TestHookObject[] $hooks + * @param string $filename */ - public function __construct($name, $includeTests, $excludeTests, $hooks) + public function __construct($name, $includeTests, $excludeTests, $hooks, $filename = null) { $this->name = $name; $this->includeTests = $includeTests; $this->excludeTests = $excludeTests; $this->hooks = $hooks; + $this->filename = $filename; } /** @@ -148,4 +157,14 @@ public function getAfterHook() { return $this->hooks['after'] ?? null; } + + /** + * Getter for the Suite Filename + * + * @return string + */ + public function getFilename() + { + return $this->filename; + } } diff --git a/src/Magento/FunctionalTestingFramework/Suite/Util/SuiteObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Suite/Util/SuiteObjectExtractor.php index 2e4d7f9dd..90fbddd6e 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/Util/SuiteObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Suite/Util/SuiteObjectExtractor.php @@ -13,8 +13,11 @@ use Magento\FunctionalTestingFramework\Test\Util\BaseObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\TestHookObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; +use Magento\FunctionalTestingFramework\Util\ModuleResolver; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; +use Symfony\Component\Finder\Finder; +use Magento\FunctionalTestingFramework\Util\ModulePathExtractor; class SuiteObjectExtractor extends BaseObjectExtractor { @@ -23,7 +26,6 @@ class SuiteObjectExtractor extends BaseObjectExtractor const INCLUDE_TAG_NAME = 'include'; const EXCLUDE_TAG_NAME = 'exclude'; const MODULE_TAG_NAME = 'module'; - const MODULE_TAG_FILE_ATTRIBUTE = 'file'; const TEST_TAG_NAME = 'test'; const GROUP_TAG_NAME = 'group'; @@ -181,7 +183,6 @@ private function parseObjectHooks($parsedSuite) */ private function isSuiteEmpty($suiteHooks, $includeTests, $excludeTests) { - $noHooks = count($suiteHooks) == 0 || ( empty($suiteHooks['before']->getActions()) && @@ -220,10 +221,10 @@ private function extractTestObjectsFromSuiteRef($suiteReferences) TestObjectHandler::getInstance()->getTestsByGroup($suiteRefData[self::NAME]); break; case self::MODULE_TAG_NAME: - $testObjectList = array_merge($testObjectList, $this->extractModuleAndFiles( - $suiteRefData[self::NAME], - $suiteRefData[self::MODULE_TAG_FILE_ATTRIBUTE] ?? null - )); + $testObjectList = array_merge( + $testObjectList, + $this->getTestsByModuleName($suiteRefData[self::NAME]) + ); break; } } @@ -232,83 +233,24 @@ private function extractTestObjectsFromSuiteRef($suiteReferences) } /** - * Takes an array of modules/files and resolves to an array of test objects. + * Return all test objects for a module * * @param string $moduleName - * @param string $moduleFilePath - * @return array - * @throws \Exception - */ - private function extractModuleAndFiles($moduleName, $moduleFilePath) - { - if (empty($moduleFilePath)) { - return $this->resolveModulePathTestNames($moduleName); - } - - return $this->resolveFilePathTestNames($moduleFilePath, $moduleName); - } - - /** - * Takes a filepath (and optionally a module name) and resolves to a test object. - * - * @param string $filename - * @param null $moduleName * @return TestObject[] * @throws Exception */ - private function resolveFilePathTestNames($filename, $moduleName = null) + private function getTestsByModuleName($moduleName) { - $filepath = $filename; - if (!strstr($filepath, DIRECTORY_SEPARATOR)) { - $filepath = FilePathFormatter::format(TESTS_MODULE_PATH) . - $moduleName . - DIRECTORY_SEPARATOR . - 'Test' . - DIRECTORY_SEPARATOR . - $filename; - } - - if (!file_exists($filepath)) { - throw new Exception("Could not find file ${filename}"); - } - $testObjects = []; - $xml = simplexml_load_file($filepath); - for ($i = 0; $i < $xml->count(); $i++) { - $testName = (string)$xml->test[$i]->attributes()->name; - $testObjects[$testName] = TestObjectHandler::getInstance()->getObject($testName); - } - - return $testObjects; - } - - /** - * Takes a single module name and resolves to an array of tests contained within specified module. - * - * @param string $moduleName - * @return array - * @throws \Exception - */ - private function resolveModulePathTestNames($moduleName) - { - $testObjects = []; - $xmlFiles = glob( - FilePathFormatter::format(TESTS_MODULE_PATH) . - $moduleName . - DIRECTORY_SEPARATOR . - 'Test' . - DIRECTORY_SEPARATOR . - '*.xml' - ); - - foreach ($xmlFiles as $xmlFile) { - $testObjs = $this->resolveFilePathTestNames($xmlFile); - - foreach ($testObjs as $testObj) { - $testObjects[$testObj->getName()] = $testObj; + $pathExtractor = new ModulePathExtractor(); + $allTestObjects = TestObjectHandler::getInstance()->getAllObjects(); + foreach ($allTestObjects as $testName => $testObject) { + /** @var TestObject $testObject */ + $filename = $testObject->getFilename(); + if ($pathExtractor->extractModuleName($filename) === $moduleName) { + $testObjects[$testName] = $testObject; } } - return $testObjects; } } diff --git a/src/Magento/FunctionalTestingFramework/Suite/etc/mergedSuiteSchema.xsd b/src/Magento/FunctionalTestingFramework/Suite/etc/mergedSuiteSchema.xsd new file mode 100644 index 000000000..fee742df5 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Suite/etc/mergedSuiteSchema.xsd @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:include schemaLocation="../../Test/etc/testSchema.xsd"/> + <xs:element name="suites" type="suiteConfigType"/> + <xs:complexType name="groupSuiteOptionType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="name" use="required"/> + <xs:attribute type="xs:boolean" name="remove" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="testSuiteOptionType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="name" use="required"/> + <xs:attribute type="xs:boolean" name="remove" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="moduleSuiteOptionType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="name" use="optional"/> + <xs:attribute type="xs:boolean" name="remove" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="includeType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="groupSuiteOptionType" name="group" minOccurs="0"/> + <xs:element type="testSuiteOptionType" name="test" minOccurs="0"/> + <xs:element type="moduleSuiteOptionType" name="module" minOccurs="0"/> + </xs:choice> + </xs:complexType> + <xs:complexType name="excludeType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="groupSuiteOptionType" name="group" minOccurs="0"/> + <xs:element type="testSuiteOptionType" name="test" minOccurs="0"/> + <xs:element type="moduleSuiteOptionType" name="module" minOccurs="0"/> + </xs:choice> + </xs:complexType> + <xs:complexType name="suiteType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="includeType" name="include" maxOccurs="1"/> + <xs:element type="excludeType" name="exclude" maxOccurs="1"/> + <xs:element type="hookType" name="before" maxOccurs="1"/> + <xs:element type="hookType" name="after" maxOccurs="1"/> + </xs:choice> + <xs:attribute type="xs:string" name="name"/> + <xs:attribute type="xs:string" name="deprecated"> + <xs:annotation> + <xs:documentation> + Message and flag which shows that entity is deprecated. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="filename"/> + </xs:complexType> + <xs:complexType name="suiteConfigType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="suiteType" name="suite"/> + </xs:choice> + </xs:complexType> +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd b/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd index b36e35517..8dc9d573d 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd @@ -7,71 +7,11 @@ --> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:include schemaLocation="../../Test/etc/testSchema.xsd"/> - <xs:element name="suites" type="suiteConfigType"/> - <xs:complexType name="groupSuiteOptionType"> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute type="xs:string" name="name" use="required"/> - <xs:attribute type="xs:boolean" name="remove" use="optional"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="testSuiteOptionType"> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute type="xs:string" name="name" use="required"/> - <xs:attribute type="xs:boolean" name="remove" use="optional"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="moduleSuiteOptionType"> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute type="xs:string" name="name" use="optional"/> - <xs:attribute type="xs:string" name="file" use="optional"/> - <xs:attribute type="xs:boolean" name="remove" use="optional"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="includeType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element type="groupSuiteOptionType" name="group" minOccurs="0"/> - <xs:element type="testSuiteOptionType" name="test" minOccurs="0"/> - <xs:element type="moduleSuiteOptionType" name="module" minOccurs="0"/> - </xs:choice> - </xs:complexType> - <xs:complexType name="excludeType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element type="groupSuiteOptionType" name="group" minOccurs="0"/> - <xs:element type="testSuiteOptionType" name="test" minOccurs="0"/> - <xs:element type="moduleSuiteOptionType" name="module" minOccurs="0"/> - </xs:choice> - </xs:complexType> - <!--<xs:complexType name="suiteHookType">--> - <!--<xs:choice minOccurs="0" maxOccurs="unbounded">--> - <!--<xs:group ref="dataOperationTags" maxOccurs="unbounded" minOccurs="0"/>--> - <!--</xs:choice>--> - <!--</xs:complexType>--> - <xs:complexType name="suiteType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element type="includeType" name="include" maxOccurs="1"/> - <xs:element type="excludeType" name="exclude" maxOccurs="1"/> - <xs:element type="hookType" name="before" maxOccurs="1"/> - <xs:element type="hookType" name="after" maxOccurs="1"/> - </xs:choice> - <xs:attribute type="xs:string" name="name"/> - <xs:attribute type="xs:string" name="deprecated"> - <xs:annotation> - <xs:documentation> - Message and flag which shows that entity is deprecated. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:complexType> - <xs:complexType name="suiteConfigType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element type="suiteType" name="suite"/> - </xs:choice> - </xs:complexType> + <xs:redefine schemaLocation="mergedSuiteSchema.xsd"> + <xs:complexType name="suiteConfigType"> + <xs:choice minOccurs="0" maxOccurs="1"> + <xs:element type="suiteType" name="suite"/> + </xs:choice> + </xs:complexType> + </xs:redefine> </xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache b/src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache index b98405c03..a9fdcd6df 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache +++ b/src/Magento/FunctionalTestingFramework/Suite/views/SuiteClass.mustache @@ -2,8 +2,10 @@ namespace Group; +use Facebook\WebDriver\Remote\RemoteWebDriver; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\Module\MagentoWebDriver; /** * Group class is Codeception Extension which is allowed to handle to all internal events. @@ -20,12 +22,25 @@ class {{suiteName}} extends \Codeception\GroupObject private $testCount = {{testCount}}; private $preconditionFailure = null; private $currentTestRun = 0; + {{#helpers}} + /** + * @var \Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer + */ + private $helperContainer; + {{/helpers}} private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of {{suiteName}} suite %s block ********/\n"; private static $HOOK_EXECUTION_END = "\n/******** Execution of {{suiteName}} suite %s block complete ********/\n"; {{#before}} public function _before(\Codeception\Event\TestEvent $e) { + {{#helpers}} + /** @var \Magento\FunctionalTestingFramework\Helper\HelperContainer $helperContainer */ + $this->helperContainer = $this->getModule('\Magento\FunctionalTestingFramework\Helper\HelperContainer'); + {{/helpers}} + {{#helpers}} + $this->helperContainer->create("{{ . }}"); + {{/helpers}} // increment test count per execution $this->currentTestRun++; $this->executePreConditions(); @@ -42,18 +57,20 @@ class {{suiteName}} extends \Codeception\GroupObject if ($this->currentTestRun == 1) { print sprintf(self::$HOOK_EXECUTION_INIT, "before"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { {{> testActions}} - - // reset configuration and close session - $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig(); - $webDriver->webDriver->close(); - $webDriver->webDriver = null; - } catch (\Exception $exception) { $this->preconditionFailure = $exception->getMessage(); } + // reset configuration and close session + $webDriver->_resetConfig(); + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + print sprintf(self::$HOOK_EXECUTION_END, "before"); } } @@ -71,6 +88,9 @@ class {{suiteName}} extends \Codeception\GroupObject if ($this->currentTestRun == $this->testCount) { print sprintf(self::$HOOK_EXECUTION_INIT, "after"); + /** @var MagentoWebDriver $webDriver */ + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + try { // Find out if Test in Suite failed, will cause potential failures in suite after $cest = $e->getTest(); @@ -99,8 +119,38 @@ class {{suiteName}} extends \Codeception\GroupObject } PersistedObjectHandler::getInstance()->clearSuiteObjects(); + + $this->closeSession($webDriver); + print sprintf(self::$HOOK_EXECUTION_END, "after"); } } {{/after}} + + /** + * Close session method closes current session. + * If config 'close_all_sessions' is set to 'true' all sessions will be closed. + * + * @param MagentoWebDriver $webDriver + * return void + */ + private function closeSession(MagentoWebDriver $webDriver): void + { + $webDriverConfig = $webDriver->_getConfig(); + $webDriver->_closeSession(); + if (isset($webDriverConfig['close_all_sessions']) && $webDriverConfig['close_all_sessions'] === "true") { + $wdHost = sprintf( + '%s://%s:%s%s', + $webDriverConfig['protocol'], + $webDriverConfig['host'], + $webDriverConfig['port'], + $webDriverConfig['path'] + ); + $availableSessions = RemoteWebDriver::getAllSessions($wdHost); + foreach ($availableSessions as $session) { + $remoteWebDriver = RemoteWebDriver::createBySessionID($session['id'], $wdHost); + $remoteWebDriver->quit(); + } + } + } } diff --git a/src/Magento/FunctionalTestingFramework/Suite/views/partials/testActions.mustache b/src/Magento/FunctionalTestingFramework/Suite/views/partials/testActions.mustache index 2ed5e8d5e..73079f169 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/views/partials/testActions.mustache +++ b/src/Magento/FunctionalTestingFramework/Suite/views/partials/testActions.mustache @@ -1,15 +1,10 @@ {{#actions}} {{#webDriverInit}} -$webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - -// close any open sessions if ($webDriver->webDriver != null) { - $webDriver->webDriver->close(); - $webDriver->webDriver = null; + $webDriver->_restart(); +} else { + $webDriver->_initializeSession(); } - -// initialize the webdriver session -$webDriver->_initializeSession(); {{/webDriverInit}} {{#action}} {{{action}}} diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php b/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php index 7eec3286d..a99432e40 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/ActionGroupDom.php @@ -31,15 +31,23 @@ public function initDom($xml, $filename = null) if ($this->checkFilenameSuffix($filename, self::ACTION_GROUP_FILE_NAME_ENDING)) { $actionGroupsNode = $dom->getElementsByTagName('actionGroups')[0]; - $actionGroupNodes = $dom->getElementsByTagName('actionGroup'); $this->testsValidationUtil->validateChildUniqueness( $actionGroupsNode, $filename, null ); - foreach ($actionGroupNodes as $actionGroupNode) { + + // Validate single action group node per file + $this->singleNodePerFileValidationUtil->validateSingleNodeForTag( + $dom, + 'actionGroup', + $filename + ); + + if ($dom->getElementsByTagName('actionGroup')->length > 0) { /** @var \DOMElement $actionGroupNode */ + $actionGroupNode = $dom->getElementsByTagName('actionGroup')[0]; $actionGroupNode->setAttribute(self::TEST_META_FILENAME_ATTRIBUTE, $filename); $this->actionsValidationUtil->validateChildUniqueness( $actionGroupNode, diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php b/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php index 12127ef32..7ded754be 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/Dom.php @@ -12,6 +12,7 @@ use Magento\FunctionalTestingFramework\Config\Dom\NodePathMatcher; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Util\Validation\DuplicateNodeValidationUtil; +use Magento\FunctionalTestingFramework\Util\Validation\SingleNodePerFileValidationUtil; /** * MFTF test.xml configuration XML DOM utility @@ -38,6 +39,12 @@ class Dom extends \Magento\FunctionalTestingFramework\Config\MftfDom */ protected $testsValidationUtil; + /** + * SingleNodePerFileValidationUtil + * @var SingleNodePerFileValidationUtil + */ + protected $singleNodePerFileValidationUtil; + /** * ExceptionCollector * @var ExceptionCollector @@ -65,6 +72,7 @@ public function __construct( ) { $this->actionsValidationUtil = new DuplicateNodeValidationUtil('stepKey', $exceptionCollector); $this->testsValidationUtil = new DuplicateNodeValidationUtil('name', $exceptionCollector); + $this->singleNodePerFileValidationUtil = new SingleNodePerFileValidationUtil($exceptionCollector); $this->exceptionCollector = $exceptionCollector; parent::__construct( $xml, @@ -91,14 +99,21 @@ public function initDom($xml, $filename = null) // Cannot rely on filename to ensure this file is a Test.xml if ($dom->getElementsByTagName('tests')->length > 0) { $testsNode = $dom->getElementsByTagName('tests')[0]; - $testNodes = $dom->getElementsByTagName('test'); $this->testsValidationUtil->validateChildUniqueness( $testsNode, $filename, null ); - foreach ($testNodes as $testNode) { + // Validate single test node per file + $this->singleNodePerFileValidationUtil->validateSingleNodeForTag( + $dom, + 'test', + $filename + ); + + if ($dom->getElementsByTagName('test')->length > 0) { /** @var \DOMElement $testNode */ + $testNode = $dom->getElementsByTagName('test')[0]; $testNode->setAttribute(self::TEST_META_FILENAME_ATTRIBUTE, $filename); if ($testNode->getAttribute(self::TEST_MERGE_POINTER_AFTER) !== "") { $this->appendMergePointerToActions( diff --git a/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php b/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php index 131ae0a26..5a87a32f6 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php @@ -6,13 +6,14 @@ namespace Magento\FunctionalTestingFramework\Test\Handlers; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; -use Magento\FunctionalTestingFramework\Test\Objects\TestObject; use Magento\FunctionalTestingFramework\Test\Parsers\ActionGroupDataParser; use Magento\FunctionalTestingFramework\Test\Util\ActionGroupObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\ObjectExtensionUtil; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; /** * Class ActionGroupObjectHandler @@ -22,6 +23,7 @@ class ActionGroupObjectHandler implements ObjectHandlerInterface const BEFORE_AFTER_ERROR_MSG = "Merge Error - Steps cannot have both before and after attributes.\tTestStep='%s'"; const ACTION_GROUP_ROOT = 'actionGroups'; const ACTION_GROUP = 'actionGroup'; + const ACTION_GROUP_FILENAME_ATTRIBUTE = 'filename'; /** * Single instance of class var @@ -48,6 +50,7 @@ class ActionGroupObjectHandler implements ObjectHandlerInterface * Singleton getter for instance of ActionGroupObjectHandler * * @return ActionGroupObjectHandler + * @throws XmlException */ public static function getInstance(): ActionGroupObjectHandler { @@ -60,6 +63,7 @@ public static function getInstance(): ActionGroupObjectHandler /** * ActionGroupObjectHandler constructor. + * @throws XmlException */ private function __construct() { @@ -72,6 +76,8 @@ private function __construct() * * @param string $actionGroupName * @return ActionGroupObject + * @throws TestFrameworkException + * @throws XmlException */ public function getObject($actionGroupName) { @@ -87,6 +93,8 @@ public function getObject($actionGroupName) * Function to return all objects for which the handler is responsible * * @return array + * @throws TestFrameworkException + * @throws XmlException */ public function getAllObjects(): array { @@ -100,6 +108,7 @@ public function getAllObjects(): array * Method which populates field array with objects from parsed action_group.xml * * @return void + * @throws XmlException * @SuppressWarnings(PHPMD.UnusedPrivateMethod) */ private function initActionGroups() @@ -110,7 +119,17 @@ private function initActionGroups() $actionGroupObjectExtractor = new ActionGroupObjectExtractor(); $neededActionGroup = $parsedActionGroups[ActionGroupObjectHandler::ACTION_GROUP_ROOT]; + $actionGroupNameValidator = new NameValidationUtil(); foreach ($neededActionGroup as $actionGroupName => $actionGroupData) { + if (!in_array($actionGroupName, ["nodeName", "xsi:noNamespaceSchemaLocation"])) { + $filename = $actionGroupData[ActionGroupObjectHandler::ACTION_GROUP_FILENAME_ATTRIBUTE]; + $actionGroupNameValidator->validatePascalCase( + $actionGroupName, + NameValidationUtil::ACTION_GROUP_NAME, + $filename + ); + } + if (!is_array($actionGroupData)) { continue; } @@ -118,6 +137,7 @@ private function initActionGroups() $this->actionGroups[$actionGroupName] = $actionGroupObjectExtractor->extractActionGroup($actionGroupData); } + $actionGroupNameValidator->summarize(NameValidationUtil::ACTION_GROUP_NAME); } /** @@ -125,6 +145,7 @@ private function initActionGroups() * * @param ActionGroupObject $actionGroupObject * @return ActionGroupObject + * @throws XmlException * @throws TestFrameworkException */ private function extendActionGroup($actionGroupObject): ActionGroupObject diff --git a/src/Magento/FunctionalTestingFramework/Test/Handlers/TestObjectHandler.php b/src/Magento/FunctionalTestingFramework/Test/Handlers/TestObjectHandler.php index d5ed43806..6ad9762af 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Handlers/TestObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Test/Handlers/TestObjectHandler.php @@ -15,9 +15,8 @@ use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser; use Magento\FunctionalTestingFramework\Test\Util\ObjectExtensionUtil; use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; -use Magento\FunctionalTestingFramework\Test\Util\AnnotationExtractor; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; -use PHP_CodeSniffer\Tokenizers\PHP; +use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; /** * Class TestObjectHandler @@ -25,6 +24,7 @@ class TestObjectHandler implements ObjectHandlerInterface { const XML_ROOT = 'tests'; + const TEST_FILENAME_ATTRIBUTE = 'filename'; /** * Test Object Handler @@ -53,11 +53,11 @@ class TestObjectHandler implements ObjectHandlerInterface * @return TestObjectHandler * @throws XmlException */ - public static function getInstance() + public static function getInstance($validateAnnotations = true) { if (!self::$testObjectHandler) { self::$testObjectHandler = new TestObjectHandler(); - self::$testObjectHandler->initTestData(); + self::$testObjectHandler->initTestData($validateAnnotations); } return self::$testObjectHandler; @@ -129,7 +129,7 @@ public function getTestsByGroup($groupName) * @SuppressWarnings(PHPMD.UnusedPrivateMethod) * @throws XmlException */ - private function initTestData() + private function initTestData($validateAnnotations = true) { $testDataParser = ObjectManagerFactory::getObjectManager()->create(TestDataParser::class); $parsedTestArray = $testDataParser->readTestData(); @@ -142,20 +142,25 @@ private function initTestData() } $exceptionCollector = new ExceptionCollector(); + $testNameValidator = new NameValidationUtil(); foreach ($parsedTestArray as $testName => $testData) { + $filename = $testData[TestObjectHandler::TEST_FILENAME_ATTRIBUTE]; + $testNameValidator->validatePascalCase($testName, NameValidationUtil::TEST_NAME, $filename); if (!is_array($testData)) { continue; } try { - $this->tests[$testName] = $testObjectExtractor->extractTestData($testData); + $this->tests[$testName] = $testObjectExtractor->extractTestData($testData, $validateAnnotations); } catch (XmlException $exception) { $exceptionCollector->addError(self::class, $exception->getMessage()); } } $exceptionCollector->throwException(); - - $testObjectExtractor->getAnnotationExtractor()->validateStoryTitleUniqueness(); - $testObjectExtractor->getAnnotationExtractor()->validateTestCaseIdTitleUniqueness(); + $testNameValidator->summarize(NameValidationUtil::TEST_NAME); + if ($validateAnnotations) { + $testObjectExtractor->getAnnotationExtractor()->validateStoryTitleUniqueness(); + $testObjectExtractor->getAnnotationExtractor()->validateTestCaseIdTitleUniqueness(); + } } /** diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index dc1b158e1..74aa414a8 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -8,7 +8,6 @@ use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; -use Magento\FunctionalTestingFramework\Test\Util\ObjectExtension; /** * Class ActionGroupObject @@ -25,7 +24,7 @@ class ActionGroupObject "executeJS", "magentoCLI", "generateDate", - "formatMoney", + "formatCurrency", "deleteData", "getData", "updateData", @@ -36,7 +35,8 @@ class ActionGroupObject "grabMultiple", "grabPageSource", "grabTextFrom", - "grabValueFrom" + "grabValueFrom", + "getOTP" ]; /** @@ -211,6 +211,9 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) foreach ($this->parsedActions as $action) { $replacementStepKeys[$action->getStepKey()] = $action->getStepKey() . ucfirst($actionReferenceKey); $varAttributes = array_intersect($this->varAttributes, array_keys($action->getCustomActionAttributes())); + if ($action->getType() === ActionObject::ACTION_TYPE_HELPER) { + $varAttributes = array_keys($action->getCustomActionAttributes()); + } // replace createDataKey attributes inside the action group $resolvedActionAttributes = $this->replaceCreateDataKeys($action, $replacementStepKeys); diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index 45b5db69d..648471c7a 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -56,13 +56,13 @@ class ActionObject "command", "html" ]; - const OLD_ASSERTION_ATTRIBUTES = ["expected", "expectedType", "actual", "actualType"]; const ASSERTION_ATTRIBUTES = ["expectedResult" => "expected", "actualResult" => "actual"]; const ASSERTION_TYPE_ATTRIBUTE = "type"; const ASSERTION_VALUE_ATTRIBUTE = "value"; + const ASSERTION_ELEMENT_ATTRIBUTES = ["selector", "attribute"]; const DELETE_DATA_MUTUAL_EXCLUSIVE_ATTRIBUTES = ["url", "createDataKey"]; const EXTERNAL_URL_AREA_INVALID_ACTIONS = ['amOnPage']; - const FUNCTION_CLOSURE_ACTIONS = ['waitForElementChange', 'performOn', 'executeInSelenium']; + const FUNCTION_CLOSURE_ACTIONS = ['waitForElementChange']; const COMMAND_ACTION_ATTRIBUTES = ['magentoCLI', 'magentoCLISecret']; const MERGE_ACTION_ORDER_AFTER = 'after'; const MERGE_ACTION_ORDER_BEFORE = 'before'; @@ -75,6 +75,7 @@ class ActionObject const DEFAULT_COMMAND_WAIT_TIMEOUT = 60; const ACTION_ATTRIBUTE_USERINPUT = 'userInput'; const ACTION_TYPE_COMMENT = 'comment'; + const ACTION_TYPE_HELPER = 'helper'; const INVISIBLE_STEP_ACTIONS = ['retrieveEntityField', 'getSecret']; /** @@ -282,6 +283,7 @@ public function setTimeout($timeout) public function resolveReferences() { if (empty($this->resolvedCustomAttributes)) { + $this->resolveHelperReferences(); $this->trimAssertionAttributes(); $this->resolveSelectorReferenceAndTimeout(); $this->resolveUrlReference(); @@ -294,33 +296,73 @@ public function resolveReferences() } /** - * Flattens expectedResult/actualResults/array nested elements, if necessary. - * e.g. expectedResults[] -> ["expectedType" => "string", "expected" => "value"] - * Warns user if they are using old Assertion syntax. + * Resolves references for helpers. * + * @throws TestReferenceException * @return void */ - public function trimAssertionAttributes() + private function resolveHelperReferences() { - $actionAttributeKeys = array_keys($this->actionAttributes); + if ($this->getType() !== 'helper') { + return; + } + $isResolved = false; - /** MQE-683 DEPRECATE OLD METHOD HERE - * Checks if action has any of the old, single line attributes - * Throws a warning and returns, assuming old syntax is used. - */ - $oldAttributes = array_intersect($actionAttributeKeys, ActionObject::OLD_ASSERTION_ATTRIBUTES); - if (!empty($oldAttributes)) { - $appConfig = MftfApplicationConfig::getConfig(); - if ($appConfig->getPhase() == MftfApplicationConfig::GENERATION_PHASE && $appConfig->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation( - "use of one line Assertion actions will be deprecated in MFTF 3.0.0, please use nested syntax", - ["action" => $this->type, "stepKey" => $this->stepKey], - true + try { + foreach ($this->actionAttributes as $attrKey => $attrValue) { + $this->actionAttributes[$attrKey] = $this->findAndReplaceReferences( + SectionObjectHandler::getInstance(), + $attrValue ); } - return; + $isResolved = true; + } catch (\Exception $e) { + // catching exception to allow other entity type resolution to proceed + } + + try { + foreach ($this->actionAttributes as $attrKey => $attrValue) { + $this->actionAttributes[$attrKey] = $this->findAndReplaceReferences( + PageObjectHandler::getInstance(), + $attrValue + ); + } + $isResolved = true; + } catch (\Exception $e) { + // catching exception to allow other entity type resolution to proceed } + try { + foreach ($this->actionAttributes as $attrKey => $attrValue) { + $this->actionAttributes[$attrKey] = $this->findAndReplaceReferences( + DataObjectHandler::getInstance(), + $attrValue + ); + } + $isResolved = true; + } catch (\Exception $e) { + // catching exception to allow other entity type resolution to proceed + } + + if ($isResolved !== true) { + throw new TestReferenceException( + "Could not resolve entity reference \"{$attrValue}\" " + . "in Action with stepKey \"{$this->getStepKey()}\"", + ["input" => $attrValue, "stepKey" => $this->getStepKey()] + ); + } + } + + /** + * Flattens expectedResult/actualResults/array nested elements, if necessary. + * e.g. expectedResults[] -> ["expectedType" => "string", "expected" => "value"] + * Warns user if they are using old Assertion syntax. + * + * @return void + */ + public function trimAssertionAttributes() + { + $actionAttributeKeys = array_keys($this->actionAttributes); $relevantKeys = array_keys(ActionObject::ASSERTION_ATTRIBUTES); $relevantAssertionAttributes = array_intersect($actionAttributeKeys, $relevantKeys); @@ -328,47 +370,25 @@ public function trimAssertionAttributes() return; } - $this->validateAssertionSchema($relevantAssertionAttributes); - // Flatten nested Elements's type and value into key=>value entries + // Also, add selector/value attributes if they are present in nested Element foreach ($this->actionAttributes as $key => $subAttributes) { + foreach (self::ASSERTION_ELEMENT_ATTRIBUTES as $ATTRIBUTE) { + if (isset($subAttributes[$ATTRIBUTE])) { + $this->actionAttributes[$ATTRIBUTE] = $subAttributes[$ATTRIBUTE]; + } + } if (in_array($key, $relevantKeys)) { $prefix = ActionObject::ASSERTION_ATTRIBUTES[$key]; $this->actionAttributes[$prefix . ucfirst(ActionObject::ASSERTION_TYPE_ATTRIBUTE)] = - $subAttributes[ActionObject::ASSERTION_TYPE_ATTRIBUTE]; + $subAttributes[ActionObject::ASSERTION_TYPE_ATTRIBUTE] ?? "NO_TYPE"; $this->actionAttributes[$prefix] = - $subAttributes[ActionObject::ASSERTION_VALUE_ATTRIBUTE]; + $subAttributes[ActionObject::ASSERTION_VALUE_ATTRIBUTE] ?? ""; unset($this->actionAttributes[$key]); } } } - /** - * Validates that the given assertion attributes have valid schema according to nested assertion syntax. - * @param array $attributes - * @return void - * @throws TestReferenceException - */ - private function validateAssertionSchema($attributes) - { - /** MQE-683 DEPRECATE OLD METHOD HERE - * Unnecessary validation, only needed for backwards compatibility - */ - $singleChildTypes = ['assertEmpty', 'assertFalse', 'assertFileExists', 'assertFileNotExists', - 'assertIsEmpty', 'assertNotEmpty', 'assertNotNull', 'assertNull', 'assertTrue', - 'assertElementContainsAttribute']; - - if (!in_array($this->type, $singleChildTypes)) { - if (!in_array('expectedResult', $attributes) - || !in_array('actualResult', $attributes)) { - throw new TestReferenceException( - "{$this->type} must have both an expectedResult & actualResult defined (stepKey: {$this->stepKey})", - ["action" => $this->type, "stepKey" => $this->stepKey] - ); - } - } - } - /** * Look up the selector for SomeSectionName.ElementName and set it as the selector attribute in the * resolved custom attributes. Also set the timeout value. @@ -420,7 +440,7 @@ private function resolveUrlReference() $allPages = PageObjectHandler::getInstance()->getAllObjects(); if ($replacement === $url && array_key_exists(trim($url, "{}"), $allPages) ) { - LoggingUtil::getInstance()->getLogger(ActionObject::class)->warning( + throw new TestReferenceException( "page url attribute not found and is required", ["action" => $this->type, "url" => $url, "stepKey" => $this->stepKey] ); diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php index 504d207b4..82bb04906 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/TestObject.php @@ -78,6 +78,13 @@ class TestObject */ private $cachedOrderedActions = null; + /** + * Deprecation message. + * + * @var string|null + */ + private $deprecated; + /** * TestObject constructor. * @@ -87,15 +94,24 @@ class TestObject * @param TestHookObject[] $hooks * @param string $filename * @param string $parentTest + * @param string|null $deprecated */ - public function __construct($name, $parsedSteps, $annotations, $hooks, $filename = null, $parentTest = null) - { + public function __construct( + $name, + $parsedSteps, + $annotations, + $hooks, + $filename = null, + $parentTest = null, + $deprecated = null + ) { $this->name = $name; $this->parsedSteps = $parsedSteps; $this->annotations = $annotations; $this->hooks = $hooks; $this->filename = $filename; $this->parentTest = $parentTest; + $this->deprecated = $deprecated; } /** @@ -128,6 +144,16 @@ public function getParentName() return $this->parentTest; } + /** + * Returns deprecated messages. + * + * @return string|null + */ + public function getDeprecated() + { + return $this->deprecated; + } + /** * Getter for the skip_test boolean * @@ -135,11 +161,8 @@ public function getParentName() */ public function isSkipped() { - // TODO deprecation|deprecate MFTF 3.0.0 remove elseif when group skip is no longer allowed if (array_key_exists('skip', $this->annotations)) { return true; - } elseif (array_key_exists('group', $this->annotations) && (in_array("skip", $this->annotations['group']))) { - return true; } return false; } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php index 9d3a9877e..7f35ee302 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php @@ -13,21 +13,17 @@ */ class ActionGroupAnnotationExtractor extends AnnotationExtractor { - const ACTION_GROUP_REQUIRED_ANNOTATIONS = [ - "description" - ]; - const GENERATE_DOCS_COMMAND = 'generate:docs'; - /** * This method trims away irrelevant tags and returns annotations used in the array passed. The annotations * can be found in both Tests and their child element tests. * - * @param array $testAnnotations - * @param string $filename + * @param array $testAnnotations + * @param string $filename + * @param boolean $validateAnnotations * @return array * @throws \Exception */ - public function extractAnnotations($testAnnotations, $filename) + public function extractAnnotations($testAnnotations, $filename, $validateAnnotations = true) { $annotationObjects = []; $annotations = $this->stripDescriptorTags($testAnnotations, parent::NODE_NAME); @@ -35,52 +31,7 @@ public function extractAnnotations($testAnnotations, $filename) foreach ($annotations as $annotationKey => $annotationData) { $annotationObjects[$annotationKey] = $annotationData[parent::ANNOTATION_VALUE]; } - // TODO: Remove this when all action groups have annotations - if ($this->isCommandDefined()) { - $this->validateMissingAnnotations($annotationObjects, $filename); - } return $annotationObjects; } - - /** - * Validates given annotations against list of required annotations. - * - * @param array $annotationObjects - * @return void - * @throws \Exception - */ - private function validateMissingAnnotations($annotationObjects, $filename) - { - $missingAnnotations = []; - - foreach (self::ACTION_GROUP_REQUIRED_ANNOTATIONS as $REQUIRED_ANNOTATION) { - if (!array_key_exists($REQUIRED_ANNOTATION, $annotationObjects)) { - $missingAnnotations[] = $REQUIRED_ANNOTATION; - } - } - - if (!empty($missingAnnotations)) { - $message = "Action Group File {$filename} is missing required annotations."; - LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation( - $message, - ["actionGroup" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)], - true - ); - } - } - - /** - * Checks if command is defined as generate:docs - * - * @return boolean - */ - private function isCommandDefined() - { - if (defined('COMMAND') and COMMAND == self::GENERATE_DOCS_COMMAND) { - return true; - } else { - return false; - } - } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index 159822db1..28a7d405d 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -23,9 +23,6 @@ class ActionMergeUtil const WAIT_ATTR = 'timeout'; const WAIT_ACTION_NAME = 'waitForPageLoad'; const WAIT_ACTION_SUFFIX = 'WaitForPageLoad'; - const SKIP_READINESS_ACTION_NAME = 'skipReadinessCheck'; - const SKIP_READINESS_OFF_SUFFIX = 'SkipReadinessOff'; - const SKIP_READINESS_ON_SUFFIX = 'SkipReadinessOn'; const DEFAULT_SKIP_ON_ORDER = 'before'; const DEFAULT_SKIP_OFF_ORDER = 'after'; const DEFAULT_WAIT_ORDER = 'after'; @@ -86,7 +83,6 @@ public function resolveActionSteps($parsedSteps, $skipActionGroupResolution = fa { $this->mergeActions($parsedSteps); $this->insertWaits(); - $this->insertReadinessSkips(); if ($skipActionGroupResolution) { return $this->orderedSteps; @@ -233,39 +229,6 @@ private function insertWaits() } } - /** - * Runs through the prepared orderedSteps and calls insertWait if a step requires a wait after it. - * - * @return void - */ - private function insertReadinessSkips() - { - foreach ($this->orderedSteps as $step) { - if (array_key_exists("skipReadiness", $step->getCustomActionAttributes())) { - if ($step->getCustomActionAttributes()['skipReadiness'] == "true") { - $skipReadinessOn = new ActionObject( - $step->getStepKey() . self::SKIP_READINESS_ON_SUFFIX, - self::SKIP_READINESS_ACTION_NAME, - ['state' => "true"], - $step->getStepKey(), - self::DEFAULT_SKIP_ON_ORDER - ); - - $skipReadinessOff = new ActionObject( - $step->getStepKey() . self::SKIP_READINESS_OFF_SUFFIX, - self::SKIP_READINESS_ACTION_NAME, - ['state' => "false"], - $step->getStepKey(), - self::DEFAULT_SKIP_OFF_ORDER - ); - - $this->insertStep($skipReadinessOn); - $this->insertStep($skipReadinessOff); - } - } - } - } - /** * This method takes the steps from the parser and splits steps which need merge from steps that are ordered. * diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php index fc874fa24..03813315f 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php @@ -22,11 +22,12 @@ class ActionObjectExtractor extends BaseObjectExtractor const TEST_ACTION_AFTER = 'after'; const TEST_STEP_MERGE_KEY = 'stepKey'; const ACTION_GROUP_TAG = 'actionGroup'; + const HELPER_TAG = 'helper'; const ACTION_GROUP_REF = 'ref'; const ACTION_GROUP_ARGUMENTS = 'arguments'; const ACTION_GROUP_ARG_VALUE = 'value'; const BEFORE_AFTER_ERROR_MSG = "Merge Error - Steps cannot have both before and after attributes.\tStepKey='%s'"; - const STEP_KEY_BLACKLIST_ERROR_MSG = "StepKeys cannot contain non alphanumeric characters.\tStepKey='%s'"; + const STEP_KEY_BLOCKLIST_ERROR_MSG = "StepKeys cannot contain non alphanumeric characters.\tStepKey='%s'"; const STEP_KEY_EMPTY_ERROR_MSG = "StepKeys cannot be empty.\tAction='%s'"; const DATA_PERSISTENCE_CUSTOM_FIELD = 'field'; const DATA_PERSISTENCE_CUSTOM_FIELD_KEY = 'key'; @@ -69,7 +70,7 @@ public function extractActions($testActions, $testName = null) } if (preg_match('/[^a-zA-Z0-9_]/', $stepKey)) { - throw new XmlException(sprintf(self::STEP_KEY_BLACKLIST_ERROR_MSG, $actionName)); + throw new XmlException(sprintf(self::STEP_KEY_BLOCKLIST_ERROR_MSG, $actionName)); } $actionAttributes = $this->stripDescriptorTags( @@ -84,6 +85,7 @@ public function extractActions($testActions, $testName = null) } $actionAttributes = $this->processActionGroupArgs($actionType, $actionAttributes); + $actionAttributes = $this->processHelperArgs($actionType, $actionAttributes); $linkedAction = $this->processLinkedActions($actionName, $actionData); $actions = $this->extractFieldActions($actionData, $actions); $actionAttributes = $this->extractFieldReferences($actionData, $actionAttributes); @@ -167,6 +169,42 @@ private function processActionGroupArgs($actionType, $actionAttributeData) return $actionAttributeArgData; } + /** + * Takes the helper arguments as an array that can be passed to PHP class + * defined in the action group xml. + * + * @param string $actionType + * @param array $actionAttributeData + * @return array + * @throws TestFrameworkException + */ + private function processHelperArgs($actionType, $actionAttributeData) + { + $reservedHelperVariableNames = ['class', 'method']; + if ($actionType !== self::HELPER_TAG) { + return $actionAttributeData; + } + + $actionAttributeArgData = []; + foreach ($actionAttributeData as $attributeDataKey => $attributeDataValues) { + if (isset($attributeDataValues['nodeName']) && $attributeDataValues['nodeName'] == 'argument') { + if (isset($attributeDataValues['name']) + && in_array($attributeDataValues['name'], $reservedHelperVariableNames)) { + $message = 'Helper argument names ' . implode(',', $reservedHelperVariableNames); + $message .= ' are reserved and can not be used.'; + throw new TestFrameworkException( + $message + ); + } + $actionAttributeArgData[$attributeDataValues['name']] = $attributeDataValues['value'] ?? null; + continue; + } + $actionAttributeArgData[$attributeDataKey] = $attributeDataValues; + } + + return $actionAttributeArgData; + } + /** * Takes the array representing an action and validates it is a persistence type. If of type persistence, * the function checks for any user specified fields to extract as separate actions to be resolved independently diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php index 1859f3195..46adb7ce2 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php @@ -55,12 +55,14 @@ public function __construct() * This method trims away irrelevant tags and returns annotations used in the array passed. The annotations * can be found in both Tests and their child element tests. * - * @param array $testAnnotations - * @param string $filename + * @param array $testAnnotations + * @param string $filename + * @param boolean $validateAnnotations * @return array * @throws XmlException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function extractAnnotations($testAnnotations, $filename) + public function extractAnnotations($testAnnotations, $filename, $validateAnnotations = true) { $annotationObjects = []; $annotations = $this->stripDescriptorTags($testAnnotations, self::NODE_NAME); @@ -82,25 +84,22 @@ public function extractAnnotations($testAnnotations, $filename) if ($annotationKey == "skip") { $annotationData = $annotationData['issueId']; - $this->validateSkippedIssues($annotationData, $filename); + if ($validateAnnotations) { + $this->validateSkippedIssues($annotationData, $filename); + } } foreach ($annotationData as $annotationValue) { $annotationValues[] = $annotationValue[self::ANNOTATION_VALUE]; } - // TODO deprecation|deprecate MFTF 3.0.0 - if ($annotationKey == "group" && in_array("skip", $annotationValues)) { - LoggingUtil::getInstance()->getLogger(AnnotationExtractor::class)->warning( - "Use of group skip will be deprecated in MFTF 3.0.0. Please update tests to use skip tags.", - ["test" => $filename] - ); - } $annotationObjects[$annotationKey] = $annotationValues; } $this->addTestCaseIdToTitle($annotationObjects, $filename); - $this->validateMissingAnnotations($annotationObjects, $filename); + if ($validateAnnotations) { + $this->validateMissingAnnotations($annotationObjects, $filename); + } $this->addStoryTitleToMap($annotationObjects, $filename); return $annotationObjects; diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php index a25db0935..ff3a1e5f8 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php @@ -83,13 +83,14 @@ public function getAnnotationExtractor() * This method takes and array of test data and strips away irrelevant tags. The data is converted into an array of * TestObjects. * - * @param array $testData + * @param array $testData + * @param boolean $validateAnnotations * @return TestObject * @throws \Exception */ - public function extractTestData($testData) + public function extractTestData($testData, $validateAnnotations = true) { - // validate the test name for blacklisted char (will cause allure report issues) MQE-483 + // validate the test name for blocklisted char (will cause allure report issues) MQE-483 NameValidationUtil::validateName($testData[self::NAME], "Test"); $testAnnotations = []; @@ -117,7 +118,8 @@ public function extractTestData($testData) $testAnnotations = $this->annotationExtractor->extractAnnotations( $testData[self::TEST_ANNOTATIONS] ?? [], - $testData[self::NAME] + $testData[self::NAME], + $validateAnnotations ); //Override features with module name if present, populates it otherwise @@ -177,7 +179,8 @@ public function extractTestData($testData) $testAnnotations, $testHooks, $filename, - $testReference + $testReference, + $deprecated ); } catch (XmlException $exception) { throw new XmlException($exception->getMessage() . ' in Test ' . $filename); diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd index 4fdde9990..52794f578 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/assertActions.xsd @@ -14,11 +14,15 @@ <xs:element type="assertElementContainsAttributeType" name="assertElementContainsAttribute" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertArrayHasKeyType" name="assertArrayHasKey" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertArrayNotHasKeyType" name="assertArrayNotHasKey" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="assertArraySubsetType" name="assertArraySubset" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertContainsType" name="assertContains" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertStringContainsStringType" name="assertStringContainsString" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertStringContainsStringIgnoringCaseType" name="assertStringContainsStringIgnoringCase" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertCountType" name="assertCount" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertEmptyType" name="assertEmpty" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertEqualsType" name="assertEquals" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertEqualsWithDeltaType" name="assertEqualsWithDelta" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertEqualsCanonicalizingType" name="assertEqualsCanonicalizing" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertEqualsIgnoringCaseType" name="assertEqualsIgnoringCase" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertFalseType" name="assertFalse" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertFileExistsType" name="assertFileExists" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertFileNotExistsType" name="assertFileNotExists" minOccurs="0" maxOccurs="unbounded"/> @@ -26,14 +30,18 @@ <xs:element type="assertGreaterThanType" name="assertGreaterThan" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertGreaterThanOrEqualType" name="assertGreaterThanOrEqual" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertInstanceOfType" name="assertInstanceOf" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="assertInternalTypeType" name="assertInternalType" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertIsEmptyType" name="assertIsEmpty" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertLessOrEqualsType" name="assertLessOrEquals" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertLessThanType" name="assertLessThan" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertLessThanOrEqualType" name="assertLessThanOrEqual" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotContainsType" name="assertNotContains" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertStringNotContainsStringType" name="assertStringNotContainsString" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertStringNotContainsStringIgnoringCaseType" name="assertStringNotContainsStringIgnoringCase" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotEmptyType" name="assertNotEmpty" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotEqualsType" name="assertNotEquals" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertNotEqualsWithDeltaType" name="assertNotEqualsWithDelta" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertNotEqualsCanonicalizingType" name="assertNotEqualsCanonicalizing" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="assertNotEqualsIgnoringCaseType" name="assertNotEqualsIgnoringCase" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotInstanceOfType" name="assertNotInstanceOf" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotNullType" name="assertNotNull" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertNotRegExpType" name="assertNotRegExp" minOccurs="0" maxOccurs="unbounded"/> @@ -49,22 +57,6 @@ </xs:group> <!-- Data Attributes --> - <xs:attribute type="xs:string" name="expected"> - <xs:annotation> - <xs:documentation> - Assertion's Expected value. Cast by expectedType. - </xs:documentation> - </xs:annotation> - </xs:attribute> - - <xs:attribute type="xs:string" name="actual"> - <xs:annotation> - <xs:documentation> - Assertion's Actual value. Cast by actualType. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="message"> <xs:annotation> <xs:documentation> @@ -92,16 +84,11 @@ <!-- Complex Types --> <!-- ASSERTION TYPES --> - <!-- REMOVE expected/expectedType and actual/actualType in MQE-683--> <xs:complexType name="assertionType"> <xs:choice maxOccurs="unbounded"> <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attribute ref="delta"/> <xs:attribute ref="strict"/> @@ -115,23 +102,8 @@ </xs:documentation> </xs:annotation> <xs:choice maxOccurs="unbounded"> - <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="expectedResult" type="expectedElementContainsType" minOccurs="0"/> </xs:choice> - <xs:attribute type="xs:string" name="expectedValue"> - <xs:annotation> - <xs:documentation> - Assertion's Expected value. Cast by expectedType. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute name="selector" use="required"/> - <xs:attribute type="xs:string" name="attribute" use="required"> - <xs:annotation> - <xs:documentation> - Attribute in given element to be assert against. - </xs:documentation> - </xs:annotation> - </xs:attribute> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -145,10 +117,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -163,10 +131,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -181,10 +145,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attribute ref="strict"/> <xs:attributeGroup ref="commonActionAttributes"/> @@ -200,10 +160,34 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertStringContainsStringType"> + <xs:annotation> + <xs:documentation> + Asserts that given string contains a value. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertStringContainsStringIgnoringCaseType"> + <xs:annotation> + <xs:documentation> + Asserts that given string contains a value ignoring case. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -218,10 +202,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -235,10 +215,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -246,22 +222,62 @@ <xs:complexType name="assertEqualsType"> <xs:annotation> <xs:documentation> - Asserts that two given variables are equal. Can be given a "delta" to allow precision tolerance in floating point comparison. + Asserts that two given variables are equal. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertEqualsWithDeltaType"> + <xs:annotation> + <xs:documentation> + Asserts that two given variables are equal. Accepts a delta. </xs:documentation> </xs:annotation> <xs:choice maxOccurs="unbounded"> <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="delta"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> + <xs:complexType name="assertEqualsIgnoringCaseType"> + <xs:annotation> + <xs:documentation> + Asserts that two given variables are equal. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertEqualsCanonicalizingType"> + <xs:annotation> + <xs:documentation> + Asserts that two given variables are equal. The contents are canonicalized before they are compared. + For instance, when the two variables $expected and $actual are arrays, then these arrays are + sorted before they are compared. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + <xs:complexType name="assertFalseType"> <xs:annotation> <xs:documentation> @@ -271,10 +287,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -288,10 +300,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -305,10 +313,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -323,10 +327,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -341,10 +341,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -359,10 +355,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -377,10 +369,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -395,10 +383,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -412,10 +396,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -430,10 +410,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -448,10 +424,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -466,10 +438,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -484,10 +452,34 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertStringNotContainsStringType"> + <xs:annotation> + <xs:documentation> + Asserts that given string does not contain a value. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertStringNotContainsStringIgnoringCaseType"> + <xs:annotation> + <xs:documentation> + Asserts that given string does not contain a value ignoring case. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -501,10 +493,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -512,19 +500,59 @@ <xs:complexType name="assertNotEqualsType"> <xs:annotation> <xs:documentation> - Asserts that actual and expected are not equal. Can be given a "delta" to allow precision tolerance in floating point comparison. + Asserts that actual and expected are not equal. </xs:documentation> </xs:annotation> <xs:choice maxOccurs="unbounded"> <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertNotEqualsWithDeltaType"> + <xs:annotation> + <xs:documentation> + Asserts that two given variables are not equal. Accepts a delta. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> <xs:attribute ref="delta"/> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertNotEqualsIgnoringCaseType"> + <xs:annotation> + <xs:documentation> + Asserts that actual and expected are not equal. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="assertNotEqualsCanonicalizingType"> + <xs:annotation> + <xs:documentation> + Asserts that two given variables are equal. The contents are canonicalized before they are compared. + For instance, when the two variables $expected and $actual are arrays, then these arrays are + sorted before they are compared. + </xs:documentation> + </xs:annotation> + <xs:choice maxOccurs="unbounded"> + <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> + <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> + </xs:choice> + <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -538,10 +566,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -555,10 +579,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -573,10 +593,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -591,10 +607,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -608,10 +620,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -626,10 +634,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -644,10 +648,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -662,10 +662,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -680,10 +676,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -697,10 +689,6 @@ <xs:choice maxOccurs="unbounded"> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attribute ref="message"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -715,10 +703,6 @@ <xs:element name="expectedResult" type="expectedResultType" minOccurs="0"/> <xs:element name="actualResult" type="actualResultType" minOccurs="0"/> </xs:choice> - <xs:attribute ref="expected"/> - <xs:attribute type="assertEnum" name="expectedType" default="const"/> - <xs:attribute ref="actual"/> - <xs:attribute type="assertEnum" name="actualType" default="const"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> @@ -735,6 +719,20 @@ </xs:extension> </xs:simpleContent> </xs:complexType> + <xs:complexType name="expectedElementContainsType"> + <xs:annotation> + <xs:documentation> + Element containing the Expected value and selector/attributeName. + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="selector" use="required"/> + <xs:attribute type="xs:string" name="attribute" use="required"/> + <xs:attribute type="assertEnum" name="type" use="required"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> <xs:complexType name="actualResultType"> <xs:annotation> <xs:documentation> @@ -763,4 +761,4 @@ <xs:enumeration value="const"/> </xs:restriction> </xs:simpleType> -</xs:schema> \ No newline at end of file +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd index 8670d9885..2aad30c75 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd @@ -11,12 +11,13 @@ <xs:group name="customTags"> <xs:choice> + <xs:element name="helper" type="helperType" minOccurs="0" maxOccurs="unbounded" /> <xs:element type="magentoCLIType" name="magentoCLI" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="magentoCronType" name="magentoCron" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="closeAdminNotificationType" name="closeAdminNotification" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="searchAndMultiSelectOptionType" name="searchAndMultiSelectOption" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="selectMultipleOptionsType" name="selectMultipleOptions" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="formatMoneyType" name="formatMoney" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="formatCurrencyType" name="formatCurrency" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="parseFloatType" name="parseFloat" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="mSetLocaleType" name="mSetLocale" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="mResetLocaleType" name="mResetLocale" minOccurs="0" maxOccurs="unbounded"/> @@ -24,11 +25,31 @@ <xs:element type="clearFieldType" name="clearField" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="assertArrayIsSortedType" name="assertArrayIsSorted" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="generateDateType" name="generateDate" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="getOTPType" name="getOTP" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <!-- Complex Types --> + <xs:complexType name="helperType"> + <xs:sequence> + <xs:element name="argument" type="argumentType" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + <xs:attribute type="xs:string" name="class" use="required" /> + <xs:attribute type="xs:string" name="method" use="required" /> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:complexType> + + <xs:complexType name="argumentType" mixed="true"> + <xs:attribute name="name" use="required"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:pattern value="[^cm].*|c(.{0,3}|[^l].*|l[^a].*|la[^s].*|las[^s].*|lass.+)|m(.{0,4}|[^e].*|e[^t].*|et[^h].*|eth[^o].*|etho[^d].*|ethod.+)" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + <xs:complexType name="magentoCLIType"> <xs:annotation> <xs:documentation> @@ -158,25 +179,29 @@ <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> - <xs:complexType name="formatMoneyType"> + <xs:complexType name="formatCurrencyType"> <xs:annotation> <xs:documentation> - Formats given input to given locale. Returns formatted string for test use. + Format input to specified currency according to the locale specified. Returns formatted string for test use. + Use NumberFormatter::formatCurrency(), see https://www.php.net/manual/en/numberformatter.formatcurrency.php </xs:documentation> </xs:annotation> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute ref="userInput"/> - <xs:attribute type="xs:string" name="locale"> - <xs:annotation> - <xs:documentation> - Locale to format given input. Defaults to 'en_US.UTF-8' if nothing is given. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attributeGroup ref="commonActionAttributes"/> - </xs:extension> - </xs:simpleContent> + <xs:attribute type="xs:string" name="userInput" use="required"/> + <xs:attribute type="xs:string" name="locale" use="required"> + <xs:annotation> + <xs:documentation> + Locale in which the input would be formatted (e.g. en_US). + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="currency" use="required"> + <xs:annotation> + <xs:documentation> + The 3-letter ISO 4217 currency code indicating the currency to use. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> <xs:complexType name="parseFloatType"> @@ -296,6 +321,18 @@ </xs:simpleContent> </xs:complexType> + <xs:complexType name="getOTPType"> + <xs:annotation> + <xs:documentation> + Generates TOTP by a shared secret. Use https://github.com/Spomky-Labs/otphp + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> <xs:complexType name="arrayType"> <xs:simpleContent> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd index bd32ba879..2638722d8 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd @@ -7,54 +7,11 @@ --> <xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:include schemaLocation="../../Test/etc/actionTypeTags.xsd"/> - <xs:element name="actionGroups" type="actionGroupType"/> - <xs:complexType name="actionGroupType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element type="actionsRefType" name="actionGroup" maxOccurs="unbounded"/> - </xs:choice> - </xs:complexType> - <xs:complexType name="actionsRefType"> - <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:group ref="actionTypeTags"/> - <xs:element name="arguments"> - <xs:complexType> - <xs:sequence> - <xs:element name="argument" maxOccurs="unbounded" minOccurs="0"> - <xs:complexType> - <xs:attribute type="xs:string" name="name" use="required"/> - <xs:attribute type="xs:string" name="defaultValue"/> - <xs:attribute type="dataTypeEnum" name="type" default="entity"/> - </xs:complexType> - </xs:element> - </xs:sequence> - </xs:complexType> - </xs:element> - <xs:element name="annotations"> - <xs:complexType> - <xs:sequence> - <xs:element name="description"/> - </xs:sequence> - </xs:complexType> - </xs:element> - </xs:choice> - <xs:attribute type="xs:string" name="name" use="required"/> - <xs:attribute type="xs:string" name="filename"/> - <xs:attribute type="xs:string" name="insertBefore"/> - <xs:attribute type="xs:string" name="insertAfter"/> - <xs:attribute type="xs:string" name="extends"/> - <xs:attribute type="xs:string" name="deprecated"> - <xs:annotation> - <xs:documentation> - Message and flag which shows that entity is deprecated. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:complexType> - <xs:simpleType name="dataTypeEnum" final="restriction"> - <xs:restriction base="xs:string"> - <xs:enumeration value="string"/> - <xs:enumeration value="entity"/> - </xs:restriction> - </xs:simpleType> + <xs:redefine schemaLocation="mergedActionGroupSchema.xsd"> + <xs:complexType name="actionGroupType"> + <xs:choice minOccurs="0" maxOccurs="1"> + <xs:element type="actionsRefType" name="actionGroup" maxOccurs="1"/> + </xs:choice> + </xs:complexType> + </xs:redefine> </xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd index 9aa772858..def2964af 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionTypeTags.xsd @@ -34,7 +34,6 @@ <xs:element type="closeTabType" name="closeTab" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="commentType" name="comment" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="dragAndDropType" name="dragAndDrop" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="executeInSeleniumType" name="executeInSelenium" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="executeJSType" name="executeJS" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="fillFieldType" name="fillField" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="loadSessionSnapshotType" name="loadSessionSnapshot" minOccurs="0" maxOccurs="unbounded"/> @@ -44,8 +43,7 @@ <xs:element type="moveForwardType" name="moveForward" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="moveMouseOverType" name="moveMouseOver" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="openNewTabType" name="openNewTab" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="pauseExecutionType" name="pauseExecution" minOccurs="0" maxOccurs="unbounded"/> - <xs:element type="performOnType" name="performOn" minOccurs="0" maxOccurs="unbounded"/> + <xs:element type="pauseType" name="pause" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="pressKeyType" name="pressKey" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="reloadPageType" name="reloadPage" minOccurs="0" maxOccurs="unbounded"/> <xs:element type="resetCookieType" name="resetCookie" minOccurs="0" maxOccurs="unbounded"/> @@ -290,20 +288,6 @@ </xs:simpleContent> </xs:complexType> - <xs:complexType name="executeInSeleniumType"> - <xs:annotation> - <xs:documentation> - Allows you to use Selenium WebDriver methods directly; last resort method, do not use regularly. - </xs:documentation> - </xs:annotation> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute ref="function" use="required"/> - <xs:attributeGroup ref="commonActionAttributes"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="executeJSType"> <xs:annotation> <xs:documentation> @@ -431,7 +415,7 @@ </xs:simpleContent> </xs:complexType> - <xs:complexType name="pauseExecutionType"> + <xs:complexType name="pauseType"> <xs:annotation> <xs:documentation> Pauses test execution in debug mode. To proceed test, press "ENTER" in console. Useful for test writing. @@ -444,21 +428,6 @@ </xs:simpleContent> </xs:complexType> - <xs:complexType name="performOnType"> - <xs:annotation> - <xs:documentation> - Performs given function on element. - </xs:documentation> - </xs:annotation> - <xs:simpleContent> - <xs:extension base="xs:string"> - <xs:attribute ref="selector" use="required"/> - <xs:attribute ref="function" use="required"/> - <xs:attributeGroup ref="commonActionAttributes"/> - </xs:extension> - </xs:simpleContent> - </xs:complexType> - <xs:complexType name="pressKeyType"> <xs:annotation> <xs:documentation> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/mergedActionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/mergedActionGroupSchema.xsd new file mode 100644 index 000000000..bd32ba879 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Test/etc/mergedActionGroupSchema.xsd @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:include schemaLocation="../../Test/etc/actionTypeTags.xsd"/> + <xs:element name="actionGroups" type="actionGroupType"/> + <xs:complexType name="actionGroupType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element type="actionsRefType" name="actionGroup" maxOccurs="unbounded"/> + </xs:choice> + </xs:complexType> + <xs:complexType name="actionsRefType"> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="actionTypeTags"/> + <xs:element name="arguments"> + <xs:complexType> + <xs:sequence> + <xs:element name="argument" maxOccurs="unbounded" minOccurs="0"> + <xs:complexType> + <xs:attribute type="xs:string" name="name" use="required"/> + <xs:attribute type="xs:string" name="defaultValue"/> + <xs:attribute type="dataTypeEnum" name="type" default="entity"/> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> + <xs:element name="annotations"> + <xs:complexType> + <xs:sequence> + <xs:element name="description"/> + </xs:sequence> + </xs:complexType> + </xs:element> + </xs:choice> + <xs:attribute type="xs:string" name="name" use="required"/> + <xs:attribute type="xs:string" name="filename"/> + <xs:attribute type="xs:string" name="insertBefore"/> + <xs:attribute type="xs:string" name="insertAfter"/> + <xs:attribute type="xs:string" name="extends"/> + <xs:attribute type="xs:string" name="deprecated"> + <xs:annotation> + <xs:documentation> + Message and flag which shows that entity is deprecated. + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + <xs:simpleType name="dataTypeEnum" final="restriction"> + <xs:restriction base="xs:string"> + <xs:enumeration value="string"/> + <xs:enumeration value="entity"/> + </xs:restriction> + </xs:simpleType> +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd index 6ded366bb..6690ef8dd 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd @@ -136,13 +136,6 @@ </xs:documentation> </xs:annotation> </xs:attribute> - <xs:attribute type="xs:boolean" name="skipReadiness" use="prohibited"> - <xs:annotation> - <xs:documentation> - Flag for skipping readiness check. - </xs:documentation> - </xs:annotation> - </xs:attribute> <xs:attributeGroup ref="commonActionAttributes"/> </xs:complexType> </xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd index f9b09a86f..8fce6e63e 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd @@ -12,7 +12,7 @@ <xs:complexContent> <xs:restriction base="configType"> <xs:choice> - <xs:element type="testType" name="test" maxOccurs="unbounded"> + <xs:element type="testType" name="test" maxOccurs="1"> <xs:unique name="uniqueStepKeyInTestBlock"> <xs:annotation> <xs:documentation> diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/RemoveModuleFileInSuiteFiles.php b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveModuleFileInSuiteFiles.php new file mode 100644 index 000000000..a42fbbf31 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveModuleFileInSuiteFiles.php @@ -0,0 +1,152 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Upgrade; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Finder\Finder; + +/** + * Class RemoveModuleFileInSuiteFiles + * @package Magento\FunctionalTestingFramework\Upgrade + */ +class RemoveModuleFileInSuiteFiles implements UpgradeInterface +{ + /** + * OutputInterface + * + * @var OutputInterface + */ + private $output; + + /** + * Console output style + * + * @var SymfonyStyle + */ + private $ioStyle = null; + + /** + * Indicate if notice is print + * + * @var boolean + */ + private $printNotice = false; + + /** + * Number of test being updated + * + * @var integer + */ + private $testsUpdated = 0; + + /** + * Indicate if a match and replace has happened + * + * @var boolean + */ + private $replaced = false; + + /** + * Scan all suite xml files, remove <module file="".../> node, and print update message + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + * @throws TestFrameworkException + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $this->setOutputStyle($input, $output); + $this->output = $output; + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + + // Get module suite xml files + $xmlFiles = $scriptUtil->getModuleXmlFilesByScope($testPaths, 'Suite'); + $this->processXmlFiles($xmlFiles); + + return ("Removed module file reference in {$this->testsUpdated} suite file(s)."); + } + + /** + * Process on list of xml files + * + * @param Finder $xmlFiles + * @return void + */ + private function processXmlFiles($xmlFiles) + { + foreach ($xmlFiles as $file) { + $contents = $file->getContents(); + $filePath = $file->getRealPath(); + $this->replaced = false; + $contents = $this->removeModuleFileAttributeInSuite($contents, $filePath); + if ($this->replaced) { + file_put_contents($filePath, $contents); + $this->testsUpdated++; + } + } + } + + /** + * Remove module file attribute in Suite xml file + * + * @param string $contents + * @param string $file + * @return string|string[]|null + */ + private function removeModuleFileAttributeInSuite($contents, $file) + { + $pattern = '/<module[^\<\>]+file[\s]*=[\s]*"(?<file>[^"\<\>]*)"[^\>\<]*>/'; + $contents = preg_replace_callback( + $pattern, + function ($matches) use ($file) { + if (!$this->printNotice) { + $this->ioStyle->note( + '`file` is not a valid attribute for <module> in Suite XML schema.' . PHP_EOL + . 'The `file`references in the following xml files are commented out. ' + . 'Consider using <test> instead.' + ); + $this->printNotice = true; + } + $this->output->writeln( + PHP_EOL + . '"' . trim($matches[0]) . '"' . PHP_EOL + . 'is commented out from file: ' . $file . PHP_EOL + ); + $result = str_replace('<module', '<!--module', $matches[0]); + $result = str_replace('>', '--> <!-- Please replace with <test name="" -->', $result); + $this->replaced = true; + return $result; + }, + $contents + ); + return $contents; + } + + /** + * Set Symfony Style for output + * + * @param InputInterface $input + * @param OutputInterface $output + * @return void + */ + private function setOutputStyle(InputInterface $input, OutputInterface $output) + { + // For output style + if (null === $this->ioStyle) { + $this->ioStyle = new SymfonyStyle($input, $output); + } + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php new file mode 100644 index 000000000..ced1042ad --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/RemoveUnusedArguments.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Upgrade; + +use Magento\FunctionalTestingFramework\StaticCheck\ActionGroupArgumentsCheck; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Filesystem\Filesystem; +use DOMElement; + +/** + * Class RenameMetadataFiles + * @package Magento\FunctionalTestingFramework\Upgrade + */ +class RemoveUnusedArguments implements UpgradeInterface +{ + const ARGUMENTS_BLOCK_REGEX_PATTERN = "/\s*<arguments.*\/arguments>/s"; + + /** + * Updates all actionGroup xml files + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + $xmlFiles = $scriptUtil->getModuleXmlFilesByScope($testPaths, 'ActionGroup'); + $actionGroupsUpdated = 0; + $fileSystem = new Filesystem(); + foreach ($xmlFiles as $file) { + $contents = $file->getContents(); + $argumentsCheck = new ActionGroupArgumentsCheck(); + /** @var DOMElement $actionGroup */ + $actionGroup = $argumentsCheck->getActionGroupDomElement($contents); + $allArguments = $argumentsCheck->extractActionGroupArguments($actionGroup); + $unusedArguments = $argumentsCheck->findUnusedArguments($allArguments, $contents); + if (empty($unusedArguments)) { + continue; + } + //Remove <arguments> block if all arguments are unused + if (empty(array_diff($allArguments, $unusedArguments))) { + $contents = preg_replace(self::ARGUMENTS_BLOCK_REGEX_PATTERN, '', $contents); + } else { + foreach ($unusedArguments as $argument) { + $argumentRegexPattern = "/\s*<argument.*name\s*=\s*\"".$argument."\".*\/>/"; + $contents = preg_replace($argumentRegexPattern, '', $contents); + } + } + $fileSystem->dumpFile($file->getRealPath(), $contents); + $actionGroupsUpdated++; + } + return "Removed unused action group arguments from {$actionGroupsUpdated} file(s)."; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/RenameMetadataFiles.php b/src/Magento/FunctionalTestingFramework/Upgrade/RenameMetadataFiles.php new file mode 100644 index 000000000..5be881a62 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/RenameMetadataFiles.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Upgrade; + +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Finder\Finder; + +/** + * Class RenameMetadataFiles + * @package Magento\FunctionalTestingFramework\Upgrade + */ +class RenameMetadataFiles implements UpgradeInterface +{ + /** + * Upgrades all test xml files + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + + foreach ($testPaths as $testsPath) { + $finder = new Finder(); + $finder->files()->in($testsPath)->name("*-meta.xml"); + + foreach ($finder->files() as $file) { + $oldFileName = $file->getFileName(); + $newFileName = $this->convertFileName($oldFileName); + $oldPath = $file->getPathname(); + $newPath = $file->getPath() . "/" . $newFileName; + print("Renaming " . $oldPath . " => " . $newPath . "\n"); + rename($oldPath, $newPath); + } + } + + return "Finished renaming -meta.xml files."; + } + + /** + * Convert filenames like: + * user_role-meta.xml => UserRoleMeta.xml + * store-meta.xml => StoreMeta.xml + * + * @param string $oldFileName + * @return string + */ + private function convertFileName(string $oldFileName) + { + $stripEnding = preg_replace("/-meta.xml/", "", $oldFileName); + $hyphenToUnderscore = str_replace("-", "_", $stripEnding); + $parts = explode("_", $hyphenToUnderscore); + $ucParts = []; + foreach ($parts as $part) { + $ucParts[] = ucfirst($part); + } + $recombine = join("", $ucParts); + $addEnding = $recombine . "Meta.xml"; + return $addEnding; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/SplitMultipleEntitiesFiles.php b/src/Magento/FunctionalTestingFramework/Upgrade/SplitMultipleEntitiesFiles.php new file mode 100644 index 000000000..b0190d959 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/SplitMultipleEntitiesFiles.php @@ -0,0 +1,237 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Upgrade; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Finder\Finder; + +/** + * Class SplitMultipleEntitiesFiles + * @package Magento\FunctionalTestingFramework\Upgrade + */ +class SplitMultipleEntitiesFiles implements UpgradeInterface +{ + const XML_VERSION = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL; + const XML_COPYRIGHT = '<!--' . PHP_EOL + . ' /**' . PHP_EOL + . ' * Copyright © Magento, Inc. All rights reserved.' . PHP_EOL + . ' * See COPYING.txt for license details.' . PHP_EOL + . ' */' . PHP_EOL + . '-->' . PHP_EOL; + const XML_NAMESPACE = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' . PHP_EOL; + const XML_SCHEMA_LOCATION = "\t" . 'xsi:noNamespaceSchemaLocation="urn:magento:mftf:'; + + const FILENAME_BASE = 'base'; + const FILENAME_SUFFIX = 'type'; + + /** + * OutputInterface + * + * @var OutputInterface + */ + private $output; + + /** + * Total test updated + * + * @var integer + */ + private $testsUpdated = 0; + + /** + * Entity categories for the upgrade script + * + * @var array + */ + private $entityCategories = [ + 'Suite' => 'Suite/etc/suiteSchema.xsd', + 'Test' => 'Test/etc/testSchema.xsd', + 'ActionGroup' => 'Test/etc/actionGroupSchema.xsd', + 'Page' => 'Page/etc/PageObject.xsd', + 'Section' => 'Page/etc/SectionObject.xsd', + ]; + + /** + * Scan all xml files and split xml files that contains more than one entities + * for Test, Action Group, Page, Section, Suite types. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + * @throws TestFrameworkException + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $this->output = $output; + $this->testsUpdated = 0; + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + + // Process module xml files + foreach ($this->entityCategories as $type => $urn) { + $xmlFiles = $scriptUtil->getModuleXmlFilesByScope($testPaths, $type); + $this->processXmlFiles($xmlFiles, $type, $urn); + } + + return ("Split multiple entities in {$this->testsUpdated} file(s)."); + } + + /** + * Split on list of xml files + * + * @param Finder $xmlFiles + * @param string $type + * @param string $urn + * @return void + */ + private function processXmlFiles($xmlFiles, $type, $urn) + { + foreach ($xmlFiles as $file) { + $contents = $file->getContents(); + $domDocument = new \DOMDocument(); + $domDocument->loadXML($contents); + $entities = $domDocument->getElementsByTagName(lcfirst($type)); + + if ($entities->length > 1) { + $filename = $file->getRealPath(); + if ($this->output->isVerbose()) { + $this->output->writeln('Processing file:' . $filename); + } + foreach ($entities as $entity) { + /** @var \DOMElement $entity */ + $entityName = $entity->getAttribute('name'); + $entityContent = $entity->ownerDocument->saveXML($entity); + + $dir = dirname($file); + $dir .= DIRECTORY_SEPARATOR . ucfirst(basename($file, '.xml')); + $splitFileName = $this->formatName($entityName, $type); + $this->filePutContents( + $dir . DIRECTORY_SEPARATOR . $splitFileName . '.xml', + $type, + $urn, + $entityContent + ); + if ($this->output->isVerbose()) { + $this->output->writeln( + 'Created file:' . $dir . DIRECTORY_SEPARATOR . $splitFileName . '.xml' + ); + } + $this->testsUpdated++; + } + unlink($file); + if ($this->output->isVerbose()) { + $this->output->writeln('Unlinked file:' . $filename . PHP_EOL); + } + } + } + } + + /** + * Create file with contents and create dir if needed + * + * @param string $fullPath + * @param string $type + * @param string $urn + * @param string $contents + * @return void + */ + private function filePutContents($fullPath, $type, $urn, $contents) + { + $dir = dirname($fullPath); + + if (!is_dir($dir)) { + mkdir($dir, 0777, true); + } + + // Make sure not overwriting an existing file + $fullPath = $this->getNonExistingFileFullPath($fullPath, $type); + + $fullContents = self::XML_VERSION + . self::XML_COPYRIGHT + . '<' . lcfirst($type) . 's ' + . self::XML_NAMESPACE + . self::XML_SCHEMA_LOCATION . $urn . '">' . PHP_EOL + . ' ' . $contents . PHP_EOL + . '</' . lcfirst($type) . 's>' . PHP_EOL; + + file_put_contents($fullPath, $fullContents); + } + + /** + * Format name to include type if it's Page, Section or Action Group + * + * @param string $name + * @param string $type + * @return string + */ + private function formatName($name, $type) + { + $name = ucfirst($name); + $type = ucfirst($type); + + if ($type !== 'Section' && $type !== 'Page' && $type !== 'ActionGroup') { + return $name; + } + + $parts = $this->getFileNameParts($name, $type); + if (empty($parts[self::FILENAME_SUFFIX])) { + $name .= $type; + } + return $name; + } + + /** + * Vary the input to return a non-existing file name + * + * @param string $fullPath + * @param string $type + * @return string + */ + private function getNonExistingFileFullPath($fullPath, $type) + { + $type = ucfirst($type); + $dir = dirname($fullPath); + $filename = basename($fullPath, '.xml'); + $i = 1; + $parts = []; + while (file_exists($fullPath)) { + if (empty($parts)) { + $parts = $this->getFileNameParts($filename, $type); + } + $basename = $parts[self::FILENAME_BASE] . strval(++$i); + $fullPath = $dir . DIRECTORY_SEPARATOR . $basename . $parts[self::FILENAME_SUFFIX] . '.xml'; + } + return $fullPath; + } + + /** + * Split filename into two parts and return it in an associate array with keys FILENAME_BASE and FILENAME_SUFFIX + * + * @param string $filename + * @param string $type + * @return array + */ + private function getFileNameParts($filename, $type) + { + $type = ucfirst($type); + $fileNameParts = []; + if (substr($filename, -strlen($type)) === $type) { + $fileNameParts[self::FILENAME_BASE] = substr($filename, 0, strlen($filename) - strlen($type)); + $fileNameParts[self::FILENAME_SUFFIX] = $type; + } else { + $fileNameParts[self::FILENAME_BASE] = $filename; + $fileNameParts[self::FILENAME_SUFFIX] = ''; + } + return $fileNameParts; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php new file mode 100644 index 000000000..2628be851 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateAssertionSchema.php @@ -0,0 +1,167 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Upgrade; + +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Finder\Finder; + +/** + * Class UpdateAssertionSchema + * @package Magento\FunctionalTestingFramework\Upgrade + */ +class UpdateAssertionSchema implements UpgradeInterface +{ + /** + * Upgrades all test xml files, changing as many <assert> actions to be nested as possible + * WILL NOT CATCH cases where style is a mix of old and new + * + * @param InputInterface $input + * @param OutputInterface $output + * @return string + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $scriptUtil = new ScriptUtil(); + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } + + $testsUpdated = 0; + foreach ($testPaths as $testsPath) { + $finder = new Finder(); + $finder->files()->in($testsPath)->name("*.xml"); + + $fileSystem = new Filesystem(); + foreach ($finder->files() as $file) { + $contents = $file->getContents(); + // Isolate <assert ... /> but never <assert> ... </assert>, stops after finding first /> + preg_match_all('/<assert.*\/>/', $contents, $potentialAssertions); + $newAssertions = []; + $index = 0; + if (empty($potentialAssertions[0])) { + continue; + } + foreach ($potentialAssertions[0] as $potentialAssertion) { + $newAssertions[$index] = $this->convertOldAssertionToNew($potentialAssertion); + $index++; + } + foreach ($newAssertions as $currentIndex => $replacements) { + $contents = str_replace($potentialAssertions[0][$currentIndex], $replacements, $contents); + } + $fileSystem->dumpFile($file->getRealPath(), $contents); + $testsUpdated++; + } + } + + return ("Assertion Syntax updated in {$testsUpdated} file(s)."); + } + + /** + * Takes given string and attempts to convert it from single line to multi-line + * + * @param string $assertion + * @return string + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function convertOldAssertionToNew($assertion) + { + // <assertSomething => assertSomething + $assertType = ltrim(explode(' ', $assertion)[0], '<'); + + // regex to all attribute=>value pairs + $allAttributes = "stepKey|actual|actualType|expected|expectedType|expectedValue|"; + $allAttributes .= "delta|message|selector|attribute|before|after|remove"; + $grabValueRegex = '/('. $allAttributes .')=(\'[^\']*\'|"[^"]*")/'; + + // Makes 3 arrays in $grabbedParts: + // 0 contains stepKey="value" + // 1 contains stepKey + // 2 contains value + $sortedParts = []; + preg_match_all($grabValueRegex, $assertion, $grabbedParts); + for ($i = 0; $i < count($grabbedParts[0]); $i++) { + $sortedParts[$grabbedParts[1][$i]] = $grabbedParts[2][$i]; + } + + // Begin trimming values and adding back into new string + $trimmedParts = []; + $newString = "<$assertType"; + $subElements = ["actual" => [], "expected" => []]; + foreach ($sortedParts as $type => $value) { + // If attribute="'value'", elseif attribute='"value"', new nested format will break if we leave these in + if (strpos($value, '"') === 0) { + $value = rtrim(ltrim($value, '"'), '"'); + } elseif (strpos($value, "'") === 0) { + $value = rtrim(ltrim($value, "'"), "'"); + } + // If value is empty string (" " or ' '), trim again to become empty + if (str_replace(" ", "", $value) == "''") { + $value = ""; + } elseif (str_replace(" ", "", $value) == '""') { + $value = ""; + } + + // Value is ready for storage/reapply + $trimmedParts[$type] = $value; + if (in_array($type, ["stepKey", "delta", "message", "before", "after", "remove"])) { + // Add back as attribute safely + $newString .= " $type=\"$value\""; + continue; + } + + // Store in subtype for child element creation + if ($type == "actual") { + $subElements["actual"]["value"] = $value; + } elseif ($type == "actualType") { + $subElements["actual"]["type"] = $value; + } elseif ($type == "expected" or $type == "expectedValue") { + $subElements["expected"]["value"] = $value; + } elseif ($type == "expectedType") { + $subElements["expected"]["type"] = $value; + } + } + $newString .= ">\n"; + + // Assert type is very edge-cased, completely different schema + if ($assertType == 'assertElementContainsAttribute') { + // assertElementContainsAttribute type defaulted to string if not present + if (!isset($subElements["expected"]['type'])) { + $subElements["expected"]['type'] = "string"; + } + $value = $subElements['expected']['value'] ?? ""; + $type = $subElements["expected"]['type']; + $selector = $trimmedParts['selector']; + $attribute = $trimmedParts['attribute']; + // @codingStandardsIgnoreStart + $newString .= "\t\t\t<expectedResult selector=\"$selector\" attribute=\"$attribute\" type=\"$type\">$value</expectedResult>\n"; + // @codingStandardsIgnoreEnd + } else { + // Set type to const if it's absent, old default + if (isset($subElements["actual"]['value']) && !isset($subElements["actual"]['type'])) { + $subElements["actual"]['type'] = "const"; + } + if (isset($subElements["expected"]['value']) && !isset($subElements["expected"]['type'])) { + $subElements["expected"]['type'] = "const"; + } + foreach ($subElements as $type => $subElement) { + if (empty($subElement)) { + continue; + } + $value = $subElement['value']; + $typeValue = $subElement['type']; + $newString .= "\t\t\t<{$type}Result type=\"$typeValue\">$value</{$type}Result>\n"; + } + } + $newString .= " </$assertType>"; + return $newString; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateTestSchemaPaths.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateTestSchemaPaths.php index 8b79b6019..e6d3358d6 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpdateTestSchemaPaths.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpdateTestSchemaPaths.php @@ -6,9 +6,11 @@ namespace Magento\FunctionalTestingFramework\Upgrade; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Script\ScriptUtil; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; +use Symfony\Component\Console\Output\OutputInterface; /** * Class UpdateTestSchemaPaths @@ -16,58 +18,82 @@ */ class UpdateTestSchemaPaths implements UpgradeInterface { + /** + * OutputInterface + * + * @var OutputInterface + */ + private $output; + + /** + * Total test updated + * + * @var integer + */ + private $testsUpdated = 0; + + /** + * Entity type to urn map + * + * @var array + */ + private $typeToUrns = [ + 'ActionGroup' => 'urn:magento:mftf:Test/etc/actionGroupSchema.xsd', + 'Data' => 'urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd', + 'Metadata' => 'urn:magento:mftf:DataGenerator/etc/dataOperation.xsd', + 'Page' => 'urn:magento:mftf:Page/etc/PageObject.xsd', + 'Section' => 'urn:magento:mftf:Page/etc/SectionObject.xsd', + 'Suite' => 'urn:magento:mftf:Suite/etc/suiteSchema.xsd', + 'Test' => 'urn:magento:mftf:Test/etc/testSchema.xsd', + ]; + /** * Upgrades all test xml files, replacing relative schema paths to URN. * - * @param InputInterface $input + * @param InputInterface $input + * @param OutputInterface $output * @return string + * @throws TestFrameworkException */ - public function execute(InputInterface $input) + public function execute(InputInterface $input, OutputInterface $output) { - // @codingStandardsIgnoreStart - $relativeToUrn = [ - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd" - => "urn:magento:mftf:DataGenerator/etc/dataOperation.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd" - => "urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd" - => "urn:magento:mftf:Page/etc/PageObject.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd" - => "urn:magento:mftf:Page/etc/SectionObject.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd" - => "urn:magento:mftf:Test/etc/actionGroupSchema.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd" - => "urn:magento:mftf:Test/etc/testSchema.xsd", - "dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd" - => "urn:magento:mftf:Suite/etc/suiteSchema.xsd" - ]; - // @codingStandardsIgnoreEnd + $scriptUtil = new ScriptUtil(); + $this->output = $output; + $this->testsUpdated = 0; + $testPaths[] = $input->getArgument('path'); + if (empty($testPaths[0])) { + $testPaths = $scriptUtil->getAllModulePaths(); + } - $relativePatterns = []; - $urns = []; - // Prepare array of patterns to URNs for preg_replace (replace / to escapes - foreach ($relativeToUrn as $relative => $urn) { - $relativeReplaced = str_replace('/', '\/', $relative); - $relativePatterns[] = '/[.\/]+' . $relativeReplaced . '/'; - $urns[] = $urn; + // Process module xml files + foreach ($this->typeToUrns as $type => $urn) { + $xmlFiles = $scriptUtil->getModuleXmlFilesByScope($testPaths, $type); + $this->processXmlFiles($xmlFiles, $urn); } - $testsPath = $input->getArgument('path'); - $finder = new Finder(); - $finder->files()->in($testsPath)->name("*.xml"); + return ("Schema Path updated to use MFTF URNs in {$this->testsUpdated} file(s)."); + } - $fileSystem = new Filesystem(); - $testsUpdated = 0; - foreach ($finder->files() as $file) { - $count = 0; + /** + * Convert xml schema location from non urn based to urn based + * + * @param Finder $xmlFiles + * @param string $urn + * @return void + */ + private function processXmlFiles($xmlFiles, $urn) + { + $pattern = '/xsi:noNamespaceSchemaLocation[\s]*=[\s]*"(?<urn>[^\<\>"\']*)"/'; + foreach ($xmlFiles as $file) { + $filePath = $file->getRealPath(); $contents = $file->getContents(); - $contents = preg_replace($relativePatterns, $urns, $contents, -1, $count); - $fileSystem->dumpFile($file->getRealPath(), $contents); - if ($count > 0) { - $testsUpdated++; + preg_match($pattern, $contents, $matches); + if (isset($matches['urn'])) { + if (trim($matches['urn']) !== $urn) { + file_put_contents($filePath, str_replace($matches['urn'], $urn, $contents)); + $this->testsUpdated++; + } } } - - return ("Schema Path updated to use MFTF URNs in {$testsUpdated} file(s)."); } } diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeInterface.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeInterface.php index b6905845c..150737bc2 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeInterface.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeInterface.php @@ -7,6 +7,7 @@ namespace Magento\FunctionalTestingFramework\Upgrade; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; /** * Upgrade script interface @@ -15,8 +16,9 @@ interface UpgradeInterface { /** * Executes upgrade script, returns output. - * @param InputInterface $input + * @param InputInterface $input + * @param OutputInterface $output * @return string */ - public function execute(InputInterface $input); + public function execute(InputInterface $input, OutputInterface $output); } diff --git a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php index 245f95d82..cf2aabe2d 100644 --- a/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php +++ b/src/Magento/FunctionalTestingFramework/Upgrade/UpgradeScriptList.php @@ -28,7 +28,12 @@ class UpgradeScriptList implements UpgradeScriptListInterface public function __construct(array $scripts = []) { $this->scripts = [ + 'removeUnusedArguments' => new RemoveUnusedArguments(), 'upgradeTestSchema' => new UpdateTestSchemaPaths(), + 'upgradeAssertionSchema' => new UpdateAssertionSchema(), + 'renameMetadataFiles' => new RenameMetadataFiles(), + 'removeModuleFileInSuiteFiles' => new RemoveModuleFileInSuiteFiles(), + 'splitMultipleEntitiesFiles' => new SplitMultipleEntitiesFiles(), ] + $scripts; } diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php deleted file mode 100644 index 7a28f8969..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ /dev/null @@ -1,137 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Util; - -use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; -use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; -use Magento\FunctionalTestingFramework\Test\Objects\TestObject; -use Magento\FunctionalTestingFramework\Test\Util\ActionGroupAnnotationExtractor; -use Magento\FunctionalTestingFramework\Test\Util\ActionGroupObjectExtractor; - -/** - * Class TestGenerator - */ -class DocGenerator -{ - const DEFAULT_OUTPUT_DIR = - PROJECT_ROOT . - DIRECTORY_SEPARATOR . - "dev" . - DIRECTORY_SEPARATOR . - "tests" . - DIRECTORY_SEPARATOR . - "docs"; - const DOC_NAME = "documentation.md"; - # This is the only place FILENAMES is defined as this string - const FILENAMES = "filenames"; - - /** - * DocGenerator constructor. - * - */ - public function __construct() - { - } - - /** - * This creates html documentation for objects passed in - * - * @param ActionGroupObject[]|TestObject[] $annotatedObjects - * @param string $outputDir - * @return void - * @throws TestFrameworkException - */ - public function createDocumentation($annotatedObjects, $outputDir, $clean) - { - if (empty($outputDir)) { - $fullPath = self::DEFAULT_OUTPUT_DIR . DIRECTORY_SEPARATOR; - } else { - $fullPath = $outputDir . DIRECTORY_SEPARATOR; - } - $filePath = $fullPath . self::DOC_NAME; - - if (!file_exists($fullPath)) { - mkdir($fullPath, 0755, true); - } - if (file_exists($filePath) and !$clean) { - throw new TestFrameworkException( - "$filePath already exists, please add --clean if you want to overwrite it." - ); - } - $pageGroups = []; - - foreach ($annotatedObjects as $name => $object) { - $annotations = $object->getAnnotations(); - $filenames = explode(',', $object->getFilename()); - $arguments = $object->getArguments(); - - $info = [ - actionGroupObject::ACTION_GROUP_DESCRIPTION => $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] - ?? 'NO_DESCRIPTION_SPECIFIED', - self::FILENAMES => $filenames, - ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS => $arguments - ]; - - $pageGroups = array_merge_recursive( - $pageGroups, - [$annotations[ActionGroupObject::ACTION_GROUP_PAGE] ?? 'NO_PAGE_SPECIFIED' => [$name => $info]] - ); - } - - ksort($pageGroups); - foreach ($pageGroups as $page => $groups) { - ksort($groups); - $pageGroups[$page] = $groups; - } - - $markdown = $this->transformToMarkdown($pageGroups); - - file_put_contents($filePath, $markdown); - } - - /** - * This creates html documentation for objects passed in - * - * @param array $annotationList - * @return string - */ - private function transformToMarkdown($annotationList) - { - $markdown = "#Action Group Information" . PHP_EOL; - $markdown .= "This documentation contains a list of all Action Groups." . - PHP_EOL . - PHP_EOL; - - $markdown .= "---" . PHP_EOL; - foreach ($annotationList as $group => $objects) { - foreach ($objects as $name => $annotations) { - $markdown .= "###$name" . PHP_EOL; - $markdown .= "**Description**:" . PHP_EOL; - $markdown .= "- " . $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] . PHP_EOL . PHP_EOL; - if (!empty($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS])) { - $markdown .= "**Action Group Arguments**:" . PHP_EOL . PHP_EOL; - $markdown .= "| Name | Type |" . PHP_EOL; - $markdown .= "| ---- | ---- |" . PHP_EOL; - foreach ($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS] as $argument) { - $argumentName = $argument->getName(); - $argumentType = $argument->getDataType(); - $markdown .= "| $argumentName | $argumentType |" . PHP_EOL; - } - $markdown .= PHP_EOL; - } - $markdown .= "**Located In**:" . PHP_EOL; - foreach ($annotations[self::FILENAMES] as $filename) { - $relativeFilename = str_replace(MAGENTO_BP . DIRECTORY_SEPARATOR, "", $filename); - $markdown .= PHP_EOL . "- $relativeFilename"; - } - $markdown .= PHP_EOL . "***" . PHP_EOL; - } - } - return $markdown; - } -} diff --git a/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php b/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php index 0e8c1e17f..5955235ce 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php +++ b/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php @@ -7,28 +7,53 @@ namespace Magento\FunctionalTestingFramework\Util\Logger; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Monolog\Handler\StreamHandler; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Monolog\Handler\HandlerInterface; use Monolog\Logger; class MftfLogger extends Logger { + /** + * MFTF execution phase + * + * @var string + */ + private $phase; + + /** + * MftfLogger constructor. + * + * @param string $name + * @param HandlerInterface[] $handlers + * @param callable[] $processors + * @throws TestFrameworkException + */ + public function __construct($name, array $handlers = [], array $processors = []) + { + parent::__construct($name, $handlers, $processors); + $this->phase = MftfApplicationConfig::getConfig()->getPhase(); + } + /** * Prints a deprecation warning, as well as adds a log at the WARNING level. + * Suppresses logging during execution phase. * * @param string $message The log message. * @param array $context The log context. * @param boolean $verbose * @return void - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException */ public function deprecation($message, array $context = [], $verbose = false) { $message = "DEPRECATION: " . $message; - // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { + // print during test generation + if ($this->phase === MftfApplicationConfig::GENERATION_PHASE && $verbose) { print ($message . json_encode($context) . "\n"); } - parent::warning($message, $context); + // suppress logging during test execution + if ($this->phase !== MftfApplicationConfig::EXECUTION_PHASE) { + parent::warning($message, $context); + } } /** @@ -38,13 +63,12 @@ public function deprecation($message, array $context = [], $verbose = false) * @param array $context The log context. * @param boolean $verbose * @return void - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException */ public function criticalFailure($message, array $context = [], $verbose = false) { $message = "FAILURE: " . $message; // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { + if ($this->phase !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { print ($message . implode("\n", $context) . "\n"); } parent::critical($message, $context); @@ -52,20 +76,23 @@ public function criticalFailure($message, array $context = [], $verbose = false) /** * Adds a log record at the NOTICE level. + * Suppresses logging during execution phase. * * @param string $message * @param array $context * @param boolean $verbose * @return void - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException */ public function notification($message, array $context = [], $verbose = false) { $message = "NOTICE: " . $message; - // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { - print ($message . implode("\n", $context) . "\n"); + // print during test generation + if ($this->phase === MftfApplicationConfig::GENERATION_PHASE && $verbose) { + print ($message . json_encode($context) . "\n"); + } + // suppress logging during test execution + if ($this->phase !== MftfApplicationConfig::EXECUTION_PHASE) { + parent::notice($message, $context); } - parent::notice($message, $context); } } diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/MetadataGenUtil.php b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/MetadataGenUtil.php deleted file mode 100644 index 2cd3f7011..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/MetadataGenUtil.php +++ /dev/null @@ -1,170 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\Util\MetadataGenerator\FormData; - -use Mustache_Engine; -use Mustache_Loader_FilesystemLoader; - -class MetadataGenUtil -{ - const OUTPUT_DIR = '_output'; - const INPUT_TXT_FILE = 'input.yml'; - - /** - * Mustache Engine instance for the templating. - * - * @var Mustache_Engine - */ - private $mustacheEngine; - - /** - * Name of the operation (e.g. createCategory) - * - * @var string - */ - private $operationName; - - /** - * Data type of the operation (e.g. category) - * - * @var string - */ - private $operationDataType; - - /** - * Url path for the operation (e.g. /admin/system_config/save/section/payment) - * - * @var string - */ - private $operationUrl; - - /** - * The raw parameter data to be converted into metadata - * (e.g. entity[param1]=value1&entity[param2]=value2&entity[param3]=value3&entityField=field1) - * - * @var string - */ - private $inputString; - - /** - * The relative filepath for the *meta.xml file to be generated. - * - * @var string - */ - private $filepath; - - /** - * MetadataGenUtil constructor. - * - * @param string $operationName - * @param string $operationDataType - * @param string $operationUrl - * @param string $inputString - */ - public function __construct($operationName, $operationDataType, $operationUrl, $inputString) - { - $this->operationName = $operationName; - $this->operationDataType = $operationDataType; - $this->operationUrl = $operationUrl; - $this->inputString = $inputString; - - $this->filepath = self::OUTPUT_DIR . DIRECTORY_SEPARATOR . $this->operationDataType . "-meta.xml"; - } - - /** - * Function which takes params from constructor, transforms into data array and outputs a representative metadata - * file for MFTF to consume and send requests. - * - * @return void - */ - public function generateMetadataFile() - { - // Load Mustache templates - $this->mustacheEngine = new Mustache_Engine( - ['loader' => new Mustache_Loader_FilesystemLoader("views"), - 'partials_loader' => new Mustache_Loader_FilesystemLoader( - "views" . DIRECTORY_SEPARATOR . "partials" - )] - ); - - // parse the string params into an array - parse_str($this->inputString, $results); - $data = $this->convertResultToEntry($results, $this->operationDataType); - $data = $this->appendParentParams($data); - $output = $this->mustacheEngine->render('operation', $data); - $this->cleanAndCreateOutputDir(); - file_put_contents( - $this->filepath, - $output - ); - } - - /** - * Function which takes the top level params from the user and returns an array appended with the needed config. - * - * @param array $data - * @return array - */ - private function appendParentParams($data) - { - $result = $data; - $result['operationName'] = $this->operationName; - $result['operationDataType'] = $this->operationDataType; - $result['operationUrl'] = $this->operationUrl; - - return $result; - } - - /** - * Function which is called recursively to generate the mustache array for the template enging. Makes decisions - * about type and format based on parameter array. - * - * @param array $results - * @param string $defaultDataType - * @return array - */ - private function convertResultToEntry($results, $defaultDataType) - { - $data = []; - - foreach ($results as $key => $result) { - $entry = []; - if (is_array($result)) { - $entry = array_merge($entry, ['objectName' => $key]); - $res = $this->convertResultToEntry($result, $defaultDataType); - if (!array_key_exists('objects', $res)) { - $entry = array_merge($entry, ['objects' => null]); - $entry = array_merge($entry, ['dataType' => $key]); - } else { - $entry = array_merge($entry, ['hasChildObj' => true]); - $entry = array_merge($entry, ['dataType' => $defaultDataType]); - } - $data['objects'][] = array_merge($entry, $res); - } else { - $data['fields'][] = ['fieldName' => $key]; - } - } - - return $data; - } - - /** - * Function which cleans any previously created fileand creates the _output dir. - * - * @return void - */ - private function cleanAndCreateOutputDir() - { - if (!file_exists(self::OUTPUT_DIR)) { - mkdir(self::OUTPUT_DIR); - } - - if (file_exists($this->filepath)) { - unlink($this->filepath); - } - } -} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/_generateMetadataFile.php b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/_generateMetadataFile.php deleted file mode 100644 index fce54be41..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/_generateMetadataFile.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -require_once '../../../../../../vendor/autoload.php'; - -const INPUT_TXT_FILE = 'input.yml'; - -// parse the input.yml file for context -$inputCfg = \Symfony\Component\Yaml\Yaml::parse(file_get_contents(INPUT_TXT_FILE)); - -// create new MetadataGenUtil Object -$metadataGenUtil = new Magento\FunctionalTestingFramework\Util\MetadataGenerator\FormData\MetadataGenUtil( - $inputCfg['operationName'], - $inputCfg['operationDataType'], - $inputCfg['operationUrl'], - $inputCfg['inputString'] -); - -//generate the metadata file in the _output dir -$metadataGenUtil->generateMetadataFile(); diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/input.yml.sample b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/input.yml.sample deleted file mode 100644 index 503aef067..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/input.yml.sample +++ /dev/null @@ -1,4 +0,0 @@ -operationName: createMyEntity -operationDataType: myEntityType -operationUrl: /admin/system_config/save/someEntity -inputString: entity[param1]=value1&entity[param2]=value2&entity[param3]=value3&entityField=field1 diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/operation.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/operation.mustache deleted file mode 100644 index 28321504d..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/operation.mustache +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../DataGenerator/etc/dataOperation.xsd"> - <operation name="{{operationName}}" dataType="{{operationDataType}}" type="create" auth="adminFormKey" url="{{operationUrl}}" method="POST"> - {{>object}} - </operation> -</config> diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/field.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/field.mustache deleted file mode 100644 index 284835ef2..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/field.mustache +++ /dev/null @@ -1 +0,0 @@ -<field key="{{fieldName}}">string</field> diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/object.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/object.mustache deleted file mode 100644 index 7d3aaf5ca..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/FormData/views/partials/object.mustache +++ /dev/null @@ -1,10 +0,0 @@ -{{#objects}} -<object key="{{objectName}}" dataType="{{dataType}}"> -{{#fields}} - {{> field}} -{{/fields}} -{{#hasChildObj}} - {{> object}} -{{/hasChildObj}} -</object> -{{/objects}} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/MetadataGenerator.php b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/MetadataGenerator.php deleted file mode 100644 index 10d75bf8e..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/MetadataGenerator.php +++ /dev/null @@ -1,533 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\FunctionalTestingFramework\Util\MetadataGenerator\Swagger; - -use Doctrine\Common\Collections\ArrayCollection; -use Epfremme\Swagger\Entity\Schemas\SchemaInterface; -use Epfremme\Swagger\Entity\Schemas\ObjectSchema; -use Epfremme\Swagger\Entity\Schemas\RefSchema; -use Epfremme\Swagger\Entity\Schemas\ArraySchema; -use Epfremme\Swagger\Factory\SwaggerFactory; -use Epfremme\Swagger\Entity\Swagger; -use Epfremme\Swagger\Entity\Operation; -use Epfremme\Swagger\Entity\Parameters\BodyParameter; -use Epfremme\Swagger\Entity\Parameters\AbstractTypedParameter; -use Mustache_Engine; -use Mustache_Loader_FilesystemLoader; - -class MetadataGenerator -{ - const OUTPUT_DIR = '_operations'; - const OUTPUT_DIR2 = '_definitions'; - const INPUT_TXT_FILE = 'magento.json'; - const AUTH = 'adminOauth'; - const TEMPLATE_VAR_DEF_TYPE = 'create'; - - const TEMPLATE_VAR_OP_NAME = 'operationName'; - const TEMPLATE_VAR_OP_DATATYPE = 'operationDataType'; - const TEMPLATE_VAR_OP_TYPE = 'operationType'; - const TEMPLATE_VAR_OP_AUTH = 'auth'; - const TEMPLATE_VAR_OP_URL = 'operationUrl'; - const TEMPLATE_VAR_OP_METHOD = 'method'; - - const TEMPLATE_VAR_OP_FIELD = 'fields'; - const TEMPLATE_VAR_FIELD_NAME = 'fieldName'; - const TEMPLATE_VAR_FIELD_TYPE = 'fieldType'; - const TEMPLATE_VAR_FIELD_IS_REQUIRED = 'isRequired'; - - const TEMPLATE_VAR_OP_PARAM = 'params'; - const TEMPLATE_VAR_PARAM_NAME = 'paramName'; - const TEMPLATE_VAR_PARAM_TYPE = 'paramType'; - - const TEMPLATE_VAR_OP_ARRAY = 'arrays'; - const TEMPLATE_VAR_ARRAY_KEY = 'arrayKey'; - const TEMPLATE_VAR_ARRAY_IS_REQUIRED = 'isRequiredArray'; - const TEMPLATE_VAR_VALUES = 'values'; - const TEMPLATE_VAR_VALUE = 'value'; - - const REF_REGEX = "~#/definitions/([\S]+)~"; - - /** - * Mustache Engine instance for the templating. - * - * @var Mustache_Engine - */ - private $mustache_engine; - - /** - * Swagger built from json. - * - * @var Swagger - */ - private static $swagger; - - /** - * Path params. - * - * @var string - */ - private $pathParams; - - /** - * Array to hold operation query params. - * - * @var array - */ - private $params; - - /** - * Array to hold operation fields. - * - * @var array - */ - private $fields; - - /** - * The relative filepath for the *meta.xml file to be generated. - * - * @var string - */ - private $filepath; - - /** - * Operation method mapping. - * - * @var array - */ - private static $methodMapping = [ - 'POST' => 'create', - 'DELETE' => 'delete', - 'PUT' => 'update', - 'GET' => 'get', - ]; - - /** - * Build and initialize generator. - */ - public function __construct() - { - self::buildSwaggerSpec(); - $this->initMustacheTemplates(); - } - - /** - * Parse swagger spec from input json file. - * TODO: read swagger spec from magento server. - * - * @return void - */ - public function generateMetadataFromSwagger() - { - $paths = self::$swagger->getPaths(); - - foreach ($paths->getIterator() as $pathKey => $path) { - $operations = $path->getOperations(); - foreach ($operations->getIterator() as $operationKey => $operation) { - $this->renderOperation($operation, $pathKey, $operationKey); - } - } - - $definitions = self::$swagger->getDefinitions(); - foreach ($definitions->getIterator() as $defKey => $definition) { - $this->renderDefinition($defKey, $definition); - } - } - - /** - * Render swagger operations. - * - * @param Operation $operation - * @param string $path - * @param string $method - * @return void - */ - private function renderOperation($operation, $path, $method) - { - $operationArray = []; - $this->pathParams = ''; - $this->params = []; - $this->fields = []; - $operationMethod = strtoupper($method); - $operationDataType = ucfirst($operation->getOperationId()); - - $operationArray[self::TEMPLATE_VAR_OP_NAME] = self::$methodMapping[$operationMethod] . $operationDataType; - $operationArray[self::TEMPLATE_VAR_OP_DATATYPE] = $operationDataType; - $operationArray[self::TEMPLATE_VAR_OP_METHOD] = $operationMethod; - $operationArray[self::TEMPLATE_VAR_OP_AUTH] = self::AUTH; - $operationArray[self::TEMPLATE_VAR_OP_TYPE] = self::$methodMapping[$operationMethod]; - $operationArray[self::TEMPLATE_VAR_OP_URL] = $path; - - $params = $operation->getParameters(); - if (!empty($params)) { - $this->parseParams($params, $path); - $operationArray[self::TEMPLATE_VAR_OP_FIELD] = $this->fields; - $operationArray[self::TEMPLATE_VAR_OP_PARAM] = $this->params; - } - - if (!empty($this->pathParams)) { - $operationArray[self::TEMPLATE_VAR_OP_URL] .= $this->pathParams; - } - - $this->generateMetaDataFile( - self::OUTPUT_DIR, - $operationDataType, - 'operation', - $operationArray - ); - } - - /** - * Render swagger definitions. - * - * @param string $defKey - * @param ObjectSchema|ArraySchema $definition - * @return void - */ - private function renderDefinition($defKey, $definition) - { - $operationArray = []; - $this->fields = []; - - $operationArray[self::TEMPLATE_VAR_OP_NAME] = $defKey; - $operationArray[self::TEMPLATE_VAR_OP_DATATYPE] = $defKey; - $operationArray[self::TEMPLATE_VAR_OP_TYPE] = self::TEMPLATE_VAR_DEF_TYPE; - - if ($definition instanceof ObjectSchema) { - $properties = $definition->getProperties(); - if (!empty($properties)) { - $dataField = []; - $dataArray = []; - foreach ($properties->getIterator() as $propertyKey => $property) { - if ($property instanceof ArraySchema) { - $dataArray[] = $this->parseSchema($property, $propertyKey, 1, 1); - } else { - $dataField[] = $this->parseSchema($property, $propertyKey, 0, 1); - } - } - if (!empty($dataField)) { - $operationArray[self::TEMPLATE_VAR_OP_FIELD] = $dataField; - } - if (!empty($dataArray)) { - foreach ($dataArray as $array) { - $operationArray[self::TEMPLATE_VAR_OP_ARRAY.'1'][] = $array[self::TEMPLATE_VAR_OP_ARRAY.'1']; - } - } - } - } elseif ($definition instanceof ArraySchema) { - $operationArray = array_merge($operationArray, $this->parseSchema($definition, $defKey, 1, 1)); - } - - $this->generateMetaDataFile( - self::OUTPUT_DIR2, - $defKey, - 'definition', - $operationArray - ); - } - - /** - * Parse schema and return an array that will be consumed by mustache template engine. - * - * @param SchemaInterface $schema - * @param string $name - * @param boolean $forArray - * @param integer $depth - * @return array - */ - private function parseSchema($schema, $name, $forArray, $depth) - { - $data = []; - - if ($schema instanceof RefSchema) { - $ref = $schema->getRef(); - preg_match(self::REF_REGEX, $ref, $matches); - if (count($matches) == 2) { - if (!$forArray) { - $data[self::TEMPLATE_VAR_FIELD_NAME] = $name; - $data[self::TEMPLATE_VAR_FIELD_TYPE] = $matches[1]; - } else { - $data[self::TEMPLATE_VAR_VALUES][] = [self::TEMPLATE_VAR_VALUE => $matches[1]]; - } - } - } elseif ($schema instanceof ArraySchema) { - $values = []; - $items = $schema->getItems(); - $data[self::TEMPLATE_VAR_OP_ARRAY.$depth][self::TEMPLATE_VAR_ARRAY_KEY] = $name; - if ($items instanceof ArrayCollection) { - foreach ($items->getIterator() as $itemKey => $item) { - $values[] = $this->parseSchema($item, $itemKey, 1, $depth+1); - } - $data[self::TEMPLATE_VAR_VALUES] = $values; - $data[self::TEMPLATE_VAR_OP_ARRAY.$depth] = $data; - } else { - $data[self::TEMPLATE_VAR_OP_ARRAY.$depth] = array_merge( - $data[self::TEMPLATE_VAR_OP_ARRAY.$depth], - $this->parseSchema($items, $name, 1, $depth+1) - ); - } - } else { - if (method_exists($schema, 'getType')) { - if (!$forArray) { - $data[self::TEMPLATE_VAR_FIELD_NAME] = $name; - $data[self::TEMPLATE_VAR_FIELD_TYPE] = $schema->getType(); - } else { - $data[self::TEMPLATE_VAR_VALUES][] = [self::TEMPLATE_VAR_VALUE => $schema->getType()]; - } - } - } - return $data; - } - - /** - * Parse params for an operation. - * - * @param ArrayCollection $params - * @param string $path - * @return void - */ - private function parseParams($params, $path) - { - foreach ($params->getIterator() as $paramKey => $param) { - if (empty($param)) { - continue; - } - - $paramIn = $param->getIn(); - if ($paramIn == 'body') { - $this->setBodyParams($param); - } elseif ($paramIn == 'path') { - $this->setPathParams($param, $path); - } elseif ($paramIn == 'query') { - $this->setQueryParams($param); - } - } - } - - /** - * Set body params for an operation. - * - * @param BodyParameter $param - * @return void - */ - private function setBodyParams($param) - { - $this->fields = []; - $required = []; - - $paramSchema = $param->getSchema(); - $paramSchemaRequired = $paramSchema->getRequired(); - if (!empty($paramSchemaRequired)) { - foreach ($paramSchemaRequired as $i => $key) { - $required[] = $key; - } - } - $paramSchemaProperties = $paramSchema->getProperties(); - foreach ($paramSchemaProperties->getIterator() as $paramPropertyKey => $paramSchemaProperty) { - $field = []; - $field[self::TEMPLATE_VAR_FIELD_NAME] = $paramPropertyKey; - $field[self::TEMPLATE_VAR_FIELD_TYPE] = $paramSchemaProperty->getType(); - if ($field[self::TEMPLATE_VAR_FIELD_TYPE] == 'ref') { - preg_match(self::REF_REGEX, $paramSchemaProperty->getRef(), $matches); - if (count($matches) == 2) { - $field[self::TEMPLATE_VAR_FIELD_TYPE] = $matches[1]; - } - } - if (in_array($paramPropertyKey, $required)) { - $field[self::TEMPLATE_VAR_FIELD_IS_REQUIRED] = 'true'; - } else { - $field[self::TEMPLATE_VAR_FIELD_IS_REQUIRED] = 'false'; - } - $this->fields[] = $field; - } - } - - /** - * Set path params for an operation. - * - * @param AbstractTypedParameter $param - * @param string $path - * @return void - */ - private function setPathParams($param, $path) - { - $pathParamStr = '{' . $param->getName() . '}'; - if (strpos($path, $pathParamStr) === false) { - $this->pathParams .= '/' . $pathParamStr; - } - } - - /** - * Set query params for an operation. - * - * @param AbstractTypedParameter $param - * @return void - */ - private function setQueryParams($param) - { - $query = []; - $query[self::TEMPLATE_VAR_PARAM_NAME] = $param->getName(); - $query[self::TEMPLATE_VAR_PARAM_TYPE] = $param->getType(); - - $this->params[] = $query; - } - - /** - * Build swagger spec from factory. - * - * @return void - */ - private static function buildSwaggerSpec() - { - $factory = new SwaggerFactory(); - self::$swagger = $factory->build(self::INPUT_TXT_FILE); - } - - /** - * Function which initializes mustache templates for file generation. - * - * @return void - */ - private function initMustacheTemplates() - { - $this->mustache_engine = new Mustache_Engine( - ['loader' => new Mustache_Loader_FilesystemLoader("views"), - 'partials_loader' => new Mustache_Loader_FilesystemLoader( - "views" . DIRECTORY_SEPARATOR . "partials" - )] - ); - } - - /** - * Render template and generate a metadata file. - * - * @param string $relativeDir - * @param string $fileName - * @param string $template - * @param array $data - * @return void - */ - private function generateMetaDataFile($relativeDir, $fileName, $template, $data) - { - $this->filepath = $relativeDir . DIRECTORY_SEPARATOR . $fileName . "-meta.xml"; - $result = $this->mustache_engine->render($template, $data); - $this->cleanAndCreateOutputDir(); - file_put_contents( - $this->filepath, - $result - ); - } - - /** - * Function which cleans any previously created fileand creates the _output dir. - * - * @return void - */ - private function cleanAndCreateOutputDir() - { - if (!file_exists(self::OUTPUT_DIR)) { - mkdir(self::OUTPUT_DIR); - } - - if (!file_exists(self::OUTPUT_DIR2)) { - mkdir(self::OUTPUT_DIR2); - } - - if (file_exists($this->filepath)) { - unlink($this->filepath); - } - } - /* - private static function debugData() { - $paramsExample = ['params' => - [ - 'paramName' => 'name', - 'paramType' => 'type' - ], - [ - 'paramName' => 'name', - 'paramType' => 'type' - ], - [ - 'paramName' => 'name', - 'paramType' => 'type' - ], - ]; - $fieldsExample = ['fields' => - [ - 'fieldName' => 'name', - 'fieldType' => 'type', - 'isRequired' => true, - ], - [ - 'fieldName' => 'name', - 'fieldType' => 'type', - 'isRequired' => true, - ], - [ - 'fieldName' => 'name', - 'fieldType' => 'type', - 'isRequired' => true, - ], - ]; - $arraysExample = ['arrays1' => - [ - 'arrayKey' => 'someKey', - 'values' => [ - 'type1', - 'type2', - ], - 'arrays2' => [ - 'arrayKey' => 'otherKey', - 'values' => [ - 'type3', - 'type4', - ], - 'arrays3' => [ - 'arrayKey' => 'anotherKey', - 'values' => [ - 'type5', - 'type6', - ], - ], - ], - ], - [ - 'arrayKey' => 'someKey', - 'values' => [ - [ - 'value' => 'type1', - ], - [ - 'value' => 'type2', - ], - ], - 'arrays2' => [ - 'arrayKey' => 'otherKey', - 'values' => [ - [ - 'value' => 'type3', - ], - [ - 'value' => 'type4', - ], - ], - 'arrays3' => [ - 'arrayKey' => 'anotherKey', - 'values' => [ - [ - 'value' => 'type5', - ], - [ - 'value' => 'type6', - ], - ], - ], - ], - ], - ]; - } - */ -} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/_generateMetadataFile.php b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/_generateMetadataFile.php deleted file mode 100644 index c759b045e..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/_generateMetadataFile.php +++ /dev/null @@ -1,10 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -require_once 'autoload.php'; - -// create a MetadataGenerator Object -$generator = new Magento\FunctionalTestingFramework\Util\MetadataGenerator\Swagger\MetadataGenerator(); -$generator->generateMetadataFromSwagger(); diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/autoload.php b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/autoload.php deleted file mode 100644 index e7108d0f4..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/autoload.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -use Doctrine\Common\Annotations\AnnotationRegistry; - -$loader = require '../../../../../../vendor/autoload.php'; - -AnnotationRegistry::registerAutoloadNamespace( - 'JMS\Serializer\Annotation', - "../../../../../vendor/jms/serializer/src" -); - -AnnotationRegistry::registerLoader([$loader, 'loadClass']); - -return $loader; diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/magento.json b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/magento.json deleted file mode 100644 index 07f40e979..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/magento.json +++ /dev/null @@ -1 +0,0 @@ -{"swagger":"2.0","info":{"version":"2.2","title":"Magento Enterprise"},"host":"magento3.loc","basePath":"/index.php/rest/all","schemes":["http"],"tags":[{"name":"storeStoreRepositoryV1","description":"Store repository interface"},{"name":"storeGroupRepositoryV1","description":"Group repository interface"},{"name":"storeWebsiteRepositoryV1","description":"Website repository interface"},{"name":"storeStoreConfigManagerV1","description":"Store config manager interface"},{"name":"directoryCurrencyInformationAcquirerV1","description":"Currency information acquirer interface"},{"name":"directoryCountryInformationAcquirerV1","description":"Country information acquirer interface"},{"name":"eavAttributeSetRepositoryV1","description":"Interface AttributeSetRepositoryInterface"},{"name":"eavAttributeSetManagementV1","description":"Interface AttributeSetManagementInterface"},{"name":"customerGroupRepositoryV1","description":"Customer group CRUD interface"},{"name":"customerGroupManagementV1","description":"Interface for managing customer groups."},{"name":"customerCustomerGroupConfigV1","description":"Interface for system configuration operations for customer groups."},{"name":"customerCustomerMetadataV1","description":"Interface for retrieval information about customer attributes metadata."},{"name":"customerAddressMetadataV1","description":"Interface for retrieval information about customer address attributes metadata."},{"name":"customerCustomerRepositoryV1","description":"Customer CRUD interface."},{"name":"customerAccountManagementV1","description":"Interface for managing customers accounts."},{"name":"customerAddressRepositoryV1","description":"Customer address CRUD interface."},{"name":"backendModuleServiceV1","description":"Interface for module service."},{"name":"cmsPageRepositoryV1","description":"CMS page CRUD interface."},{"name":"cmsBlockRepositoryV1","description":"CMS block CRUD interface."},{"name":"catalogProductRepositoryV1","description":""},{"name":"catalogProductAttributeTypesListV1","description":""},{"name":"catalogProductAttributeRepositoryV1","description":"Interface RepositoryInterface must be implemented in new model"},{"name":"catalogCategoryAttributeRepositoryV1","description":"Interface RepositoryInterface must be implemented in new model"},{"name":"catalogCategoryAttributeOptionManagementV1","description":"Interface RepositoryInterface must be implemented in new model"},{"name":"catalogProductTypeListV1","description":""},{"name":"catalogAttributeSetRepositoryV1","description":""},{"name":"catalogAttributeSetManagementV1","description":""},{"name":"catalogProductAttributeManagementV1","description":""},{"name":"catalogProductAttributeGroupRepositoryV1","description":""},{"name":"catalogProductAttributeOptionManagementV1","description":""},{"name":"catalogProductMediaAttributeManagementV1","description":""},{"name":"catalogProductAttributeMediaGalleryManagementV1","description":""},{"name":"catalogProductTierPriceManagementV1","description":""},{"name":"catalogTierPriceStorageV1","description":"Tier prices storage."},{"name":"catalogBasePriceStorageV1","description":"Base prices storage."},{"name":"catalogCostStorageV1","description":"Product cost storage."},{"name":"catalogSpecialPriceStorageV1","description":"Special price storage presents efficient price API and is used to retrieve, update or delete special prices."},{"name":"catalogCategoryRepositoryV1","description":""},{"name":"catalogCategoryManagementV1","description":""},{"name":"catalogCategoryListV1","description":""},{"name":"catalogProductCustomOptionTypeListV1","description":""},{"name":"catalogProductCustomOptionRepositoryV1","description":""},{"name":"catalogProductLinkTypeListV1","description":""},{"name":"catalogProductLinkManagementV1","description":""},{"name":"catalogProductLinkRepositoryV1","description":"Interface Product links handling interface"},{"name":"catalogCategoryLinkManagementV1","description":""},{"name":"catalogCategoryLinkRepositoryV1","description":""},{"name":"catalogProductWebsiteLinkRepositoryV1","description":"Interface ProductWebsiteLinkRepositoryInterface"},{"name":"catalogProductRenderListV1","description":"Interface which provides product renders information for products"},{"name":"catalogInventoryStockRegistryV1","description":"Interface StockRegistryInterface"},{"name":"bundleProductLinkManagementV1","description":"Interface for Management of ProductLink"},{"name":"bundleProductOptionRepositoryV1","description":"Interface ProductOptionRepositoryInterface"},{"name":"bundleProductOptionTypeListV1","description":"Interface ProductOptionTypeListInterface"},{"name":"bundleProductOptionManagementV1","description":"Option manager for bundle products"},{"name":"quoteCartRepositoryV1","description":"Interface CartRepositoryInterface"},{"name":"quoteCartManagementV1","description":"Interface CartManagementInterface"},{"name":"quoteGuestCartRepositoryV1","description":"Cart Repository interface for guest carts."},{"name":"quoteGuestCartManagementV1","description":"Cart Management interface for guest carts."},{"name":"quoteShippingMethodManagementV1","description":"Interface ShippingMethodManagementInterface"},{"name":"quoteShipmentEstimationV1","description":"Interface ShipmentManagementInterface"},{"name":"quoteGuestShippingMethodManagementV1","description":"Shipping method management interface for guest carts."},{"name":"quoteGuestShipmentEstimationV1","description":"Interface GuestShipmentEstimationInterface"},{"name":"quoteCartItemRepositoryV1","description":"Interface CartItemRepositoryInterface"},{"name":"quoteGuestCartItemRepositoryV1","description":"Cart Item repository interface for guest carts."},{"name":"quotePaymentMethodManagementV1","description":"Interface PaymentMethodManagementInterface"},{"name":"quoteGuestPaymentMethodManagementV1","description":"Payment method management interface for guest carts."},{"name":"quoteBillingAddressManagementV1","description":"Interface BillingAddressManagementInterface"},{"name":"quoteGuestBillingAddressManagementV1","description":"Billing address management interface for guest carts."},{"name":"quoteCouponManagementV1","description":"Coupon management service interface."},{"name":"quoteGuestCouponManagementV1","description":"Coupon management interface for guest carts."},{"name":"quoteCartTotalRepositoryV1","description":"Interface CartTotalRepositoryInterface"},{"name":"quoteGuestCartTotalManagementV1","description":"Bundled API to collect totals for cart based on shipping/payment methods and additional data."},{"name":"quoteGuestCartTotalRepositoryV1","description":"Cart totals repository interface for guest carts."},{"name":"quoteCartTotalManagementV1","description":"Bundled API to collect totals for cart based on shipping/payment methods and additional data."},{"name":"searchV1","description":"Search API for all requests"},{"name":"salesOrderRepositoryV1","description":"Order repository interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer."},{"name":"salesOrderManagementV1","description":"Order management interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer."},{"name":"salesOrderAddressRepositoryV1","description":"Order address repository interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer."},{"name":"salesOrderItemRepositoryV1","description":"Order item repository interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer."},{"name":"salesInvoiceRepositoryV1","description":"Invoice repository interface. An invoice is a record of the receipt of payment for an order."},{"name":"salesInvoiceManagementV1","description":"Invoice management interface. An invoice is a record of the receipt of payment for an order."},{"name":"salesInvoiceCommentRepositoryV1","description":"Invoice comment repository interface. An invoice is a record of the receipt of payment for an order. An invoice can include comments that detail the invoice history."},{"name":"salesRefundInvoiceV1","description":"Interface RefundInvoiceInterface"},{"name":"salesCreditmemoManagementV1","description":"Credit memo add comment interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases."},{"name":"salesCreditmemoRepositoryV1","description":"Credit memo repository interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases."},{"name":"salesCreditmemoCommentRepositoryV1","description":"Credit memo comment repository interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases. A credit memo usually includes comments that detail why the credit memo amount was credited to the customer."},{"name":"salesRefundOrderV1","description":"Interface RefundOrderInterface"},{"name":"salesShipmentRepositoryV1","description":"Shipment repository interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package."},{"name":"salesShipmentManagementV1","description":"Shipment management interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package."},{"name":"salesShipmentCommentRepositoryV1","description":"Shipment comment repository interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package. A shipment document can contain comments."},{"name":"salesShipmentTrackRepositoryV1","description":"Shipment track repository interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package."},{"name":"salesShipOrderV1","description":"Class ShipOrderInterface"},{"name":"salesTransactionRepositoryV1","description":"Transaction repository interface. A transaction is an interaction between a merchant and a customer such as a purchase, a credit, a refund, and so on."},{"name":"salesInvoiceOrderV1","description":"Class InvoiceOrderInterface"},{"name":"checkoutGuestShippingInformationManagementV1","description":"Interface for managing guest shipping address information"},{"name":"checkoutShippingInformationManagementV1","description":"Interface for managing customer shipping address information"},{"name":"checkoutTotalsInformationManagementV1","description":"Interface for quote totals calculation"},{"name":"checkoutGuestTotalsInformationManagementV1","description":"Interface for guest quote totals calculation"},{"name":"checkoutGuestPaymentInformationManagementV1","description":"Interface for managing guest payment information"},{"name":"checkoutPaymentInformationManagementV1","description":"Interface for managing quote payment information"},{"name":"downloadableLinkRepositoryV1","description":"Interface LinkRepositoryInterface"},{"name":"downloadableSampleRepositoryV1","description":"Interface SampleRepositoryInterface"},{"name":"checkoutAgreementsCheckoutAgreementsRepositoryV1","description":"Interface CheckoutAgreementsRepositoryInterface"},{"name":"configurableProductLinkManagementV1","description":"Manage children products of configurable product"},{"name":"configurableProductConfigurableProductManagementV1","description":"Interface ConfigurableProductManagementInterface"},{"name":"configurableProductOptionRepositoryV1","description":"Manage options of configurable product"},{"name":"customerBalanceBalanceManagementV1","description":"Customer balance(store credit) operations"},{"name":"giftCardAccountGiftCardAccountManagementV1","description":"Interface GiftCardAccountManagementInterface"},{"name":"giftCardAccountGuestGiftCardAccountManagementV1","description":"Interface GuestGiftCardAccountManagementInterface"},{"name":"taxTaxRateRepositoryV1","description":"Tax rate CRUD interface."},{"name":"taxTaxRuleRepositoryV1","description":"Tax rule CRUD interface."},{"name":"taxTaxClassRepositoryV1","description":"Tax class CRUD interface."},{"name":"giftMessageCartRepositoryV1","description":"Interface CartRepositoryInterface"},{"name":"giftMessageItemRepositoryV1","description":"Interface ItemRepositoryInterface"},{"name":"giftMessageGuestCartRepositoryV1","description":"Interface GuestCartRepositoryInterface"},{"name":"giftMessageGuestItemRepositoryV1","description":"Interface GuestItemRepositoryInterface"},{"name":"giftWrappingWrappingRepositoryV1","description":"Interface WrappingRepositoryInterface"},{"name":"salesRuleRuleRepositoryV1","description":"Sales rule CRUD interface"},{"name":"salesRuleCouponRepositoryV1","description":"Coupon CRUD interface"},{"name":"salesRuleCouponManagementV1","description":"Coupon management interface"},{"name":"giftRegistryShippingMethodManagementV1","description":"Interface ShippingMethodManagementInterface"},{"name":"giftRegistryGuestCartShippingMethodManagementV1","description":"Interface ShippingMethodManagementInterface"},{"name":"rewardRewardManagementV1","description":"Interface RewardManagementInterface"},{"name":"rmaTrackManagementV1","description":"Interface TrackManagementInterface"},{"name":"rmaRmaRepositoryV1","description":"Interface RmaRepositoryInterface"},{"name":"rmaCommentManagementV1","description":"Interface CommentRepositoryInterface"},{"name":"rmaRmaManagementV1","description":"Interface RmaManagementInterface"},{"name":"rmaRmaAttributesManagementV1","description":"Interface RmaAttributesManagementInterface"},{"name":"integrationAdminTokenServiceV1","description":"Interface providing token generation for Admins"},{"name":"integrationCustomerTokenServiceV1","description":"Interface providing token generation for Customers"},{"name":"testModule1AllSoapAndRestV1","description":""},{"name":"testModule1AllSoapAndRestV2","description":""},{"name":"testModule2SubsetRestV1","description":""},{"name":"testModule3ErrorV1","description":""},{"name":"testModule4DataObjectServiceV1","description":""},{"name":"testModule5AllSoapAndRestV1","description":"Both SOAP and REST Version ONE"},{"name":"testModule5OverrideServiceV1","description":""},{"name":"testModule5AllSoapAndRestV2","description":"Both SOAP and REST Version TWO"},{"name":"testModuleDefaultHydratorCustomerPersistenceV1","description":"Customer CRUD interface"},{"name":"testModuleJoinDirectivesTestRepositoryV1","description":"Interface TestRepositoryInterface"},{"name":"testModuleMSCAllSoapAndRestV1","description":""},{"name":"worldpayGuestPaymentInformationManagementProxyV1","description":"Interface GuestPaymentInformationManagementProxyInterface"}],"paths":{"/V1/store/storeViews":{"get":{"tags":["storeStoreRepositoryV1"],"description":"Retrieve list of all stores","operationId":"storeStoreRepositoryV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/store-data-store-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/store/storeGroups":{"get":{"tags":["storeGroupRepositoryV1"],"description":"Retrieve list of all groups","operationId":"storeGroupRepositoryV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/store-data-group-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/store/websites":{"get":{"tags":["storeWebsiteRepositoryV1"],"description":"Retrieve list of all websites","operationId":"storeWebsiteRepositoryV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/store-data-website-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/store/storeConfigs":{"get":{"tags":["storeStoreConfigManagerV1"],"description":"","operationId":"storeStoreConfigManagerV1GetStoreConfigsGet","parameters":[{"name":"storeCodes","in":"query","type":"array","items":{"type":"string"},"required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/store-data-store-config-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/directory/currency":{"get":{"tags":["directoryCurrencyInformationAcquirerV1"],"description":"Get currency information for the store.","operationId":"directoryCurrencyInformationAcquirerV1GetCurrencyInfoGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/directory-data-currency-information-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/directory/countries":{"get":{"tags":["directoryCountryInformationAcquirerV1"],"description":"Get all countries and regions information for the store.","operationId":"directoryCountryInformationAcquirerV1GetCountriesInfoGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/directory-data-country-information-interface"}}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/directory/countries/{countryId}":{"get":{"tags":["directoryCountryInformationAcquirerV1"],"description":"Get country and region information for the store.","operationId":"directoryCountryInformationAcquirerV1GetCountryInfoGet","parameters":[{"name":"countryId","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/directory-data-country-information-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/eav/attribute-sets/list":{"get":{"tags":["eavAttributeSetRepositoryV1"],"description":"Retrieve list of Attribute Sets This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#AttributeSetRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"eavAttributeSetRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/eav/attribute-sets/{attributeSetId}":{"get":{"tags":["eavAttributeSetRepositoryV1"],"description":"Retrieve attribute set information based on given ID","operationId":"eavAttributeSetRepositoryV1GetGet","parameters":[{"name":"attributeSetId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["eavAttributeSetRepositoryV1"],"description":"Remove attribute set by given ID","operationId":"eavAttributeSetRepositoryV1DeleteByIdDelete","parameters":[{"name":"attributeSetId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["eavAttributeSetRepositoryV1"],"description":"Save attribute set data","operationId":"eavAttributeSetRepositoryV1SavePut","parameters":[{"name":"attributeSetId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["attributeSet"],"properties":{"attributeSet":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/eav/attribute-sets":{"post":{"tags":["eavAttributeSetManagementV1"],"description":"Create attribute set from data","operationId":"eavAttributeSetManagementV1CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entityTypeCode","attributeSet","skeletonId"],"properties":{"entityTypeCode":{"type":"string"},"attributeSet":{"$ref":"#/definitions/eav-data-attribute-set-interface"},"skeletonId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/{id}":{"get":{"tags":["customerGroupRepositoryV1"],"description":"Get customer group by group ID.","operationId":"customerGroupRepositoryV1GetByIdGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["customerGroupRepositoryV1"],"description":"Save customer group.","operationId":"customerGroupRepositoryV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["group"],"properties":{"group":{"$ref":"#/definitions/customer-data-group-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["customerGroupRepositoryV1"],"description":"Delete customer group by ID.","operationId":"customerGroupRepositoryV1DeleteByIdDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/search":{"get":{"tags":["customerGroupRepositoryV1"],"description":"Retrieve customer groups. The list of groups can be filtered to exclude the NOT_LOGGED_IN group using the first parameter and/or it can be filtered by tax class. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#GroupRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"customerGroupRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups":{"post":{"tags":["customerGroupRepositoryV1"],"description":"Save customer group.","operationId":"customerGroupRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["group"],"properties":{"group":{"$ref":"#/definitions/customer-data-group-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/default/{storeId}":{"get":{"tags":["customerGroupManagementV1"],"description":"Get default customer group.","operationId":"customerGroupManagementV1GetDefaultGroupGet","parameters":[{"name":"storeId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/default":{"get":{"tags":["customerGroupManagementV1"],"description":"Get default customer group.","operationId":"customerGroupManagementV1GetDefaultGroupGet","parameters":[{"name":"storeId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/{id}/permissions":{"get":{"tags":["customerGroupManagementV1"],"description":"Check if customer group can be deleted.","operationId":"customerGroupManagementV1IsReadonlyGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customerGroups/default/{id}":{"put":{"tags":["customerCustomerGroupConfigV1"],"description":"Set system default customer group.","operationId":"customerCustomerGroupConfigV1SetDefaultCustomerGroupPut","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customer/attribute/{attributeCode}":{"get":{"tags":["customerCustomerMetadataV1"],"description":"Retrieve attribute metadata.","operationId":"customerCustomerMetadataV1GetAttributeMetadataGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customer/form/{formCode}":{"get":{"tags":["customerCustomerMetadataV1"],"description":"Retrieve all attributes filtered by form code","operationId":"customerCustomerMetadataV1GetAttributesGet","parameters":[{"name":"formCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customer":{"get":{"tags":["customerCustomerMetadataV1"],"description":"Get all attribute metadata.","operationId":"customerCustomerMetadataV1GetAllAttributesMetadataGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customer/custom":{"get":{"tags":["customerCustomerMetadataV1"],"description":"Get custom attributes metadata for the given data interface.","operationId":"customerCustomerMetadataV1GetCustomAttributesMetadataGet","parameters":[{"name":"dataInterfaceName","in":"query","type":"string","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customerAddress/attribute/{attributeCode}":{"get":{"tags":["customerAddressMetadataV1"],"description":"Retrieve attribute metadata.","operationId":"customerAddressMetadataV1GetAttributeMetadataGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customerAddress/form/{formCode}":{"get":{"tags":["customerAddressMetadataV1"],"description":"Retrieve all attributes filtered by form code","operationId":"customerAddressMetadataV1GetAttributesGet","parameters":[{"name":"formCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customerAddress":{"get":{"tags":["customerAddressMetadataV1"],"description":"Get all attribute metadata.","operationId":"customerAddressMetadataV1GetAllAttributesMetadataGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/attributeMetadata/customerAddress/custom":{"get":{"tags":["customerAddressMetadataV1"],"description":"Get custom attributes metadata for the given data interface.","operationId":"customerAddressMetadataV1GetCustomAttributesMetadataGet","parameters":[{"name":"dataInterfaceName","in":"query","type":"string","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}":{"get":{"tags":["customerCustomerRepositoryV1"],"description":"Get customer by customer ID.","operationId":"customerCustomerRepositoryV1GetByIdGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["customerCustomerRepositoryV1"],"description":"Delete customer by ID.","operationId":"customerCustomerRepositoryV1DeleteByIdDelete","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{id}":{"put":{"tags":["customerCustomerRepositoryV1"],"description":"Create or update a customer.","operationId":"customerCustomerRepositoryV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"},"passwordHash":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/me":{"put":{"tags":["customerCustomerRepositoryV1"],"description":"Create or update a customer.","operationId":"customerCustomerRepositoryV1SavePut","parameters":[{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"},"passwordHash":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["customerCustomerRepositoryV1"],"description":"Get customer by customer ID.","operationId":"customerCustomerRepositoryV1GetByIdGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/search":{"get":{"tags":["customerCustomerRepositoryV1"],"description":"Retrieve customers which match a specified criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#CustomerRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"customerCustomerRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers":{"post":{"tags":["customerAccountManagementV1"],"description":"Create customer account. Perform necessary business operations like sending email.","operationId":"customerAccountManagementV1CreateAccountPost","parameters":[{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"},"password":{"type":"string"},"redirectUrl":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/me/activate":{"put":{"tags":["customerAccountManagementV1"],"description":"Activate a customer account using a key that was sent in a confirmation email.","operationId":"customerAccountManagementV1ActivateByIdPut","parameters":[{"name":"$body","in":"body","schema":{"required":["confirmationKey"],"properties":{"confirmationKey":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{email}/activate":{"put":{"tags":["customerAccountManagementV1"],"description":"Activate a customer account using a key that was sent in a confirmation email.","operationId":"customerAccountManagementV1ActivatePut","parameters":[{"name":"email","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["confirmationKey"],"properties":{"confirmationKey":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/me/password":{"put":{"tags":["customerAccountManagementV1"],"description":"Change customer password.","operationId":"customerAccountManagementV1ChangePasswordByIdPut","parameters":[{"name":"$body","in":"body","schema":{"required":["currentPassword","newPassword"],"properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/password/resetLinkToken/{resetPasswordLinkToken}":{"get":{"tags":["customerAccountManagementV1"],"description":"Check if password reset token is valid.","operationId":"customerAccountManagementV1ValidateResetPasswordLinkTokenGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true},{"name":"resetPasswordLinkToken","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"True if the token is valid"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/password":{"put":{"tags":["customerAccountManagementV1"],"description":"Send an email to the customer with a password reset link.","operationId":"customerAccountManagementV1InitiatePasswordResetPut","parameters":[{"name":"$body","in":"body","schema":{"required":["email","template"],"properties":{"email":{"type":"string"},"template":{"type":"string"},"websiteId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/confirm":{"get":{"tags":["customerAccountManagementV1"],"description":"Gets the account confirmation status.","operationId":"customerAccountManagementV1GetConfirmationStatusGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/confirm":{"post":{"tags":["customerAccountManagementV1"],"description":"Resend confirmation email.","operationId":"customerAccountManagementV1ResendConfirmationPost","parameters":[{"name":"$body","in":"body","schema":{"required":["email","websiteId"],"properties":{"email":{"type":"string"},"websiteId":{"type":"integer"},"redirectUrl":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/validate":{"put":{"tags":["customerAccountManagementV1"],"description":"Validate customer data.","operationId":"customerAccountManagementV1ValidatePut","parameters":[{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-validation-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/permissions/readonly":{"get":{"tags":["customerAccountManagementV1"],"description":"Check if customer can be deleted.","operationId":"customerAccountManagementV1IsReadonlyGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/isEmailAvailable":{"post":{"tags":["customerAccountManagementV1"],"description":"Check if given email is associated with a customer account in given website.","operationId":"customerAccountManagementV1IsEmailAvailablePost","parameters":[{"name":"$body","in":"body","schema":{"required":["customerEmail"],"properties":{"customerEmail":{"type":"string"},"websiteId":{"type":"integer","description":"If not set, will use the current websiteId"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/me/billingAddress":{"get":{"tags":["customerAccountManagementV1"],"description":"Retrieve default billing address for the given customerId.","operationId":"customerAccountManagementV1GetDefaultBillingAddressGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/billingAddress":{"get":{"tags":["customerAccountManagementV1"],"description":"Retrieve default billing address for the given customerId.","operationId":"customerAccountManagementV1GetDefaultBillingAddressGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/me/shippingAddress":{"get":{"tags":["customerAccountManagementV1"],"description":"Retrieve default shipping address for the given customerId.","operationId":"customerAccountManagementV1GetDefaultShippingAddressGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/shippingAddress":{"get":{"tags":["customerAccountManagementV1"],"description":"Retrieve default shipping address for the given customerId.","operationId":"customerAccountManagementV1GetDefaultShippingAddressGet","parameters":[{"name":"customerId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/addresses/{addressId}":{"get":{"tags":["customerAddressRepositoryV1"],"description":"Retrieve customer address.","operationId":"customerAddressRepositoryV1GetByIdGet","parameters":[{"name":"addressId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/addresses/{addressId}":{"delete":{"tags":["customerAddressRepositoryV1"],"description":"Delete customer address by ID.","operationId":"customerAddressRepositoryV1DeleteByIdDelete","parameters":[{"name":"addressId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/modules":{"get":{"tags":["backendModuleServiceV1"],"description":"Returns an array of enabled modules","operationId":"backendModuleServiceV1GetModulesGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"type":"string"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsPage/{pageId}":{"get":{"tags":["cmsPageRepositoryV1"],"description":"Retrieve page.","operationId":"cmsPageRepositoryV1GetByIdGet","parameters":[{"name":"pageId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-page-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["cmsPageRepositoryV1"],"description":"Delete page by ID.","operationId":"cmsPageRepositoryV1DeleteByIdDelete","parameters":[{"name":"pageId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsPage/search":{"get":{"tags":["cmsPageRepositoryV1"],"description":"Retrieve pages matching the specified criteria.","operationId":"cmsPageRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-page-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsPage":{"post":{"tags":["cmsPageRepositoryV1"],"description":"Save page.","operationId":"cmsPageRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["page"],"properties":{"page":{"$ref":"#/definitions/cms-data-page-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-page-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsPage/{id}":{"put":{"tags":["cmsPageRepositoryV1"],"description":"Save page.","operationId":"cmsPageRepositoryV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["page"],"properties":{"page":{"$ref":"#/definitions/cms-data-page-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-page-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsBlock/{blockId}":{"get":{"tags":["cmsBlockRepositoryV1"],"description":"Retrieve block.","operationId":"cmsBlockRepositoryV1GetByIdGet","parameters":[{"name":"blockId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-block-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["cmsBlockRepositoryV1"],"description":"Delete block by ID.","operationId":"cmsBlockRepositoryV1DeleteByIdDelete","parameters":[{"name":"blockId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsBlock/search":{"get":{"tags":["cmsBlockRepositoryV1"],"description":"Retrieve blocks matching the specified criteria.","operationId":"cmsBlockRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-block-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsBlock":{"post":{"tags":["cmsBlockRepositoryV1"],"description":"Save block.","operationId":"cmsBlockRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["block"],"properties":{"block":{"$ref":"#/definitions/cms-data-block-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-block-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/cmsBlock/{id}":{"put":{"tags":["cmsBlockRepositoryV1"],"description":"Save block.","operationId":"cmsBlockRepositoryV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["block"],"properties":{"block":{"$ref":"#/definitions/cms-data-block-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/cms-data-block-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products":{"post":{"tags":["catalogProductRepositoryV1"],"description":"Create product","operationId":"catalogProductRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["product"],"properties":{"product":{"$ref":"#/definitions/catalog-data-product-interface"},"saveOptions":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["catalogProductRepositoryV1"],"description":"Get product list","operationId":"catalogProductRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}":{"put":{"tags":["catalogProductRepositoryV1"],"description":"Create product","operationId":"catalogProductRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["product"],"properties":{"product":{"$ref":"#/definitions/catalog-data-product-interface"},"saveOptions":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["catalogProductRepositoryV1"],"description":"","operationId":"catalogProductRepositoryV1DeleteByIdDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"Will returned True if deleted"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["catalogProductRepositoryV1"],"description":"Get info about product by product SKU","operationId":"catalogProductRepositoryV1GetGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"editMode","in":"query","type":"boolean","required":false},{"name":"storeId","in":"query","type":"integer","required":false},{"name":"forceReload","in":"query","type":"boolean","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attributes/types":{"get":{"tags":["catalogProductAttributeTypesListV1"],"description":"Retrieve list of product attribute types","operationId":"catalogProductAttributeTypesListV1GetItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-attribute-type-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attributes/{attributeCode}":{"get":{"tags":["catalogProductAttributeRepositoryV1"],"description":"Retrieve specific attribute","operationId":"catalogProductAttributeRepositoryV1GetGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogProductAttributeRepositoryV1"],"description":"Save attribute data","operationId":"catalogProductAttributeRepositoryV1SavePut","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["attribute"],"properties":{"attribute":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["catalogProductAttributeRepositoryV1"],"description":"Delete Attribute by id","operationId":"catalogProductAttributeRepositoryV1DeleteByIdDelete","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attributes":{"get":{"tags":["catalogProductAttributeRepositoryV1"],"description":"Retrieve all attributes for entity type","operationId":"catalogProductAttributeRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-attribute-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["catalogProductAttributeRepositoryV1"],"description":"Save attribute data","operationId":"catalogProductAttributeRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["attribute"],"properties":{"attribute":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/attributes/{attributeCode}":{"get":{"tags":["catalogCategoryAttributeRepositoryV1"],"description":"Retrieve specific attribute","operationId":"catalogCategoryAttributeRepositoryV1GetGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-attribute-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/attributes":{"get":{"tags":["catalogCategoryAttributeRepositoryV1"],"description":"Retrieve all attributes for entity type","operationId":"catalogCategoryAttributeRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-attribute-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/attributes/{attributeCode}/options":{"get":{"tags":["catalogCategoryAttributeOptionManagementV1"],"description":"Retrieve list of attribute options","operationId":"catalogCategoryAttributeOptionManagementV1GetItemsGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/eav-data-attribute-option-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/types":{"get":{"tags":["catalogProductTypeListV1"],"description":"Retrieve available product types","operationId":"catalogProductTypeListV1GetProductTypesGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-type-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/sets/list":{"get":{"tags":["catalogAttributeSetRepositoryV1"],"description":"Retrieve list of Attribute Sets","operationId":"catalogAttributeSetRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/{attributeSetId}":{"get":{"tags":["catalogAttributeSetRepositoryV1"],"description":"Retrieve attribute set information based on given ID","operationId":"catalogAttributeSetRepositoryV1GetGet","parameters":[{"name":"attributeSetId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["catalogAttributeSetRepositoryV1"],"description":"Remove attribute set by given ID","operationId":"catalogAttributeSetRepositoryV1DeleteByIdDelete","parameters":[{"name":"attributeSetId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogAttributeSetRepositoryV1"],"description":"Save attribute set data","operationId":"catalogAttributeSetRepositoryV1SavePut","parameters":[{"name":"attributeSetId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["attributeSet"],"properties":{"attributeSet":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets":{"post":{"tags":["catalogAttributeSetManagementV1"],"description":"Create attribute set from data","operationId":"catalogAttributeSetManagementV1CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["attributeSet","skeletonId"],"properties":{"attributeSet":{"$ref":"#/definitions/eav-data-attribute-set-interface"},"skeletonId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/{attributeSetId}/attributes":{"get":{"tags":["catalogProductAttributeManagementV1"],"description":"Retrieve related attributes based on given attribute set ID","operationId":"catalogProductAttributeManagementV1GetAttributesGet","parameters":[{"name":"attributeSetId","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/attributes":{"post":{"tags":["catalogProductAttributeManagementV1"],"description":"Assign attribute to attribute set","operationId":"catalogProductAttributeManagementV1AssignPost","parameters":[{"name":"$body","in":"body","schema":{"required":["attributeSetId","attributeGroupId","attributeCode","sortOrder"],"properties":{"attributeSetId":{"type":"integer"},"attributeGroupId":{"type":"integer"},"attributeCode":{"type":"string"},"sortOrder":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/{attributeSetId}/attributes/{attributeCode}":{"delete":{"tags":["catalogProductAttributeManagementV1"],"description":"Remove attribute from attribute set","operationId":"catalogProductAttributeManagementV1UnassignDelete","parameters":[{"name":"attributeSetId","in":"path","type":"string","required":true},{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/groups/list":{"get":{"tags":["catalogProductAttributeGroupRepositoryV1"],"description":"Retrieve list of attribute groups","operationId":"catalogProductAttributeGroupRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-group-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/groups":{"post":{"tags":["catalogProductAttributeGroupRepositoryV1"],"description":"Save attribute group","operationId":"catalogProductAttributeGroupRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["group"],"properties":{"group":{"$ref":"#/definitions/eav-data-attribute-group-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/{attributeSetId}/groups":{"put":{"tags":["catalogProductAttributeGroupRepositoryV1"],"description":"Save attribute group","operationId":"catalogProductAttributeGroupRepositoryV1SavePut","parameters":[{"name":"attributeSetId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["group"],"properties":{"group":{"$ref":"#/definitions/eav-data-attribute-group-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/eav-data-attribute-group-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attribute-sets/groups/{groupId}":{"delete":{"tags":["catalogProductAttributeGroupRepositoryV1"],"description":"Remove attribute group by id","operationId":"catalogProductAttributeGroupRepositoryV1DeleteByIdDelete","parameters":[{"name":"groupId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attributes/{attributeCode}/options":{"get":{"tags":["catalogProductAttributeOptionManagementV1"],"description":"Retrieve list of attribute options","operationId":"catalogProductAttributeOptionManagementV1GetItemsGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/eav-data-attribute-option-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["catalogProductAttributeOptionManagementV1"],"description":"Add option to attribute","operationId":"catalogProductAttributeOptionManagementV1AddPost","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/eav-data-attribute-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/attributes/{attributeCode}/options/{optionId}":{"delete":{"tags":["catalogProductAttributeOptionManagementV1"],"description":"Delete option from attribute","operationId":"catalogProductAttributeOptionManagementV1DeleteDelete","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/media/types/{attributeSetName}":{"get":{"tags":["catalogProductMediaAttributeManagementV1"],"description":"Retrieve the list of media attributes (fronted input type is media_image) assigned to the given attribute set.","operationId":"catalogProductMediaAttributeManagementV1GetListGet","parameters":[{"name":"attributeSetName","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"list of media attributes","items":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/media/{entryId}":{"get":{"tags":["catalogProductAttributeMediaGalleryManagementV1"],"description":"Return information about gallery entry","operationId":"catalogProductAttributeMediaGalleryManagementV1GetGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"entryId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogProductAttributeMediaGalleryManagementV1"],"description":"Update gallery entry","operationId":"catalogProductAttributeMediaGalleryManagementV1UpdatePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"entryId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entry"],"properties":{"entry":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["catalogProductAttributeMediaGalleryManagementV1"],"description":"Remove gallery entry","operationId":"catalogProductAttributeMediaGalleryManagementV1RemoveDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"entryId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/media":{"post":{"tags":["catalogProductAttributeMediaGalleryManagementV1"],"description":"Create new gallery entry","operationId":"catalogProductAttributeMediaGalleryManagementV1CreatePost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entry"],"properties":{"entry":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"gallery entry ID"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["catalogProductAttributeMediaGalleryManagementV1"],"description":"Retrieve the list of gallery entries associated with given product","operationId":"catalogProductAttributeMediaGalleryManagementV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/group-prices/{customerGroupId}/tiers":{"get":{"tags":["catalogProductTierPriceManagementV1"],"description":"Get tier price of product","operationId":"catalogProductTierPriceManagementV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"customerGroupId","in":"path","type":"string","required":true,"description":"'all' can be used to specify 'ALL GROUPS'"}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-tier-price-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/group-prices/{customerGroupId}/tiers/{qty}/price/{price}":{"post":{"tags":["catalogProductTierPriceManagementV1"],"description":"Create tier price for product","operationId":"catalogProductTierPriceManagementV1AddPost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"customerGroupId","in":"path","type":"string","required":true,"description":"'all' can be used to specify 'ALL GROUPS'"},{"name":"price","in":"path","type":"number","required":true},{"name":"qty","in":"path","type":"number","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/group-prices/{customerGroupId}/tiers/{qty}":{"delete":{"tags":["catalogProductTierPriceManagementV1"],"description":"Remove tier price from product","operationId":"catalogProductTierPriceManagementV1RemoveDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"customerGroupId","in":"path","type":"string","required":true,"description":"'all' can be used to specify 'ALL GROUPS'"},{"name":"qty","in":"path","type":"number","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/tier-prices-information":{"post":{"tags":["catalogTierPriceStorageV1"],"description":"Return product prices. In case of at least one of skus is not found exception will be thrown.","operationId":"catalogTierPriceStorageV1GetPost","parameters":[{"name":"$body","in":"body","schema":{"required":["skus"],"properties":{"skus":{"type":"array","items":{"type":"string"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-tier-price-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/tier-prices":{"post":{"tags":["catalogTierPriceStorageV1"],"description":"Add or update product prices. If any items will have invalid price, price type, website id, sku, customer group or quantity, they will be marked as failed and excluded from update list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogTierPriceStorageV1UpdatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-tier-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogTierPriceStorageV1"],"description":"Remove existing tier prices and replace them with the new ones. If any items will have invalid price, price type, website id, sku, customer group or quantity, they will be marked as failed and excluded from replace list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogTierPriceStorageV1ReplacePut","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-tier-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/tier-prices-delete":{"post":{"tags":["catalogTierPriceStorageV1"],"description":"Delete product tier prices. If any items will have invalid price, price type, website id, sku, customer group or quantity, they will be marked as failed and excluded from delete list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogTierPriceStorageV1DeletePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-tier-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/base-prices-information":{"post":{"tags":["catalogBasePriceStorageV1"],"description":"Return product prices. In case of at least one of skus is not found exception will be thrown.","operationId":"catalogBasePriceStorageV1GetPost","parameters":[{"name":"$body","in":"body","schema":{"required":["skus"],"properties":{"skus":{"type":"array","items":{"type":"string"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-base-price-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/base-prices":{"post":{"tags":["catalogBasePriceStorageV1"],"description":"Add or update product prices. Input item should correspond \\Magento\\Catalog\\Api\\Data\\CostInterface. If any items will have invalid price, store id or sku, they will be marked as failed and excluded from update list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogBasePriceStorageV1UpdatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-base-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/cost-information":{"post":{"tags":["catalogCostStorageV1"],"description":"Return product prices. In case of at least one of skus is not found exception will be thrown.","operationId":"catalogCostStorageV1GetPost","parameters":[{"name":"$body","in":"body","schema":{"required":["skus"],"properties":{"skus":{"type":"array","items":{"type":"string"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-cost-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/cost":{"post":{"tags":["catalogCostStorageV1"],"description":"Add or update product cost. Input item should correspond to \\Magento\\Catalog\\Api\\Data\\CostInterface. If any items will have invalid cost, store id or sku, they will be marked as failed and excluded from update list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogCostStorageV1UpdatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-cost-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/cost-delete":{"post":{"tags":["catalogCostStorageV1"],"description":"Delete product cost. In case of at least one of skus is not found exception will be thrown. If error occurred during the delete exception will be thrown.","operationId":"catalogCostStorageV1DeletePost","parameters":[{"name":"$body","in":"body","schema":{"required":["skus"],"properties":{"skus":{"type":"array","items":{"type":"string"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"Will return True if deleted."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/special-price-information":{"post":{"tags":["catalogSpecialPriceStorageV1"],"description":"Return product's special price. In case of at least one of skus is not found exception will be thrown.","operationId":"catalogSpecialPriceStorageV1GetPost","parameters":[{"name":"$body","in":"body","schema":{"required":["skus"],"properties":{"skus":{"type":"array","items":{"type":"string"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-special-price-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/special-price":{"post":{"tags":["catalogSpecialPriceStorageV1"],"description":"Add or update product's special price. If any items will have invalid price, store id, sku or dates, they will be marked as failed and excluded from update list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the update exception will be thrown.","operationId":"catalogSpecialPriceStorageV1UpdatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-special-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/special-price-delete":{"post":{"tags":["catalogSpecialPriceStorageV1"],"description":"Delete product's special price. If any items will have invalid price, store id, sku or dates, they will be marked as failed and excluded from delete list and \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface[] with problem description will be returned. If there were no failed items during update empty array will be returned. If error occurred during the delete exception will be thrown.","operationId":"catalogSpecialPriceStorageV1DeletePost","parameters":[{"name":"$body","in":"body","schema":{"required":["prices"],"properties":{"prices":{"type":"array","items":{"$ref":"#/definitions/catalog-data-special-price-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-price-update-result-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/{categoryId}":{"delete":{"tags":["catalogCategoryRepositoryV1"],"description":"Delete category by identifier","operationId":"catalogCategoryRepositoryV1DeleteByIdentifierDelete","parameters":[{"name":"categoryId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"Will returned True if deleted"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["catalogCategoryRepositoryV1"],"description":"Get info about category by category id","operationId":"catalogCategoryRepositoryV1GetGet","parameters":[{"name":"categoryId","in":"path","type":"integer","required":true},{"name":"storeId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories":{"post":{"tags":["catalogCategoryRepositoryV1"],"description":"Create category service","operationId":"catalogCategoryRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["category"],"properties":{"category":{"$ref":"#/definitions/catalog-data-category-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["catalogCategoryManagementV1"],"description":"Retrieve list of categories","operationId":"catalogCategoryManagementV1GetTreeGet","parameters":[{"name":"rootCategoryId","in":"query","type":"integer","required":false},{"name":"depth","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-tree-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/{id}":{"put":{"tags":["catalogCategoryRepositoryV1"],"description":"Create category service","operationId":"catalogCategoryRepositoryV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["category"],"properties":{"category":{"$ref":"#/definitions/catalog-data-category-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/{categoryId}/move":{"put":{"tags":["catalogCategoryManagementV1"],"description":"Move category","operationId":"catalogCategoryManagementV1MovePut","parameters":[{"name":"categoryId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["parentId"],"properties":{"parentId":{"type":"integer"},"afterId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/list":{"get":{"tags":["catalogCategoryListV1"],"description":"Get category list","operationId":"catalogCategoryListV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-category-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/options/types":{"get":{"tags":["catalogProductCustomOptionTypeListV1"],"description":"Get custom option types","operationId":"catalogProductCustomOptionTypeListV1GetItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-custom-option-type-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/options":{"get":{"tags":["catalogProductCustomOptionRepositoryV1"],"description":"Get the list of custom options for a specific product","operationId":"catalogProductCustomOptionRepositoryV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/options/{optionId}":{"get":{"tags":["catalogProductCustomOptionRepositoryV1"],"description":"Get custom option for a specific product","operationId":"catalogProductCustomOptionRepositoryV1GetGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["catalogProductCustomOptionRepositoryV1"],"description":"","operationId":"catalogProductCustomOptionRepositoryV1DeleteByIdentifierDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/options":{"post":{"tags":["catalogProductCustomOptionRepositoryV1"],"description":"Save Custom Option","operationId":"catalogProductCustomOptionRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/options/{optionId}":{"put":{"tags":["catalogProductCustomOptionRepositoryV1"],"description":"Save Custom Option","operationId":"catalogProductCustomOptionRepositoryV1SavePut","parameters":[{"name":"optionId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/links/types":{"get":{"tags":["catalogProductLinkTypeListV1"],"description":"Retrieve information about available product link types","operationId":"catalogProductLinkTypeListV1GetItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-link-type-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/links/{type}/attributes":{"get":{"tags":["catalogProductLinkTypeListV1"],"description":"Provide a list of the product link type attributes","operationId":"catalogProductLinkTypeListV1GetItemAttributesGet","parameters":[{"name":"type","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-link-attribute-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/links/{type}":{"get":{"tags":["catalogProductLinkManagementV1"],"description":"Provide the list of links for a specific product","operationId":"catalogProductLinkManagementV1GetLinkedItemsByTypeGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"type","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-link-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/links":{"post":{"tags":["catalogProductLinkManagementV1"],"description":"Assign a product link to another product","operationId":"catalogProductLinkManagementV1SetProductLinksPost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-link-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogProductLinkRepositoryV1"],"description":"Save product link","operationId":"catalogProductLinkRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/catalog-data-product-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/links/{type}/{linkedProductSku}":{"delete":{"tags":["catalogProductLinkRepositoryV1"],"description":"","operationId":"catalogProductLinkRepositoryV1DeleteByIdDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"type","in":"path","type":"string","required":true},{"name":"linkedProductSku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/{categoryId}/products":{"get":{"tags":["catalogCategoryLinkManagementV1"],"description":"Get products assigned to category","operationId":"catalogCategoryLinkManagementV1GetAssignedProductsGet","parameters":[{"name":"categoryId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-category-product-link-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["catalogCategoryLinkRepositoryV1"],"description":"Assign a product to the required category","operationId":"catalogCategoryLinkRepositoryV1SavePost","parameters":[{"name":"categoryId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["productLink"],"properties":{"productLink":{"$ref":"#/definitions/catalog-data-category-product-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if assigned"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogCategoryLinkRepositoryV1"],"description":"Assign a product to the required category","operationId":"catalogCategoryLinkRepositoryV1SavePut","parameters":[{"name":"categoryId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["productLink"],"properties":{"productLink":{"$ref":"#/definitions/catalog-data-category-product-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if assigned"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/categories/{categoryId}/products/{sku}":{"delete":{"tags":["catalogCategoryLinkRepositoryV1"],"description":"Remove the product assignment from the category by category id and sku","operationId":"catalogCategoryLinkRepositoryV1DeleteByIdsDelete","parameters":[{"name":"categoryId","in":"path","type":"string","required":true},{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if products successfully deleted"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/websites":{"post":{"tags":["catalogProductWebsiteLinkRepositoryV1"],"description":"Assign a product to the website","operationId":"catalogProductWebsiteLinkRepositoryV1SavePost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["productWebsiteLink"],"properties":{"productWebsiteLink":{"$ref":"#/definitions/catalog-data-product-website-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if website successfully assigned to product"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["catalogProductWebsiteLinkRepositoryV1"],"description":"Assign a product to the website","operationId":"catalogProductWebsiteLinkRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["productWebsiteLink"],"properties":{"productWebsiteLink":{"$ref":"#/definitions/catalog-data-product-website-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if website successfully assigned to product"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/websites/{websiteId}":{"delete":{"tags":["catalogProductWebsiteLinkRepositoryV1"],"description":"Remove the website assignment from the product by product sku","operationId":"catalogProductWebsiteLinkRepositoryV1DeleteByIdDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"websiteId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"will returned True if website successfully unassigned from product"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products-render-info":{"get":{"tags":["catalogProductRenderListV1"],"description":"Collect and retrieve the list of product render info This info contains raw prices and formated prices, product name, stock status, store_id, etc","operationId":"catalogProductRenderListV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."},{"name":"storeId","in":"query","type":"integer","required":true},{"name":"currencyCode","in":"query","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-data-product-render-search-results-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/stockItems/{productSku}":{"get":{"tags":["catalogInventoryStockRegistryV1"],"description":"","operationId":"catalogInventoryStockRegistryV1GetStockItemBySkuGet","parameters":[{"name":"productSku","in":"path","type":"string","required":true},{"name":"scopeId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-inventory-data-stock-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{productSku}/stockItems/{itemId}":{"put":{"tags":["catalogInventoryStockRegistryV1"],"description":"","operationId":"catalogInventoryStockRegistryV1UpdateStockItemBySkuPut","parameters":[{"name":"productSku","in":"path","type":"string","required":true},{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["stockItem"],"properties":{"stockItem":{"$ref":"#/definitions/catalog-inventory-data-stock-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/stockItems/lowStock/":{"get":{"tags":["catalogInventoryStockRegistryV1"],"description":"Retrieves a list of SKU's with low inventory qty","operationId":"catalogInventoryStockRegistryV1GetLowStockItemsGet","parameters":[{"name":"scopeId","in":"query","type":"integer","required":true},{"name":"qty","in":"query","type":"number","required":true},{"name":"currentPage","in":"query","type":"integer","required":false},{"name":"pageSize","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-inventory-data-stock-status-collection-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/stockStatuses/{productSku}":{"get":{"tags":["catalogInventoryStockRegistryV1"],"description":"","operationId":"catalogInventoryStockRegistryV1GetStockStatusBySkuGet","parameters":[{"name":"productSku","in":"path","type":"string","required":true},{"name":"scopeId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/catalog-inventory-data-stock-status-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{sku}/links/{optionId}":{"post":{"tags":["bundleProductLinkManagementV1"],"description":"Add child product to specified Bundle option by product sku","operationId":"bundleProductLinkManagementV1AddChildByProductSkuPost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["linkedProduct"],"properties":{"linkedProduct":{"$ref":"#/definitions/bundle-data-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{sku}/links/{id}":{"put":{"tags":["bundleProductLinkManagementV1"],"description":"","operationId":"bundleProductLinkManagementV1SaveChildPut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["linkedProduct"],"properties":{"linkedProduct":{"$ref":"#/definitions/bundle-data-link-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{productSku}/children":{"get":{"tags":["bundleProductLinkManagementV1"],"description":"Get all children for Bundle product","operationId":"bundleProductLinkManagementV1GetChildrenGet","parameters":[{"name":"productSku","in":"path","type":"string","required":true},{"name":"optionId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/bundle-data-link-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{sku}/options/{optionId}/children/{childSku}":{"delete":{"tags":["bundleProductLinkManagementV1"],"description":"Remove product from Bundle product option","operationId":"bundleProductLinkManagementV1RemoveChildDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true},{"name":"childSku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{sku}/options/all":{"get":{"tags":["bundleProductOptionRepositoryV1"],"description":"Get all options for bundle product","operationId":"bundleProductOptionRepositoryV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/bundle-data-option-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/{sku}/options/{optionId}":{"get":{"tags":["bundleProductOptionRepositoryV1"],"description":"Get option for bundle product","operationId":"bundleProductOptionRepositoryV1GetGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/bundle-data-option-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["bundleProductOptionRepositoryV1"],"description":"Remove bundle option","operationId":"bundleProductOptionRepositoryV1DeleteByIdDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"optionId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/options/types":{"get":{"tags":["bundleProductOptionTypeListV1"],"description":"Get all types for options for bundle products","operationId":"bundleProductOptionTypeListV1GetItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/bundle-data-option-type-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/options/add":{"post":{"tags":["bundleProductOptionManagementV1"],"description":"Add new option for bundle product","operationId":"bundleProductOptionManagementV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/bundle-data-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/bundle-products/options/{optionId}":{"put":{"tags":["bundleProductOptionManagementV1"],"description":"Add new option for bundle product","operationId":"bundleProductOptionManagementV1SavePut","parameters":[{"name":"optionId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/bundle-data-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}":{"get":{"tags":["quoteCartRepositoryV1"],"description":"Enables an administrative user to return information for a specified cart.","operationId":"quoteCartRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["quoteCartManagementV1"],"description":"Assigns a specified customer to a specified shopping cart.","operationId":"quoteCartManagementV1AssignCustomerPut","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["customerId","storeId"],"properties":{"customerId":{"type":"integer","description":"The customer ID."},"storeId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/search":{"get":{"tags":["quoteCartRepositoryV1"],"description":"Enables administrative users to list carts that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#CartRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"quoteCartRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine":{"put":{"tags":["quoteCartRepositoryV1"],"description":"Save quote","operationId":"quoteCartRepositoryV1SavePut","parameters":[{"name":"$body","in":"body","schema":{"required":["quote"],"properties":{"quote":{"$ref":"#/definitions/quote-data-cart-interface"}},"type":"object"}}],"responses":{"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteCartManagementV1"],"description":"Creates an empty cart and quote for a specified customer if customer does not have a cart yet.","operationId":"quoteCartManagementV1CreateEmptyCartForCustomerPost","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"new cart ID if customer did not have a cart or ID of the existing cart otherwise."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["quoteCartManagementV1"],"description":"Returns information for the cart for a specified customer.","operationId":"quoteCartManagementV1GetCartForCustomerGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/":{"post":{"tags":["quoteCartManagementV1"],"description":"Creates an empty cart and quote for a guest.","operationId":"quoteCartManagementV1CreateEmptyCartPost","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Cart ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/customers/{customerId}/carts":{"post":{"tags":["quoteCartManagementV1"],"description":"Creates an empty cart and quote for a specified customer if customer does not have a cart yet.","operationId":"quoteCartManagementV1CreateEmptyCartForCustomerPost","parameters":[{"name":"customerId","in":"path","type":"integer","required":true,"description":"The customer ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"new cart ID if customer did not have a cart or ID of the existing cart otherwise."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/order":{"put":{"tags":["quoteCartManagementV1"],"description":"Places an order for a specified cart.","operationId":"quoteCartManagementV1PlaceOrderPut","parameters":[{"name":"$body","in":"body","schema":{"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/order":{"put":{"tags":["quoteCartManagementV1"],"description":"Places an order for a specified cart.","operationId":"quoteCartManagementV1PlaceOrderPut","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}":{"get":{"tags":["quoteGuestCartRepositoryV1"],"description":"Enable a guest user to return information for a specified cart.","operationId":"quoteGuestCartRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["quoteGuestCartManagementV1"],"description":"Assign a specified customer to a specified shopping cart.","operationId":"quoteGuestCartManagementV1AssignCustomerPut","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["customerId","storeId"],"properties":{"customerId":{"type":"integer","description":"The customer ID."},"storeId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts":{"post":{"tags":["quoteGuestCartManagementV1"],"description":"Enable an customer or guest user to create an empty cart and quote for an anonymous customer.","operationId":"quoteGuestCartManagementV1CreateEmptyCartPost","responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"Cart ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/order":{"put":{"tags":["quoteGuestCartManagementV1"],"description":"Place an order for a specified cart.","operationId":"quoteGuestCartManagementV1PlaceOrderPut","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/shipping-methods":{"get":{"tags":["quoteShippingMethodManagementV1"],"description":"Lists applicable shipping methods for a specified quote.","operationId":"quoteShippingMethodManagementV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The shopping cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/estimate-shipping-methods-by-address-id":{"post":{"tags":["quoteShippingMethodManagementV1"],"description":"Estimate shipping","operationId":"quoteShippingMethodManagementV1EstimateByAddressIdPost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The shopping cart ID."},{"name":"$body","in":"body","schema":{"required":["addressId"],"properties":{"addressId":{"type":"integer","description":"The estimate address id"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/shipping-methods":{"get":{"tags":["quoteShippingMethodManagementV1"],"description":"Lists applicable shipping methods for a specified quote.","operationId":"quoteShippingMethodManagementV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/estimate-shipping-methods-by-address-id":{"post":{"tags":["quoteShippingMethodManagementV1"],"description":"Estimate shipping","operationId":"quoteShippingMethodManagementV1EstimateByAddressIdPost","parameters":[{"name":"$body","in":"body","schema":{"required":["addressId"],"properties":{"addressId":{"type":"integer","description":"The estimate address id"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/estimate-shipping-methods":{"post":{"tags":["quoteShipmentEstimationV1"],"description":"Estimate shipping by address and return list of available shipping methods","operationId":"quoteShipmentEstimationV1EstimateByExtendedAddressPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/estimate-shipping-methods":{"post":{"tags":["quoteShipmentEstimationV1"],"description":"Estimate shipping by address and return list of available shipping methods","operationId":"quoteShipmentEstimationV1EstimateByExtendedAddressPost","parameters":[{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/shipping-methods":{"get":{"tags":["quoteGuestShippingMethodManagementV1"],"description":"List applicable shipping methods for a specified quote.","operationId":"quoteGuestShippingMethodManagementV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The shopping cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/estimate-shipping-methods":{"post":{"tags":["quoteGuestShipmentEstimationV1"],"description":"Estimate shipping by address and return list of available shipping methods","operationId":"quoteGuestShipmentEstimationV1EstimateByExtendedAddressPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/items":{"get":{"tags":["quoteCartItemRepositoryV1"],"description":"Lists items that are assigned to a specified cart.","operationId":"quoteCartItemRepositoryV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of items.","items":{"$ref":"#/definitions/quote-data-cart-item-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{quoteId}/items":{"post":{"tags":["quoteCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteCartItemRepositoryV1SavePost","parameters":[{"name":"quoteId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/items/{itemId}":{"put":{"tags":["quoteCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteCartItemRepositoryV1SavePut","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteCartItemRepositoryV1"],"description":"Removes the specified item from the specified cart.","operationId":"quoteCartItemRepositoryV1DeleteByIdDelete","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID of the item to be removed."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/items":{"get":{"tags":["quoteCartItemRepositoryV1"],"description":"Lists items that are assigned to a specified cart.","operationId":"quoteCartItemRepositoryV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of items.","items":{"$ref":"#/definitions/quote-data-cart-item-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteCartItemRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/items/{itemId}":{"put":{"tags":["quoteCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteCartItemRepositoryV1SavePut","parameters":[{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteCartItemRepositoryV1"],"description":"Removes the specified item from the specified cart.","operationId":"quoteCartItemRepositoryV1DeleteByIdDelete","parameters":[{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID of the item to be removed."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/items":{"get":{"tags":["quoteGuestCartItemRepositoryV1"],"description":"List items that are assigned to a specified cart.","operationId":"quoteGuestCartItemRepositoryV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of items.","items":{"$ref":"#/definitions/quote-data-cart-item-interface"}}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteGuestCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteGuestCartItemRepositoryV1SavePost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/items/{itemId}":{"put":{"tags":["quoteGuestCartItemRepositoryV1"],"description":"Add/update the specified cart item.","operationId":"quoteGuestCartItemRepositoryV1SavePut","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["cartItem"],"properties":{"cartItem":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteGuestCartItemRepositoryV1"],"description":"Remove the specified item from the specified cart.","operationId":"quoteGuestCartItemRepositoryV1DeleteByIdDelete","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID of the item to be removed."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/selected-payment-method":{"get":{"tags":["quotePaymentMethodManagementV1"],"description":"Returns the payment method for a specified shopping cart.","operationId":"quotePaymentMethodManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-payment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["quotePaymentMethodManagementV1"],"description":"Adds a specified payment method to a specified shopping cart.","operationId":"quotePaymentMethodManagementV1SetPut","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["method"],"properties":{"method":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"redirect url or error message."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/payment-methods":{"get":{"tags":["quotePaymentMethodManagementV1"],"description":"Lists available payment methods for a specified shopping cart. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#PaymentMethodManagementInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"quotePaymentMethodManagementV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of payment methods.","items":{"$ref":"#/definitions/quote-data-payment-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/selected-payment-method":{"get":{"tags":["quotePaymentMethodManagementV1"],"description":"Returns the payment method for a specified shopping cart.","operationId":"quotePaymentMethodManagementV1GetGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-payment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["quotePaymentMethodManagementV1"],"description":"Adds a specified payment method to a specified shopping cart.","operationId":"quotePaymentMethodManagementV1SetPut","parameters":[{"name":"$body","in":"body","schema":{"required":["method"],"properties":{"method":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"redirect url or error message."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/payment-methods":{"get":{"tags":["quotePaymentMethodManagementV1"],"description":"Lists available payment methods for a specified shopping cart. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#PaymentMethodManagementInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"quotePaymentMethodManagementV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of payment methods.","items":{"$ref":"#/definitions/quote-data-payment-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/selected-payment-method":{"get":{"tags":["quoteGuestPaymentMethodManagementV1"],"description":"Return the payment method for a specified shopping cart.","operationId":"quoteGuestPaymentMethodManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-payment-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["quoteGuestPaymentMethodManagementV1"],"description":"Add a specified payment method to a specified shopping cart.","operationId":"quoteGuestPaymentMethodManagementV1SetPut","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["method"],"properties":{"method":{"$ref":"#/definitions/quote-data-payment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Payment method ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/payment-methods":{"get":{"tags":["quoteGuestPaymentMethodManagementV1"],"description":"List available payment methods for a specified shopping cart. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#GuestPaymentMethodManagementInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"quoteGuestPaymentMethodManagementV1GetListGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"Array of payment methods.","items":{"$ref":"#/definitions/quote-data-payment-method-interface"}}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/billing-address":{"get":{"tags":["quoteBillingAddressManagementV1"],"description":"Returns the billing address for a specified quote.","operationId":"quoteBillingAddressManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteBillingAddressManagementV1"],"description":"Assigns a specified billing address to a specified cart.","operationId":"quoteBillingAddressManagementV1AssignPost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"},"useForShipping":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Address ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/billing-address":{"get":{"tags":["quoteBillingAddressManagementV1"],"description":"Returns the billing address for a specified quote.","operationId":"quoteBillingAddressManagementV1GetGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteBillingAddressManagementV1"],"description":"Assigns a specified billing address to a specified cart.","operationId":"quoteBillingAddressManagementV1AssignPost","parameters":[{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"},"useForShipping":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Address ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/billing-address":{"get":{"tags":["quoteGuestBillingAddressManagementV1"],"description":"Return the billing address for a specified quote.","operationId":"quoteGuestBillingAddressManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-address-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["quoteGuestBillingAddressManagementV1"],"description":"Assign a specified billing address to a specified cart.","operationId":"quoteGuestBillingAddressManagementV1AssignPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["address"],"properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"},"useForShipping":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Address ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/coupons":{"get":{"tags":["quoteCouponManagementV1"],"description":"Returns information for a coupon in a specified cart.","operationId":"quoteCouponManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"The coupon code data."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteCouponManagementV1"],"description":"Deletes a coupon from a specified cart.","operationId":"quoteCouponManagementV1RemoveDelete","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/coupons/{couponCode}":{"put":{"tags":["quoteCouponManagementV1"],"description":"Adds a coupon by code to a specified cart.","operationId":"quoteCouponManagementV1SetPut","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"couponCode","in":"path","type":"string","required":true,"description":"The coupon code data."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/coupons":{"get":{"tags":["quoteCouponManagementV1"],"description":"Returns information for a coupon in a specified cart.","operationId":"quoteCouponManagementV1GetGet","responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"The coupon code data."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteCouponManagementV1"],"description":"Deletes a coupon from a specified cart.","operationId":"quoteCouponManagementV1RemoveDelete","responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/coupons/{couponCode}":{"put":{"tags":["quoteCouponManagementV1"],"description":"Adds a coupon by code to a specified cart.","operationId":"quoteCouponManagementV1SetPut","parameters":[{"name":"couponCode","in":"path","type":"string","required":true,"description":"The coupon code data."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/coupons":{"get":{"tags":["quoteGuestCouponManagementV1"],"description":"Return information for a coupon in a specified cart.","operationId":"quoteGuestCouponManagementV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"The coupon code data."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["quoteGuestCouponManagementV1"],"description":"Delete a coupon from a specified cart.","operationId":"quoteGuestCouponManagementV1RemoveDelete","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/coupons/{couponCode}":{"put":{"tags":["quoteGuestCouponManagementV1"],"description":"Add a coupon by code to a specified cart.","operationId":"quoteGuestCouponManagementV1SetPut","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"couponCode","in":"path","type":"string","required":true,"description":"The coupon code data."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/totals":{"get":{"tags":["quoteCartTotalRepositoryV1"],"description":"Returns quote totals data for a specified cart.","operationId":"quoteCartTotalRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/totals":{"get":{"tags":["quoteCartTotalRepositoryV1"],"description":"Returns quote totals data for a specified cart.","operationId":"quoteCartTotalRepositoryV1GetGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/collect-totals":{"put":{"tags":["quoteGuestCartTotalManagementV1"],"description":"Set shipping/billing methods and additional data for cart and collect totals for guest.","operationId":"quoteGuestCartTotalManagementV1CollectTotalsPut","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["paymentMethod"],"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"shippingCarrierCode":{"type":"string","description":"The carrier code."},"shippingMethodCode":{"type":"string","description":"The shipping method code."},"additionalData":{"$ref":"#/definitions/quote-data-totals-additional-data-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/totals":{"get":{"tags":["quoteGuestCartTotalRepositoryV1"],"description":"Return quote totals data for a specified cart.","operationId":"quoteGuestCartTotalRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/collect-totals":{"put":{"tags":["quoteCartTotalManagementV1"],"description":"Set shipping/billing methods and additional data for cart and collect totals.","operationId":"quoteCartTotalManagementV1CollectTotalsPut","parameters":[{"name":"$body","in":"body","schema":{"required":["paymentMethod"],"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"shippingCarrierCode":{"type":"string","description":"The carrier code."},"shippingMethodCode":{"type":"string","description":"The shipping method code."},"additionalData":{"$ref":"#/definitions/quote-data-totals-additional-data-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/search":{"get":{"tags":["searchV1"],"description":"Make Full Text Search and return found Documents","operationId":"searchV1SearchGet","parameters":[{"name":"searchCriteria[requestName]","in":"query","type":"string"},{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/framework-search-search-result-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}":{"get":{"tags":["salesOrderRepositoryV1"],"description":"Loads a specified order.","operationId":"salesOrderRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders":{"get":{"tags":["salesOrderRepositoryV1"],"description":"Lists orders that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#OrderRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesOrderRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/create":{"put":{"tags":["salesOrderRepositoryV1"],"description":"Performs persist operations for a specified order.","operationId":"salesOrderRepositoryV1SavePut","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-order-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/":{"post":{"tags":["salesOrderRepositoryV1"],"description":"Performs persist operations for a specified order.","operationId":"salesOrderRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-order-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/statuses":{"get":{"tags":["salesOrderManagementV1"],"description":"Gets the status for a specified order.","operationId":"salesOrderManagementV1GetStatusGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"Order status."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/cancel":{"post":{"tags":["salesOrderManagementV1"],"description":"Cancels a specified order.","operationId":"salesOrderManagementV1CancelPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/emails":{"post":{"tags":["salesOrderManagementV1"],"description":"Emails a user a specified order.","operationId":"salesOrderManagementV1NotifyPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/hold":{"post":{"tags":["salesOrderManagementV1"],"description":"Holds a specified order.","operationId":"salesOrderManagementV1HoldPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/unhold":{"post":{"tags":["salesOrderManagementV1"],"description":"Releases a specified order from hold status.","operationId":"salesOrderManagementV1UnHoldPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{id}/comments":{"post":{"tags":["salesOrderManagementV1"],"description":"Adds a comment to a specified order.","operationId":"salesOrderManagementV1AddCommentPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."},{"name":"$body","in":"body","schema":{"required":["statusHistory"],"properties":{"statusHistory":{"$ref":"#/definitions/sales-data-order-status-history-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["salesOrderManagementV1"],"description":"Lists comments for a specified order.","operationId":"salesOrderManagementV1GetCommentsListGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-status-history-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/{parent_id}":{"put":{"tags":["salesOrderAddressRepositoryV1"],"description":"Performs persist operations for a specified order address.","operationId":"salesOrderAddressRepositoryV1SavePut","parameters":[{"name":"parent_id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-order-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-address-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/items/{id}":{"get":{"tags":["salesOrderItemRepositoryV1"],"description":"Loads a specified order item.","operationId":"salesOrderItemRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The order item ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/orders/items":{"get":{"tags":["salesOrderItemRepositoryV1"],"description":"Lists order items that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#OrderItemRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesOrderItemRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-order-item-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/{id}":{"get":{"tags":["salesInvoiceRepositoryV1"],"description":"Loads a specified invoice.","operationId":"salesInvoiceRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The invoice ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-invoice-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices":{"get":{"tags":["salesInvoiceRepositoryV1"],"description":"Lists invoices that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#InvoiceRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesInvoiceRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-invoice-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/":{"post":{"tags":["salesInvoiceRepositoryV1"],"description":"Performs persist operations for a specified invoice.","operationId":"salesInvoiceRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-invoice-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-invoice-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/{id}/comments":{"get":{"tags":["salesInvoiceManagementV1"],"description":"Lists comments for a specified invoice.","operationId":"salesInvoiceManagementV1GetCommentsListGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The invoice ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-invoice-comment-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/{id}/emails":{"post":{"tags":["salesInvoiceManagementV1"],"description":"Emails a user a specified invoice.","operationId":"salesInvoiceManagementV1NotifyPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The invoice ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/{id}/void":{"post":{"tags":["salesInvoiceManagementV1"],"description":"Voids a specified invoice.","operationId":"salesInvoiceManagementV1SetVoidPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The invoice ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/{id}/capture":{"post":{"tags":["salesInvoiceManagementV1"],"description":"Sets invoice capture.","operationId":"salesInvoiceManagementV1SetCapturePost","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoices/comments":{"post":{"tags":["salesInvoiceCommentRepositoryV1"],"description":"Performs persist operations for a specified invoice comment.","operationId":"salesInvoiceCommentRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-invoice-comment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-invoice-comment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/invoice/{invoiceId}/refund":{"post":{"tags":["salesRefundInvoiceV1"],"description":"Create refund for invoice","operationId":"salesRefundInvoiceV1ExecutePost","parameters":[{"name":"invoiceId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"properties":{"items":{"type":"array","items":{"$ref":"#/definitions/sales-data-creditmemo-item-creation-interface"}},"isOnline":{"type":"boolean"},"notify":{"type":"boolean"},"appendComment":{"type":"boolean"},"comment":{"$ref":"#/definitions/sales-data-creditmemo-comment-creation-interface"},"arguments":{"$ref":"#/definitions/sales-data-creditmemo-creation-arguments-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemo/{id}/comments":{"get":{"tags":["salesCreditmemoManagementV1"],"description":"Lists comments for a specified credit memo.","operationId":"salesCreditmemoManagementV1GetCommentsListGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The credit memo ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-comment-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["salesCreditmemoCommentRepositoryV1"],"description":"Performs persist operations for a specified entity.","operationId":"salesCreditmemoCommentRepositoryV1SavePost","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-creditmemo-comment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-comment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemo/{id}":{"put":{"tags":["salesCreditmemoManagementV1"],"description":"Cancels a specified credit memo.","operationId":"salesCreditmemoManagementV1CancelPut","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The credit memo ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["salesCreditmemoRepositoryV1"],"description":"Loads a specified credit memo.","operationId":"salesCreditmemoRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The credit memo ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemo/{id}/emails":{"post":{"tags":["salesCreditmemoManagementV1"],"description":"Emails a user a specified credit memo.","operationId":"salesCreditmemoManagementV1NotifyPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The credit memo ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemo/refund":{"post":{"tags":["salesCreditmemoManagementV1"],"description":"Prepare creditmemo to refund and save it.","operationId":"salesCreditmemoManagementV1RefundPost","parameters":[{"name":"$body","in":"body","schema":{"required":["creditmemo"],"properties":{"creditmemo":{"$ref":"#/definitions/sales-data-creditmemo-interface"},"offlineRequested":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemos":{"get":{"tags":["salesCreditmemoRepositoryV1"],"description":"Lists credit memos that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#CreditmemoRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesCreditmemoRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/creditmemo":{"post":{"tags":["salesCreditmemoRepositoryV1"],"description":"Performs persist operations for a specified credit memo.","operationId":"salesCreditmemoRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-creditmemo-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-creditmemo-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/order/{orderId}/refund":{"post":{"tags":["salesRefundOrderV1"],"description":"Create offline refund for order","operationId":"salesRefundOrderV1ExecutePost","parameters":[{"name":"orderId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"properties":{"items":{"type":"array","items":{"$ref":"#/definitions/sales-data-creditmemo-item-creation-interface"}},"notify":{"type":"boolean"},"appendComment":{"type":"boolean"},"comment":{"$ref":"#/definitions/sales-data-creditmemo-comment-creation-interface"},"arguments":{"$ref":"#/definitions/sales-data-creditmemo-creation-arguments-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/{id}":{"get":{"tags":["salesShipmentRepositoryV1"],"description":"Loads a specified shipment.","operationId":"salesShipmentRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The shipment ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipments":{"get":{"tags":["salesShipmentRepositoryV1"],"description":"Lists shipments that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#ShipmentRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesShipmentRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/":{"post":{"tags":["salesShipmentRepositoryV1"],"description":"Performs persist operations for a specified shipment.","operationId":"salesShipmentRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-shipment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/{id}/comments":{"get":{"tags":["salesShipmentManagementV1"],"description":"Lists comments for a specified shipment.","operationId":"salesShipmentManagementV1GetCommentsListGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The shipment ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-comment-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["salesShipmentCommentRepositoryV1"],"description":"Performs persist operations for a specified shipment comment.","operationId":"salesShipmentCommentRepositoryV1SavePost","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-shipment-comment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-comment-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/{id}/emails":{"post":{"tags":["salesShipmentManagementV1"],"description":"Emails user a specified shipment.","operationId":"salesShipmentManagementV1NotifyPost","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The shipment ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/{id}/label":{"get":{"tags":["salesShipmentManagementV1"],"description":"Gets a specified shipment label.","operationId":"salesShipmentManagementV1GetLabelGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The shipment label ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"Shipment label."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/track":{"post":{"tags":["salesShipmentTrackRepositoryV1"],"description":"Performs persist operations for a specified shipment track.","operationId":"salesShipmentTrackRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entity"],"properties":{"entity":{"$ref":"#/definitions/sales-data-shipment-track-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-shipment-track-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/shipment/track/{id}":{"delete":{"tags":["salesShipmentTrackRepositoryV1"],"description":"Deletes a specified shipment track by ID.","operationId":"salesShipmentTrackRepositoryV1DeleteByIdDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The shipment track ID."}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/order/{orderId}/ship":{"post":{"tags":["salesShipOrderV1"],"description":"Creates new Shipment for given Order.","operationId":"salesShipOrderV1ExecutePost","parameters":[{"name":"orderId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"properties":{"items":{"type":"array","items":{"$ref":"#/definitions/sales-data-shipment-item-creation-interface"}},"notify":{"type":"boolean"},"appendComment":{"type":"boolean"},"comment":{"$ref":"#/definitions/sales-data-shipment-comment-creation-interface"},"tracks":{"type":"array","items":{"$ref":"#/definitions/sales-data-shipment-track-creation-interface"}},"packages":{"type":"array","items":{"$ref":"#/definitions/sales-data-shipment-package-creation-interface"}},"arguments":{"$ref":"#/definitions/sales-data-shipment-creation-arguments-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Id of created Shipment."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/transactions/{id}":{"get":{"tags":["salesTransactionRepositoryV1"],"description":"Loads a specified transaction.","operationId":"salesTransactionRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true,"description":"The transaction ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-transaction-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/transactions":{"get":{"tags":["salesTransactionRepositoryV1"],"description":"Lists transactions that match specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#TransactionRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesTransactionRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-data-transaction-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/order/{orderId}/invoice":{"post":{"tags":["salesInvoiceOrderV1"],"description":"","operationId":"salesInvoiceOrderV1ExecutePost","parameters":[{"name":"orderId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"properties":{"capture":{"type":"boolean"},"items":{"type":"array","items":{"$ref":"#/definitions/sales-data-invoice-item-creation-interface"}},"notify":{"type":"boolean"},"appendComment":{"type":"boolean"},"comment":{"$ref":"#/definitions/sales-data-invoice-comment-creation-interface"},"arguments":{"$ref":"#/definitions/sales-data-invoice-creation-arguments-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/shipping-information":{"post":{"tags":["checkoutGuestShippingInformationManagementV1"],"description":"","operationId":"checkoutGuestShippingInformationManagementV1SaveAddressInformationPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-shipping-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/checkout-data-payment-details-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/shipping-information":{"post":{"tags":["checkoutShippingInformationManagementV1"],"description":"","operationId":"checkoutShippingInformationManagementV1SaveAddressInformationPost","parameters":[{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-shipping-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/checkout-data-payment-details-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/shipping-information":{"post":{"tags":["checkoutShippingInformationManagementV1"],"description":"","operationId":"checkoutShippingInformationManagementV1SaveAddressInformationPost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-shipping-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/checkout-data-payment-details-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/totals-information":{"post":{"tags":["checkoutTotalsInformationManagementV1"],"description":"Calculate quote totals based on address and shipping method.","operationId":"checkoutTotalsInformationManagementV1CalculatePost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-totals-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/totals-information":{"post":{"tags":["checkoutTotalsInformationManagementV1"],"description":"Calculate quote totals based on address and shipping method.","operationId":"checkoutTotalsInformationManagementV1CalculatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-totals-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/totals-information":{"post":{"tags":["checkoutGuestTotalsInformationManagementV1"],"description":"Calculate quote totals based on address and shipping method.","operationId":"checkoutGuestTotalsInformationManagementV1CalculatePost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["addressInformation"],"properties":{"addressInformation":{"$ref":"#/definitions/checkout-data-totals-information-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-totals-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/payment-information":{"post":{"tags":["checkoutGuestPaymentInformationManagementV1"],"description":"Set payment information and place order for a specified cart.","operationId":"checkoutGuestPaymentInformationManagementV1SavePaymentInformationAndPlaceOrderPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["email","paymentMethod"],"properties":{"email":{"type":"string"},"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"billingAddress":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["checkoutGuestPaymentInformationManagementV1"],"description":"Get payment information","operationId":"checkoutGuestPaymentInformationManagementV1GetPaymentInformationGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/checkout-data-payment-details-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/set-payment-information":{"post":{"tags":["checkoutGuestPaymentInformationManagementV1"],"description":"Set payment information for a specified cart.","operationId":"checkoutGuestPaymentInformationManagementV1SavePaymentInformationPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["email","paymentMethod"],"properties":{"email":{"type":"string"},"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"billingAddress":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/payment-information":{"post":{"tags":["checkoutPaymentInformationManagementV1"],"description":"Set payment information and place order for a specified cart.","operationId":"checkoutPaymentInformationManagementV1SavePaymentInformationAndPlaceOrderPost","parameters":[{"name":"$body","in":"body","schema":{"required":["paymentMethod"],"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"billingAddress":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["checkoutPaymentInformationManagementV1"],"description":"Get payment information","operationId":"checkoutPaymentInformationManagementV1GetPaymentInformationGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/checkout-data-payment-details-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/set-payment-information":{"post":{"tags":["checkoutPaymentInformationManagementV1"],"description":"Set payment information for a specified cart.","operationId":"checkoutPaymentInformationManagementV1SavePaymentInformationPost","parameters":[{"name":"$body","in":"body","schema":{"required":["paymentMethod"],"properties":{"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"billingAddress":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/downloadable-links":{"get":{"tags":["downloadableLinkRepositoryV1"],"description":"List of links with associated samples","operationId":"downloadableLinkRepositoryV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/downloadable-data-link-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["downloadableLinkRepositoryV1"],"description":"Update downloadable link of the given product (link type and its resources cannot be changed)","operationId":"downloadableLinkRepositoryV1SavePost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["link"],"properties":{"link":{"$ref":"#/definitions/downloadable-data-link-interface"},"isGlobalScopeContent":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/downloadable-links/{id}":{"put":{"tags":["downloadableLinkRepositoryV1"],"description":"Update downloadable link of the given product (link type and its resources cannot be changed)","operationId":"downloadableLinkRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["link"],"properties":{"link":{"$ref":"#/definitions/downloadable-data-link-interface"},"isGlobalScopeContent":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/downloadable-links/{id}":{"delete":{"tags":["downloadableLinkRepositoryV1"],"description":"Delete downloadable link","operationId":"downloadableLinkRepositoryV1DeleteDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/downloadable-links/samples":{"get":{"tags":["downloadableSampleRepositoryV1"],"description":"List of samples for downloadable product","operationId":"downloadableSampleRepositoryV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/downloadable-data-sample-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["downloadableSampleRepositoryV1"],"description":"Update downloadable sample of the given product","operationId":"downloadableSampleRepositoryV1SavePost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["sample"],"properties":{"sample":{"$ref":"#/definitions/downloadable-data-sample-interface"},"isGlobalScopeContent":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/{sku}/downloadable-links/samples/{id}":{"put":{"tags":["downloadableSampleRepositoryV1"],"description":"Update downloadable sample of the given product","operationId":"downloadableSampleRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["sample"],"properties":{"sample":{"$ref":"#/definitions/downloadable-data-sample-interface"},"isGlobalScopeContent":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/products/downloadable-links/samples/{id}":{"delete":{"tags":["downloadableSampleRepositoryV1"],"description":"Delete downloadable sample","operationId":"downloadableSampleRepositoryV1DeleteDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/licence":{"get":{"tags":["checkoutAgreementsCheckoutAgreementsRepositoryV1"],"description":"Lists active checkout agreements.","operationId":"checkoutAgreementsCheckoutAgreementsRepositoryV1GetListGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/checkout-agreements-data-agreement-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/children":{"get":{"tags":["configurableProductLinkManagementV1"],"description":"Get all children for Configurable product","operationId":"configurableProductLinkManagementV1GetChildrenGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/children/{childSku}":{"delete":{"tags":["configurableProductLinkManagementV1"],"description":"Remove configurable product option","operationId":"configurableProductLinkManagementV1RemoveChildDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"childSku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/child":{"post":{"tags":["configurableProductLinkManagementV1"],"description":"","operationId":"configurableProductLinkManagementV1AddChildPost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["childSku"],"properties":{"childSku":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/variation":{"put":{"tags":["configurableProductConfigurableProductManagementV1"],"description":"Generate variation based on same product","operationId":"configurableProductConfigurableProductManagementV1GenerateVariationPut","parameters":[{"name":"$body","in":"body","schema":{"required":["product","options"],"properties":{"product":{"$ref":"#/definitions/catalog-data-product-interface"},"options":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-option-interface"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/options/{id}":{"get":{"tags":["configurableProductOptionRepositoryV1"],"description":"Get option for configurable product","operationId":"configurableProductOptionRepositoryV1GetGet","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/configurable-product-data-option-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["configurableProductOptionRepositoryV1"],"description":"Save option","operationId":"configurableProductOptionRepositoryV1SavePut","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/configurable-product-data-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["configurableProductOptionRepositoryV1"],"description":"Remove option from configurable product","operationId":"configurableProductOptionRepositoryV1DeleteByIdDelete","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/options/all":{"get":{"tags":["configurableProductOptionRepositoryV1"],"description":"Get all options for configurable product","operationId":"configurableProductOptionRepositoryV1GetListGet","parameters":[{"name":"sku","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-option-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/configurable-products/{sku}/options":{"post":{"tags":["configurableProductOptionRepositoryV1"],"description":"Save option","operationId":"configurableProductOptionRepositoryV1SavePost","parameters":[{"name":"sku","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["option"],"properties":{"option":{"$ref":"#/definitions/configurable-product-data-option-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/balance/apply":{"post":{"tags":["customerBalanceBalanceManagementV1"],"description":"Apply store credit","operationId":"customerBalanceBalanceManagementV1ApplyPost","responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{quoteId}/giftCards":{"get":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"Return GiftCard Account cards","operationId":"giftCardAccountGiftCardAccountManagementV1GetListByQuoteIdGet","parameters":[{"name":"quoteId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-card-account-data-gift-card-account-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/giftCards":{"put":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"","operationId":"giftCardAccountGiftCardAccountManagementV1SaveByQuoteIdPut","parameters":[{"name":"cartId","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["giftCardAccountData"],"properties":{"giftCardAccountData":{"$ref":"#/definitions/gift-card-account-data-gift-card-account-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/giftCards/{giftCardCode}":{"delete":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"Remove GiftCard Account entity","operationId":"giftCardAccountGiftCardAccountManagementV1DeleteByQuoteIdDelete","parameters":[{"name":"cartId","in":"path","type":"integer","required":true},{"name":"giftCardCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/giftCards/{giftCardCode}":{"delete":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"Remove GiftCard Account entity","operationId":"giftCardAccountGiftCardAccountManagementV1DeleteByQuoteIdDelete","parameters":[{"name":"giftCardCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/giftCards":{"post":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"","operationId":"giftCardAccountGiftCardAccountManagementV1SaveByQuoteIdPost","parameters":[{"name":"$body","in":"body","schema":{"required":["giftCardAccountData"],"properties":{"giftCardAccountData":{"$ref":"#/definitions/gift-card-account-data-gift-card-account-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/checkGiftCard/{giftCardCode}":{"get":{"tags":["giftCardAccountGiftCardAccountManagementV1"],"description":"","operationId":"giftCardAccountGiftCardAccountManagementV1CheckGiftCardGet","parameters":[{"name":"giftCardCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"number"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/guest-carts/{cartId}/giftCards/{giftCardCode}":{"delete":{"tags":["giftCardAccountGuestGiftCardAccountManagementV1"],"description":"Remove GiftCard Account entity","operationId":"giftCardAccountGuestGiftCardAccountManagementV1DeleteByQuoteIdDelete","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"giftCardCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/guest-carts/{cartId}/giftCards":{"post":{"tags":["giftCardAccountGuestGiftCardAccountManagementV1"],"description":"","operationId":"giftCardAccountGuestGiftCardAccountManagementV1AddGiftCardPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["giftCardAccountData"],"properties":{"giftCardAccountData":{"$ref":"#/definitions/gift-card-account-data-gift-card-account-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/guest-carts/{cartId}/checkGiftCard/{giftCardCode}":{"get":{"tags":["giftCardAccountGuestGiftCardAccountManagementV1"],"description":"","operationId":"giftCardAccountGuestGiftCardAccountManagementV1CheckGiftCardGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"giftCardCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"number"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRates":{"post":{"tags":["taxTaxRateRepositoryV1"],"description":"Create or update tax rate","operationId":"taxTaxRateRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["taxRate"],"properties":{"taxRate":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["taxTaxRateRepositoryV1"],"description":"Create or update tax rate","operationId":"taxTaxRateRepositoryV1SavePut","parameters":[{"name":"$body","in":"body","schema":{"required":["taxRate"],"properties":{"taxRate":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRates/{rateId}":{"get":{"tags":["taxTaxRateRepositoryV1"],"description":"Get tax rate","operationId":"taxTaxRateRepositoryV1GetGet","parameters":[{"name":"rateId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["taxTaxRateRepositoryV1"],"description":"Delete tax rate","operationId":"taxTaxRateRepositoryV1DeleteByIdDelete","parameters":[{"name":"rateId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRates/search":{"get":{"tags":["taxTaxRateRepositoryV1"],"description":"Search TaxRates This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#TaxRateRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"taxTaxRateRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rate-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRules":{"post":{"tags":["taxTaxRuleRepositoryV1"],"description":"Save TaxRule","operationId":"taxTaxRuleRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["rule"],"properties":{"rule":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["taxTaxRuleRepositoryV1"],"description":"Save TaxRule","operationId":"taxTaxRuleRepositoryV1SavePut","parameters":[{"name":"$body","in":"body","schema":{"required":["rule"],"properties":{"rule":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRules/{ruleId}":{"delete":{"tags":["taxTaxRuleRepositoryV1"],"description":"Delete TaxRule","operationId":"taxTaxRuleRepositoryV1DeleteByIdDelete","parameters":[{"name":"ruleId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["taxTaxRuleRepositoryV1"],"description":"Get TaxRule","operationId":"taxTaxRuleRepositoryV1GetGet","parameters":[{"name":"ruleId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxRules/search":{"get":{"tags":["taxTaxRuleRepositoryV1"],"description":"Search TaxRules This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#TaxRuleRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"taxTaxRuleRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-rule-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxClasses":{"post":{"tags":["taxTaxClassRepositoryV1"],"description":"Create a Tax Class","operationId":"taxTaxClassRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["taxClass"],"properties":{"taxClass":{"$ref":"#/definitions/tax-data-tax-class-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"id for the newly created Tax class"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxClasses/{taxClassId}":{"get":{"tags":["taxTaxClassRepositoryV1"],"description":"Get a tax class with the given tax class id.","operationId":"taxTaxClassRepositoryV1GetGet","parameters":[{"name":"taxClassId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-class-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["taxTaxClassRepositoryV1"],"description":"Delete a tax class with the given tax class id.","operationId":"taxTaxClassRepositoryV1DeleteByIdDelete","parameters":[{"name":"taxClassId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"True if the tax class was deleted, false otherwise"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxClasses/{classId}":{"put":{"tags":["taxTaxClassRepositoryV1"],"description":"Create a Tax Class","operationId":"taxTaxClassRepositoryV1SavePut","parameters":[{"name":"classId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["taxClass"],"properties":{"taxClass":{"$ref":"#/definitions/tax-data-tax-class-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"id for the newly created Tax class"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/taxClasses/search":{"get":{"tags":["taxTaxClassRepositoryV1"],"description":"Retrieve tax classes which match a specific criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#TaxClassRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"taxTaxClassRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/tax-data-tax-class-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/gift-message":{"get":{"tags":["giftMessageCartRepositoryV1"],"description":"Return the gift message for a specified order.","operationId":"giftMessageCartRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The shopping cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageCartRepositoryV1"],"description":"Set the gift message for an entire order.","operationId":"giftMessageCartRepositoryV1SavePost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/gift-message":{"get":{"tags":["giftMessageCartRepositoryV1"],"description":"Return the gift message for a specified order.","operationId":"giftMessageCartRepositoryV1GetGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageCartRepositoryV1"],"description":"Set the gift message for an entire order.","operationId":"giftMessageCartRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/{cartId}/gift-message/{itemId}":{"get":{"tags":["giftMessageItemRepositoryV1"],"description":"Return the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageItemRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The shopping cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageItemRepositoryV1"],"description":"Set the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageItemRepositoryV1SavePost","parameters":[{"name":"cartId","in":"path","type":"integer","required":true,"description":"The cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."},{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/carts/mine/gift-message/{itemId}":{"get":{"tags":["giftMessageItemRepositoryV1"],"description":"Return the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageItemRepositoryV1GetGet","parameters":[{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageItemRepositoryV1"],"description":"Set the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageItemRepositoryV1SavePost","parameters":[{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."},{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/gift-message":{"get":{"tags":["giftMessageGuestCartRepositoryV1"],"description":"Return the gift message for a specified order.","operationId":"giftMessageGuestCartRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The shopping cart ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageGuestCartRepositoryV1"],"description":"Set the gift message for an entire order.","operationId":"giftMessageGuestCartRepositoryV1SavePost","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-carts/{cartId}/gift-message/{itemId}":{"get":{"tags":["giftMessageGuestItemRepositoryV1"],"description":"Return the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageGuestItemRepositoryV1GetGet","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The shopping cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-message-data-message-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["giftMessageGuestItemRepositoryV1"],"description":"Set the gift message for a specified item in a specified shopping cart.","operationId":"giftMessageGuestItemRepositoryV1SavePost","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The cart ID."},{"name":"itemId","in":"path","type":"integer","required":true,"description":"The item ID."},{"name":"$body","in":"body","schema":{"required":["giftMessage"],"properties":{"giftMessage":{"$ref":"#/definitions/gift-message-data-message-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/gift-wrappings/{id}":{"get":{"tags":["giftWrappingWrappingRepositoryV1"],"description":"Return data object for specified wrapping ID and store.","operationId":"giftWrappingWrappingRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"storeId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["giftWrappingWrappingRepositoryV1"],"description":"Delete gift wrapping","operationId":"giftWrappingWrappingRepositoryV1DeleteByIdDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/gift-wrappings":{"post":{"tags":["giftWrappingWrappingRepositoryV1"],"description":"Create/Update new gift wrapping with data object values","operationId":"giftWrappingWrappingRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["data"],"properties":{"data":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"},"storeId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["giftWrappingWrappingRepositoryV1"],"description":"Return list of gift wrapping data objects based on search criteria","operationId":"giftWrappingWrappingRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-wrapping-data-wrapping-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/gift-wrappings/{wrappingId}":{"put":{"tags":["giftWrappingWrappingRepositoryV1"],"description":"Create/Update new gift wrapping with data object values","operationId":"giftWrappingWrappingRepositoryV1SavePut","parameters":[{"name":"wrappingId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["data"],"properties":{"data":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"},"storeId":{"type":"integer"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/salesRules/{ruleId}":{"get":{"tags":["salesRuleRuleRepositoryV1"],"description":"Get rule by ID.","operationId":"salesRuleRuleRepositoryV1GetByIdGet","parameters":[{"name":"ruleId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["salesRuleRuleRepositoryV1"],"description":"Save sales rule.","operationId":"salesRuleRuleRepositoryV1SavePut","parameters":[{"name":"ruleId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["rule"],"properties":{"rule":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["salesRuleRuleRepositoryV1"],"description":"Delete rule by ID.","operationId":"salesRuleRuleRepositoryV1DeleteByIdDelete","parameters":[{"name":"ruleId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/salesRules/search":{"get":{"tags":["salesRuleRuleRepositoryV1"],"description":"Retrieve sales rules that match te specified criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#RuleRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesRuleRuleRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-rule-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/salesRules":{"post":{"tags":["salesRuleRuleRepositoryV1"],"description":"Save sales rule.","operationId":"salesRuleRuleRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["rule"],"properties":{"rule":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons/{couponId}":{"get":{"tags":["salesRuleCouponRepositoryV1"],"description":"Get coupon by coupon id.","operationId":"salesRuleCouponRepositoryV1GetByIdGet","parameters":[{"name":"couponId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["salesRuleCouponRepositoryV1"],"description":"Save a coupon.","operationId":"salesRuleCouponRepositoryV1SavePut","parameters":[{"name":"couponId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["coupon"],"properties":{"coupon":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["salesRuleCouponRepositoryV1"],"description":"Delete coupon by coupon id.","operationId":"salesRuleCouponRepositoryV1DeleteByIdDelete","parameters":[{"name":"couponId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean","description":"true on success"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons/search":{"get":{"tags":["salesRuleCouponRepositoryV1"],"description":"Retrieve a coupon using the specified search criteria. This call returns an array of objects, but detailed information about each object\u2019s attributes might not be included. See http://devdocs.magento.com/codelinks/attributes.html#CouponRepositoryInterface to determine which call to use to get detailed information about all attributes for an object.","operationId":"salesRuleCouponRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons":{"post":{"tags":["salesRuleCouponRepositoryV1"],"description":"Save a coupon.","operationId":"salesRuleCouponRepositoryV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["coupon"],"properties":{"coupon":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons/generate":{"post":{"tags":["salesRuleCouponManagementV1"],"description":"Generate coupon for a rule","operationId":"salesRuleCouponManagementV1GeneratePost","parameters":[{"name":"$body","in":"body","schema":{"required":["couponSpec"],"properties":{"couponSpec":{"$ref":"#/definitions/sales-rule-data-coupon-generation-spec-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"type":"string"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons/deleteByIds":{"post":{"tags":["salesRuleCouponManagementV1"],"description":"Delete coupon by coupon ids.","operationId":"salesRuleCouponManagementV1DeleteByIdsPost","parameters":[{"name":"$body","in":"body","schema":{"required":["ids"],"properties":{"ids":{"type":"array","items":{"type":"integer"}},"ignoreInvalidCoupons":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-mass-delete-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/coupons/deleteByCodes":{"post":{"tags":["salesRuleCouponManagementV1"],"description":"Delete coupon by coupon codes.","operationId":"salesRuleCouponManagementV1DeleteByCodesPost","parameters":[{"name":"$body","in":"body","schema":{"required":["codes"],"properties":{"codes":{"type":"array","items":{"type":"string"}},"ignoreInvalidCoupons":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/sales-rule-data-coupon-mass-delete-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/giftregistry/mine/estimate-shipping-methods":{"post":{"tags":["giftRegistryShippingMethodManagementV1"],"description":"Estimate shipping","operationId":"giftRegistryShippingMethodManagementV1EstimateByRegistryIdPost","parameters":[{"name":"$body","in":"body","schema":{"required":["registryId"],"properties":{"registryId":{"type":"integer","description":"The estimate registry id"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/guest-giftregistry/{cartId}/estimate-shipping-methods":{"post":{"tags":["giftRegistryGuestCartShippingMethodManagementV1"],"description":"Estimate shipping","operationId":"giftRegistryGuestCartShippingMethodManagementV1EstimateByRegistryIdPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true,"description":"The shopping cart ID."},{"name":"$body","in":"body","schema":{"required":["registryId"],"properties":{"registryId":{"type":"integer","description":"The estimate registry id"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","description":"An array of shipping methods.","items":{"$ref":"#/definitions/quote-data-shipping-method-interface"}}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/reward/mine/use-reward":{"post":{"tags":["rewardRewardManagementV1"],"description":"Set reward points to quote","operationId":"rewardRewardManagementV1SetPost","responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns/{id}/tracking-numbers":{"post":{"tags":["rmaTrackManagementV1"],"description":"Add track","operationId":"rmaTrackManagementV1AddTrackPost","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["track"],"properties":{"track":{"$ref":"#/definitions/rma-data-track-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["rmaTrackManagementV1"],"description":"Get track list","operationId":"rmaTrackManagementV1GetTracksGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-track-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns/{id}/tracking-numbers/{trackId}":{"delete":{"tags":["rmaTrackManagementV1"],"description":"Remove track by id","operationId":"rmaTrackManagementV1RemoveTrackByIdDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"trackId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns/{id}/labels":{"get":{"tags":["rmaTrackManagementV1"],"description":"Get shipping label int the PDF format","operationId":"rmaTrackManagementV1GetShippingLabelPdfGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns/{id}":{"get":{"tags":["rmaRmaRepositoryV1"],"description":"Return data object for specified RMA id","operationId":"rmaRmaRepositoryV1GetGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-rma-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["rmaRmaRepositoryV1"],"description":"Delete RMA","operationId":"rmaRmaRepositoryV1DeleteDelete","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["rmaDataObject"],"properties":{"rmaDataObject":{"$ref":"#/definitions/rma-data-rma-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["rmaRmaManagementV1"],"description":"Save RMA","operationId":"rmaRmaManagementV1SaveRmaPut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["rmaDataObject"],"properties":{"rmaDataObject":{"$ref":"#/definitions/rma-data-rma-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-rma-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns/{id}/comments":{"post":{"tags":["rmaCommentManagementV1"],"description":"Add comment","operationId":"rmaCommentManagementV1AddCommentPost","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["data"],"properties":{"data":{"$ref":"#/definitions/rma-data-comment-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["rmaCommentManagementV1"],"description":"Comments list","operationId":"rmaCommentManagementV1CommentsListGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-comment-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returns":{"post":{"tags":["rmaRmaManagementV1"],"description":"Save RMA","operationId":"rmaRmaManagementV1SaveRmaPost","parameters":[{"name":"$body","in":"body","schema":{"required":["rmaDataObject"],"properties":{"rmaDataObject":{"$ref":"#/definitions/rma-data-rma-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-rma-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"get":{"tags":["rmaRmaManagementV1"],"description":"Return list of rma data objects based on search criteria","operationId":"rmaRmaManagementV1SearchGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/rma-data-rma-search-result-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returnsAttributeMetadata/{attributeCode}":{"get":{"tags":["rmaRmaAttributesManagementV1"],"description":"Retrieve attribute metadata.","operationId":"rmaRmaAttributesManagementV1GetAttributeMetadataGet","parameters":[{"name":"attributeCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returnsAttributeMetadata/form/{formCode}":{"get":{"tags":["rmaRmaAttributesManagementV1"],"description":"Retrieve all attributes filtered by form code","operationId":"rmaRmaAttributesManagementV1GetAttributesGet","parameters":[{"name":"formCode","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returnsAttributeMetadata":{"get":{"tags":["rmaRmaAttributesManagementV1"],"description":"Get all attribute metadata.","operationId":"rmaRmaAttributesManagementV1GetAllAttributesMetadataGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/customer-data-attribute-metadata-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/returnsAttributeMetadata/custom":{"get":{"tags":["rmaRmaAttributesManagementV1"],"description":"Get custom attribute metadata for the given Data object's attribute set","operationId":"rmaRmaAttributesManagementV1GetCustomAttributesMetadataGet","parameters":[{"name":"dataObjectClassName","in":"query","type":"string","description":"Data object class name","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/framework-metadata-object-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/integration/admin/token":{"post":{"tags":["integrationAdminTokenServiceV1"],"description":"Create access token for admin given the admin credentials.","operationId":"integrationAdminTokenServiceV1CreateAdminAccessTokenPost","parameters":[{"name":"$body","in":"body","schema":{"required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"Token created"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/integration/customer/token":{"post":{"tags":["integrationCustomerTokenServiceV1"],"description":"Create access token for admin given the customer credentials.","operationId":"integrationCustomerTokenServiceV1CreateCustomerAccessTokenPost","parameters":[{"name":"$body","in":"body","schema":{"required":["username","password"],"properties":{"username":{"type":"string"},"password":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"string","description":"Token created"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/overwritten":{"get":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1ItemGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/testOptionalParam":{"post":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1TestOptionalParamPost","parameters":[{"name":"$body","in":"body","schema":{"properties":{"name":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/{itemId}":{"get":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1ItemGet","parameters":[{"name":"itemId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1UpdatePut","parameters":[{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1":{"get":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1ItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module1-v1-entity-item"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["name"],"properties":{"name":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/resource1/{itemId}":{"get":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1ItemGet","parameters":[{"name":"itemId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/itemAnyType":{"post":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1ItemAnyTypePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule1/itemPreconfigured":{"get":{"tags":["testModule1AllSoapAndRestV1"],"description":"","operationId":"testModule1AllSoapAndRestV1GetPreconfiguredItemGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V2/testmodule1/{id}":{"get":{"tags":["testModule1AllSoapAndRestV2"],"description":"Get item.","operationId":"testModule1AllSoapAndRestV2ItemGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v2-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModule1AllSoapAndRestV2"],"description":"Update item.","operationId":"testModule1AllSoapAndRestV2UpdatePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module1-v2-entity-item"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v2-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["testModule1AllSoapAndRestV2"],"description":"Delete an item.","operationId":"testModule1AllSoapAndRestV2DeleteDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v2-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V2/testmodule1":{"get":{"tags":["testModule1AllSoapAndRestV2"],"description":"Retrieve a list of items.","operationId":"testModule1AllSoapAndRestV2ItemsGet","parameters":[{"name":"filters[][field]","in":"query","type":"string","description":"Field"},{"name":"filters[][value]","in":"query","type":"string","description":"Value"},{"name":"filters[][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"sortOrder","in":"query","type":"string","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module1-v2-entity-item"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModule1AllSoapAndRestV2"],"description":"Create item.","operationId":"testModule1AllSoapAndRestV2CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["name"],"properties":{"name":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module1-v2-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testModule2SubsetRest/{id}":{"get":{"tags":["testModule2SubsetRestV1"],"description":"Return a single item.","operationId":"testModule2SubsetRestV1ItemGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module2-v1-entity-item"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testModule2SubsetRest":{"get":{"tags":["testModule2SubsetRestV1"],"description":"Return multiple items.","operationId":"testModule2SubsetRestV1ItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module2-v1-entity-item"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/success":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1SuccessGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module3-v1-entity-parameter"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/notfound":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1ResourceNotFoundExceptionGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/serviceexception":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1ServiceExceptionGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/unauthorized":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1AuthorizationExceptionGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/otherException":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1OtherExceptionGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/returnIncompatibleDataType":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1ReturnIncompatibleDataTypeGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/webapiException":{"get":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1WebapiExceptionGet","responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/errortest/inputException":{"post":{"tags":["testModule3ErrorV1"],"description":"","operationId":"testModule3ErrorV1InputExceptionPost","parameters":[{"name":"$body","in":"body","schema":{"required":["wrappedErrorParameters"],"properties":{"wrappedErrorParameters":{"type":"array","items":{"$ref":"#/definitions/test-module3-v1-entity-wrapped-error-parameter"}}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Status"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule4/{id}":{"get":{"tags":["testModule4DataObjectServiceV1"],"description":"","operationId":"testModule4DataObjectServiceV1GetDataGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module4-v1-entity-data-object-response"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModule4DataObjectServiceV1"],"description":"","operationId":"testModule4DataObjectServiceV1UpdateDataPost","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["request"],"properties":{"request":{"$ref":"#/definitions/test-module4-v1-entity-data-object-request"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module4-v1-entity-data-object-response"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule4/scalar/{id}":{"get":{"tags":["testModule4DataObjectServiceV1"],"description":"Test return scalar value","operationId":"testModule4DataObjectServiceV1ScalarResponseGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule4/{id}/nested":{"post":{"tags":["testModule4DataObjectServiceV1"],"description":"","operationId":"testModule4DataObjectServiceV1NestedDataPost","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["request"],"properties":{"request":{"$ref":"#/definitions/test-module4-v1-entity-nested-data-object-request"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module4-v1-entity-data-object-response"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmodule4/extensibleDataObject/{id}":{"post":{"tags":["testModule4DataObjectServiceV1"],"description":"","operationId":"testModule4DataObjectServiceV1ExtensibleDataObjectPost","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"$body","in":"body","schema":{"required":["request"],"properties":{"request":{"$ref":"#/definitions/test-module4-v1-entity-extensible-request-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module4-v1-entity-data-object-response"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModule5/{entityId}":{"get":{"tags":["testModule5AllSoapAndRestV1"],"description":"Retrieve an item.","operationId":"testModule5AllSoapAndRestV1ItemGet","parameters":[{"name":"entityId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModule5AllSoapAndRestV1"],"description":"Update existing item.","operationId":"testModule5AllSoapAndRestV1UpdatePut","parameters":[{"name":"entityId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModule5":{"get":{"tags":["testModule5AllSoapAndRestV1"],"description":"Retrieve all items.","operationId":"testModule5AllSoapAndRestV1ItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModule5AllSoapAndRestV1"],"description":"Create a new item.","operationId":"testModule5AllSoapAndRestV1CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModule5/{parentId}/nestedResource/{entityId}":{"put":{"tags":["testModule5AllSoapAndRestV1"],"description":"Update existing item.","operationId":"testModule5AllSoapAndRestV1NestedUpdatePut","parameters":[{"name":"parentId","in":"path","type":"string","required":true},{"name":"entityId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModule5/OverrideService/{parentId}/nestedResource/{entityId}":{"put":{"tags":["testModule5OverrideServiceV1"],"description":"Update existing item.","operationId":"testModule5OverrideServiceV1ScalarUpdatePut","parameters":[{"name":"entityId","in":"path","type":"string","required":true},{"name":"parentId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["name","orders"],"properties":{"name":{"type":"string"},"orders":{"type":"boolean"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v1-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V2/TestModule5/{id}":{"get":{"tags":["testModule5AllSoapAndRestV2"],"description":"Retrieve existing item.","operationId":"testModule5AllSoapAndRestV2ItemGet","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModule5AllSoapAndRestV2"],"description":"Update one item.","operationId":"testModule5AllSoapAndRestV2UpdatePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["testModule5AllSoapAndRestV2"],"description":"Delete existing item.","operationId":"testModule5AllSoapAndRestV2DeleteDelete","parameters":[{"name":"id","in":"path","type":"string","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V2/TestModule5":{"get":{"tags":["testModule5AllSoapAndRestV2"],"description":"Retrieve a list of all existing items.","operationId":"testModule5AllSoapAndRestV2ItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModule5AllSoapAndRestV2"],"description":"Add new item.","operationId":"testModule5AllSoapAndRestV2CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModuleDefaultHydrator":{"post":{"tags":["testModuleDefaultHydratorCustomerPersistenceV1"],"description":"Create customer","operationId":"testModuleDefaultHydratorCustomerPersistenceV1SavePost","parameters":[{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModuleDefaultHydrator/{id}":{"get":{"tags":["testModuleDefaultHydratorCustomerPersistenceV1"],"description":"Retrieve customer by id","operationId":"testModuleDefaultHydratorCustomerPersistenceV1GetByIdGet","parameters":[{"name":"id","in":"path","type":"integer","required":true},{"name":"websiteId","in":"query","type":"integer","required":false}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"delete":{"tags":["testModuleDefaultHydratorCustomerPersistenceV1"],"description":"Delete customer by id","operationId":"testModuleDefaultHydratorCustomerPersistenceV1DeleteDelete","parameters":[{"name":"id","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"type":"boolean"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModuleDefaultHydratorCustomerPersistenceV1"],"description":"Create customer","operationId":"testModuleDefaultHydratorCustomerPersistenceV1SavePut","parameters":[{"name":"id","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["customer"],"properties":{"customer":{"$ref":"#/definitions/customer-data-customer-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/customer-data-customer-interface"}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/TestModuleJoinDirectives":{"get":{"tags":["testModuleJoinDirectivesTestRepositoryV1"],"description":"Get list of quotes","operationId":"testModuleJoinDirectivesTestRepositoryV1GetListGet","parameters":[{"name":"searchCriteria[filterGroups][][filters][][field]","in":"query","type":"string","description":"Field"},{"name":"searchCriteria[filterGroups][][filters][][value]","in":"query","type":"string","description":"Value"},{"name":"searchCriteria[filterGroups][][filters][][conditionType]","in":"query","type":"string","description":"Condition type"},{"name":"searchCriteria[sortOrders][][field]","in":"query","type":"string","description":"Sorting field."},{"name":"searchCriteria[sortOrders][][direction]","in":"query","type":"string","description":"Sorting direction."},{"name":"searchCriteria[pageSize]","in":"query","type":"integer","description":"Page size."},{"name":"searchCriteria[currentPage]","in":"query","type":"integer","description":"Current page."}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/quote-data-cart-search-results-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC/overwritten":{"get":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1ItemGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC/testOptionalParam":{"post":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1TestOptionalParamPost","parameters":[{"name":"$body","in":"body","schema":{"properties":{"name":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC/{itemId}":{"get":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1ItemGet","parameters":[{"name":"itemId","in":"path","type":"integer","required":true}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"put":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1UpdatePut","parameters":[{"name":"itemId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC":{"get":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1ItemsGet","responses":{"200":{"description":"200 Success.","schema":{"type":"array","items":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}},"post":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1CreatePost","parameters":[{"name":"$body","in":"body","schema":{"required":["name"],"properties":{"name":{"type":"string"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC/itemAnyType":{"post":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1ItemAnyTypePost","parameters":[{"name":"$body","in":"body","schema":{"required":["entityItem"],"properties":{"entityItem":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/testmoduleMSC/itemPreconfigured":{"get":{"tags":["testModuleMSCAllSoapAndRestV1"],"description":"","operationId":"testModuleMSCAllSoapAndRestV1GetPreconfiguredItemGet","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module-ms-cdata-item-interface"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}},"/V1/worldpay-guest-carts/{cartId}/payment-information":{"post":{"tags":["worldpayGuestPaymentInformationManagementProxyV1"],"description":"Proxy handler for guest place order","operationId":"worldpayGuestPaymentInformationManagementProxyV1SavePaymentInformationAndPlaceOrderPost","parameters":[{"name":"cartId","in":"path","type":"string","required":true},{"name":"$body","in":"body","schema":{"required":["email","paymentMethod"],"properties":{"email":{"type":"string"},"paymentMethod":{"$ref":"#/definitions/quote-data-payment-interface"},"billingAddress":{"$ref":"#/definitions/quote-data-address-interface"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"type":"integer","description":"Order ID."}},"400":{"description":"400 Bad Request","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"store-data-store-interface":{"type":"object","description":"Store interface","properties":{"id":{"type":"integer"},"code":{"type":"string"},"name":{"type":"string","description":"Store name"},"website_id":{"type":"integer"},"store_group_id":{"type":"integer"},"extension_attributes":{"$ref":"#/definitions/store-data-store-extension-interface"}},"required":["id","code","name","website_id","store_group_id"]},"store-data-store-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Store\\Api\\Data\\StoreInterface"},"store-data-group-interface":{"type":"object","description":"Group interface","properties":{"id":{"type":"integer"},"website_id":{"type":"integer"},"root_category_id":{"type":"integer"},"default_store_id":{"type":"integer"},"name":{"type":"string"},"code":{"type":"string","description":"Group code."},"extension_attributes":{"$ref":"#/definitions/store-data-group-extension-interface"}},"required":["id","website_id","root_category_id","default_store_id","name","code"]},"store-data-group-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Store\\Api\\Data\\GroupInterface"},"store-data-website-interface":{"type":"object","description":"Website interface","properties":{"id":{"type":"integer"},"code":{"type":"string"},"name":{"type":"string","description":"Website name"},"default_group_id":{"type":"integer"},"extension_attributes":{"$ref":"#/definitions/store-data-website-extension-interface"}},"required":["id","code","name","default_group_id"]},"store-data-website-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Store\\Api\\Data\\WebsiteInterface"},"store-data-store-config-interface":{"type":"object","description":"StoreConfig interface","properties":{"id":{"type":"integer","description":"Store id"},"code":{"type":"string","description":"Store code"},"website_id":{"type":"integer","description":"Website id of the store"},"locale":{"type":"string","description":"Store locale"},"base_currency_code":{"type":"string","description":"Base currency code"},"default_display_currency_code":{"type":"string","description":"Default display currency code"},"timezone":{"type":"string","description":"Timezone of the store"},"weight_unit":{"type":"string","description":"The unit of weight"},"base_url":{"type":"string","description":"Base URL for the store"},"base_link_url":{"type":"string","description":"Base link URL for the store"},"base_static_url":{"type":"string","description":"Base static URL for the store"},"base_media_url":{"type":"string","description":"Base media URL for the store"},"secure_base_url":{"type":"string","description":"Secure base URL for the store"},"secure_base_link_url":{"type":"string","description":"Secure base link URL for the store"},"secure_base_static_url":{"type":"string","description":"Secure base static URL for the store"},"secure_base_media_url":{"type":"string","description":"Secure base media URL for the store"},"extension_attributes":{"$ref":"#/definitions/store-data-store-config-extension-interface"}},"required":["id","code","website_id","locale","base_currency_code","default_display_currency_code","timezone","weight_unit","base_url","base_link_url","base_static_url","base_media_url","secure_base_url","secure_base_link_url","secure_base_static_url","secure_base_media_url"]},"store-data-store-config-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Store\\Api\\Data\\StoreConfigInterface"},"directory-data-currency-information-interface":{"type":"object","description":"Currency Information interface.","properties":{"base_currency_code":{"type":"string","description":"The base currency code for the store."},"base_currency_symbol":{"type":"string","description":"The currency symbol of the base currency for the store."},"default_display_currency_code":{"type":"string","description":"The default display currency code for the store."},"default_display_currency_symbol":{"type":"string","description":"The currency symbol of the default display currency for the store."},"available_currency_codes":{"type":"array","description":"The list of allowed currency codes for the store.","items":{"type":"string"}},"exchange_rates":{"type":"array","description":"The list of exchange rate information for the store.","items":{"$ref":"#/definitions/directory-data-exchange-rate-interface"}},"extension_attributes":{"$ref":"#/definitions/directory-data-currency-information-extension-interface"}},"required":["base_currency_code","base_currency_symbol","default_display_currency_code","default_display_currency_symbol","available_currency_codes","exchange_rates"]},"directory-data-exchange-rate-interface":{"type":"object","description":"Exchange Rate interface.","properties":{"currency_to":{"type":"string","description":"The currency code associated with the exchange rate."},"rate":{"type":"number","description":"The exchange rate for the associated currency and the store's base currency."},"extension_attributes":{"$ref":"#/definitions/directory-data-exchange-rate-extension-interface"}},"required":["currency_to","rate"]},"directory-data-exchange-rate-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Directory\\Api\\Data\\ExchangeRateInterface"},"directory-data-currency-information-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Directory\\Api\\Data\\CurrencyInformationInterface"},"directory-data-country-information-interface":{"type":"object","description":"Country Information interface.","properties":{"id":{"type":"string","description":"The country id for the store."},"two_letter_abbreviation":{"type":"string","description":"The country 2 letter abbreviation for the store."},"three_letter_abbreviation":{"type":"string","description":"The country 3 letter abbreviation for the store."},"full_name_locale":{"type":"string","description":"The country full name (in store locale) for the store."},"full_name_english":{"type":"string","description":"The country full name (in English) for the store."},"available_regions":{"type":"array","description":"The available regions for the store.","items":{"$ref":"#/definitions/directory-data-region-information-interface"}},"extension_attributes":{"$ref":"#/definitions/directory-data-country-information-extension-interface"}},"required":["id","two_letter_abbreviation","three_letter_abbreviation","full_name_locale","full_name_english"]},"directory-data-region-information-interface":{"type":"object","description":"Region Information interface.","properties":{"id":{"type":"string","description":"Region id"},"code":{"type":"string","description":"Region code"},"name":{"type":"string","description":"Region name"},"extension_attributes":{"$ref":"#/definitions/directory-data-region-information-extension-interface"}},"required":["id","code","name"]},"directory-data-region-information-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Directory\\Api\\Data\\RegionInformationInterface"},"directory-data-country-information-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Directory\\Api\\Data\\CountryInformationInterface"},"eav-data-attribute-set-search-results-interface":{"type":"object","description":"Interface AttributeSetSearchResultsInterface","properties":{"items":{"type":"array","description":"Attribute sets list.","items":{"$ref":"#/definitions/eav-data-attribute-set-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"eav-data-attribute-set-interface":{"type":"object","description":"Interface AttributeSetInterface","properties":{"attribute_set_id":{"type":"integer","description":"Attribute set ID"},"attribute_set_name":{"type":"string","description":"Attribute set name"},"sort_order":{"type":"integer","description":"Attribute set sort order index"},"entity_type_id":{"type":"integer","description":"Attribute set entity type id"},"extension_attributes":{"$ref":"#/definitions/eav-data-attribute-set-extension-interface"}},"required":["attribute_set_name","sort_order"]},"eav-data-attribute-set-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Eav\\Api\\Data\\AttributeSetInterface"},"framework-search-criteria-interface":{"type":"object","description":"Search criteria interface.","properties":{"filter_groups":{"type":"array","description":"A list of filter groups.","items":{"$ref":"#/definitions/framework-search-filter-group"}},"sort_orders":{"type":"array","description":"Sort order.","items":{"$ref":"#/definitions/framework-sort-order"}},"page_size":{"type":"integer","description":"Page size."},"current_page":{"type":"integer","description":"Current page."}},"required":["filter_groups"]},"framework-search-filter-group":{"type":"object","description":"Groups two or more filters together using a logical OR","properties":{"filters":{"type":"array","description":"A list of filters in this group","items":{"$ref":"#/definitions/framework-filter"}}}},"framework-filter":{"type":"object","description":"Filter which can be used by any methods from service layer.","properties":{"field":{"type":"string","description":"Field"},"value":{"type":"string","description":"Value"},"condition_type":{"type":"string","description":"Condition type"}},"required":["field","value"]},"framework-sort-order":{"type":"object","description":"Data object for sort order.","properties":{"field":{"type":"string","description":"Sorting field."},"direction":{"type":"string","description":"Sorting direction."}},"required":["field","direction"]},"customer-data-group-interface":{"type":"object","description":"Customer group interface.","properties":{"id":{"type":"integer","description":"Id"},"code":{"type":"string","description":"Code"},"tax_class_id":{"type":"integer","description":"Tax class id"},"tax_class_name":{"type":"string","description":"Tax class name"},"extension_attributes":{"$ref":"#/definitions/customer-data-group-extension-interface"}},"required":["code","tax_class_id"]},"customer-data-group-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Customer\\Api\\Data\\GroupInterface"},"customer-data-group-search-results-interface":{"type":"object","description":"Interface for customer groups search results.","properties":{"items":{"type":"array","description":"Customer groups list.","items":{"$ref":"#/definitions/customer-data-group-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"customer-data-attribute-metadata-interface":{"type":"object","description":"Customer attribute metadata interface.","properties":{"frontend_input":{"type":"string","description":"HTML for input element."},"input_filter":{"type":"string","description":"Template used for input (e.g. \"date\")"},"store_label":{"type":"string","description":"Label of the store."},"validation_rules":{"type":"array","description":"Validation rules.","items":{"$ref":"#/definitions/customer-data-validation-rule-interface"}},"multiline_count":{"type":"integer","description":"Of lines of the attribute value."},"visible":{"type":"boolean","description":"Attribute is visible on frontend."},"required":{"type":"boolean","description":"Attribute is required."},"data_model":{"type":"string","description":"Data model for attribute."},"options":{"type":"array","description":"Options of the attribute (key => value pairs for select)","items":{"$ref":"#/definitions/customer-data-option-interface"}},"frontend_class":{"type":"string","description":"Class which is used to display the attribute on frontend."},"user_defined":{"type":"boolean","description":"Current attribute has been defined by a user."},"sort_order":{"type":"integer","description":"Attributes sort order."},"frontend_label":{"type":"string","description":"Label which supposed to be displayed on frontend."},"note":{"type":"string","description":"The note attribute for the element."},"system":{"type":"boolean","description":"This is a system attribute."},"backend_type":{"type":"string","description":"Backend type."},"is_used_in_grid":{"type":"boolean","description":"It is used in customer grid"},"is_visible_in_grid":{"type":"boolean","description":"It is visible in customer grid"},"is_filterable_in_grid":{"type":"boolean","description":"It is filterable in customer grid"},"is_searchable_in_grid":{"type":"boolean","description":"It is searchable in customer grid"},"attribute_code":{"type":"string","description":"Code of the attribute."}},"required":["frontend_input","input_filter","store_label","validation_rules","multiline_count","visible","required","data_model","options","frontend_class","user_defined","sort_order","frontend_label","note","system","backend_type","attribute_code"]},"customer-data-validation-rule-interface":{"type":"object","description":"Validation rule interface.","properties":{"name":{"type":"string","description":"Validation rule name"},"value":{"type":"string","description":"Validation rule value"}},"required":["name","value"]},"customer-data-option-interface":{"type":"object","description":"Option interface.","properties":{"label":{"type":"string","description":"Option label"},"value":{"type":"string","description":"Option value"},"options":{"type":"array","description":"Nested options","items":{"$ref":"#/definitions/customer-data-option-interface"}}},"required":["label"]},"customer-data-customer-interface":{"type":"object","description":"Customer interface.","properties":{"id":{"type":"integer","description":"Customer id"},"group_id":{"type":"integer","description":"Group id"},"default_billing":{"type":"string","description":"Default billing address id"},"default_shipping":{"type":"string","description":"Default shipping address id"},"confirmation":{"type":"string","description":"Confirmation"},"created_at":{"type":"string","description":"Created at time"},"updated_at":{"type":"string","description":"Updated at time"},"created_in":{"type":"string","description":"Created in area"},"dob":{"type":"string","description":"Date of birth"},"email":{"type":"string","description":"Email address"},"firstname":{"type":"string","description":"First name"},"lastname":{"type":"string","description":"Last name"},"middlename":{"type":"string","description":"Middle name"},"prefix":{"type":"string","description":"Prefix"},"suffix":{"type":"string","description":"Suffix"},"gender":{"type":"integer","description":"Gender"},"store_id":{"type":"integer","description":"Store id"},"taxvat":{"type":"string","description":"Tax Vat"},"website_id":{"type":"integer","description":"Website id"},"addresses":{"type":"array","description":"Customer addresses.","items":{"$ref":"#/definitions/customer-data-address-interface"}},"disable_auto_group_change":{"type":"integer","description":"Disable auto group change flag."},"extension_attributes":{"$ref":"#/definitions/customer-data-customer-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["email","firstname","lastname"]},"customer-data-address-interface":{"type":"object","description":"Customer address interface.","properties":{"id":{"type":"integer","description":"ID"},"customer_id":{"type":"integer","description":"Customer ID"},"region":{"$ref":"#/definitions/customer-data-region-interface"},"region_id":{"type":"integer","description":"Region ID"},"country_id":{"type":"string","description":"Country code in ISO_3166-2 format"},"street":{"type":"array","description":"Street","items":{"type":"string"}},"company":{"type":"string","description":"Company"},"telephone":{"type":"string","description":"Telephone number"},"fax":{"type":"string","description":"Fax number"},"postcode":{"type":"string","description":"Postcode"},"city":{"type":"string","description":"City name"},"firstname":{"type":"string","description":"First name"},"lastname":{"type":"string","description":"Last name"},"middlename":{"type":"string","description":"Middle name"},"prefix":{"type":"string","description":"Prefix"},"suffix":{"type":"string","description":"Suffix"},"vat_id":{"type":"string","description":"Vat id"},"default_shipping":{"type":"boolean","description":"If this address is default shipping address."},"default_billing":{"type":"boolean","description":"If this address is default billing address"},"extension_attributes":{"$ref":"#/definitions/customer-data-address-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}}},"customer-data-region-interface":{"type":"object","description":"Customer address region interface.","properties":{"region_code":{"type":"string","description":"Region code"},"region":{"type":"string","description":"Region"},"region_id":{"type":"integer","description":"Region id"},"extension_attributes":{"$ref":"#/definitions/customer-data-region-extension-interface"}},"required":["region_code","region","region_id"]},"customer-data-region-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Customer\\Api\\Data\\RegionInterface"},"customer-data-address-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Customer\\Api\\Data\\AddressInterface"},"framework-attribute-interface":{"type":"object","description":"Interface for custom attribute value.","properties":{"attribute_code":{"type":"string","description":"Attribute code"},"value":{"type":"string","description":"Attribute value"}},"required":["attribute_code","value"]},"customer-data-customer-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Customer\\Api\\Data\\CustomerInterface","properties":{"is_subscribed":{"type":"boolean"},"extension_attribute":{"$ref":"#/definitions/test-module-default-hydrator-data-extension-attribute-interface"}}},"test-module-default-hydrator-data-extension-attribute-interface":{"type":"object","description":"","properties":{"id":{"type":"integer","description":"ID"},"customer_id":{"type":"integer","description":"Customer ID"},"value":{"type":"string","description":"Value"}}},"customer-data-customer-search-results-interface":{"type":"object","description":"Interface for customer search results.","properties":{"items":{"type":"array","description":"Customers list.","items":{"$ref":"#/definitions/customer-data-customer-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"customer-data-validation-results-interface":{"type":"object","description":"Validation results interface.","properties":{"valid":{"type":"boolean","description":"If the provided data is valid."},"messages":{"type":"array","description":"Error messages as array in case of validation failure, else return empty array.","items":{"type":"string"}}},"required":["valid","messages"]},"cms-data-page-interface":{"type":"object","description":"CMS page interface.","properties":{"id":{"type":"integer","description":"ID"},"identifier":{"type":"string","description":"Identifier"},"title":{"type":"string","description":"Title"},"page_layout":{"type":"string","description":"Page layout"},"meta_title":{"type":"string","description":"Meta title"},"meta_keywords":{"type":"string","description":"Meta keywords"},"meta_description":{"type":"string","description":"Meta description"},"content_heading":{"type":"string","description":"Content heading"},"content":{"type":"string","description":"Content"},"creation_time":{"type":"string","description":"Creation time"},"update_time":{"type":"string","description":"Update time"},"sort_order":{"type":"string","description":"Sort order"},"layout_update_xml":{"type":"string","description":"Layout update xml"},"custom_theme":{"type":"string","description":"Custom theme"},"custom_root_template":{"type":"string","description":"Custom root template"},"custom_layout_update_xml":{"type":"string","description":"Custom layout update xml"},"custom_theme_from":{"type":"string","description":"Custom theme from"},"custom_theme_to":{"type":"string","description":"Custom theme to"},"active":{"type":"boolean","description":"Active"}},"required":["identifier"]},"cms-data-page-search-results-interface":{"type":"object","description":"Interface for cms page search results.","properties":{"items":{"type":"array","description":"Pages list.","items":{"$ref":"#/definitions/cms-data-page-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"cms-data-block-interface":{"type":"object","description":"CMS block interface.","properties":{"id":{"type":"integer","description":"ID"},"identifier":{"type":"string","description":"Identifier"},"title":{"type":"string","description":"Title"},"content":{"type":"string","description":"Content"},"creation_time":{"type":"string","description":"Creation time"},"update_time":{"type":"string","description":"Update time"},"active":{"type":"boolean","description":"Active"}},"required":["identifier"]},"cms-data-block-search-results-interface":{"type":"object","description":"Interface for cms block search results.","properties":{"items":{"type":"array","description":"Blocks list.","items":{"$ref":"#/definitions/cms-data-block-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-data-product-interface":{"type":"object","description":"","properties":{"id":{"type":"integer","description":"Id"},"sku":{"type":"string","description":"Sku"},"name":{"type":"string","description":"Name"},"attribute_set_id":{"type":"integer","description":"Attribute set id"},"price":{"type":"number","description":"Price"},"status":{"type":"integer","description":"Status"},"visibility":{"type":"integer","description":"Visibility"},"type_id":{"type":"string","description":"Type id"},"created_at":{"type":"string","description":"Created date"},"updated_at":{"type":"string","description":"Updated date"},"weight":{"type":"number","description":"Weight"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-extension-interface"},"product_links":{"type":"array","description":"Product links info","items":{"$ref":"#/definitions/catalog-data-product-link-interface"}},"options":{"type":"array","description":"List of product options","items":{"$ref":"#/definitions/catalog-data-product-custom-option-interface"}},"media_gallery_entries":{"type":"array","description":"Media gallery entries","items":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-interface"}},"tier_prices":{"type":"array","description":"List of product tier prices","items":{"$ref":"#/definitions/catalog-data-product-tier-price-interface"}},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["sku"]},"catalog-data-product-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductInterface","properties":{"website_ids":{"type":"array","items":{"type":"integer"}},"category_links":{"type":"array","items":{"$ref":"#/definitions/catalog-data-category-link-interface"}},"stock_item":{"$ref":"#/definitions/catalog-inventory-data-stock-item-interface"},"bundle_product_options":{"type":"array","items":{"$ref":"#/definitions/bundle-data-option-interface"}},"downloadable_product_links":{"type":"array","items":{"$ref":"#/definitions/downloadable-data-link-interface"}},"downloadable_product_samples":{"type":"array","items":{"$ref":"#/definitions/downloadable-data-sample-interface"}},"giftcard_amounts":{"type":"array","items":{"$ref":"#/definitions/gift-card-data-giftcard-amount-interface"}},"configurable_product_options":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-option-interface"}},"configurable_product_links":{"type":"array","items":{"type":"integer"}}}},"catalog-data-category-link-interface":{"type":"object","description":"","properties":{"position":{"type":"integer"},"category_id":{"type":"string","description":"Category id"},"extension_attributes":{"$ref":"#/definitions/catalog-data-category-link-extension-interface"}},"required":["category_id"]},"catalog-data-category-link-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\CategoryLinkInterface"},"catalog-inventory-data-stock-item-interface":{"type":"object","description":"Interface StockItem","properties":{"item_id":{"type":"integer"},"product_id":{"type":"integer"},"stock_id":{"type":"integer","description":"Stock identifier"},"qty":{"type":"number"},"is_in_stock":{"type":"boolean","description":"Stock Availability"},"is_qty_decimal":{"type":"boolean"},"show_default_notification_message":{"type":"boolean"},"use_config_min_qty":{"type":"boolean"},"min_qty":{"type":"number","description":"Minimal quantity available for item status in stock"},"use_config_min_sale_qty":{"type":"integer"},"min_sale_qty":{"type":"number","description":"Minimum Qty Allowed in Shopping Cart or NULL when there is no limitation"},"use_config_max_sale_qty":{"type":"boolean"},"max_sale_qty":{"type":"number","description":"Maximum Qty Allowed in Shopping Cart data wrapper"},"use_config_backorders":{"type":"boolean"},"backorders":{"type":"integer","description":"Backorders status"},"use_config_notify_stock_qty":{"type":"boolean"},"notify_stock_qty":{"type":"number","description":"Notify for Quantity Below data wrapper"},"use_config_qty_increments":{"type":"boolean"},"qty_increments":{"type":"number","description":"Quantity Increments data wrapper"},"use_config_enable_qty_inc":{"type":"boolean"},"enable_qty_increments":{"type":"boolean","description":"Whether Quantity Increments is enabled"},"use_config_manage_stock":{"type":"boolean"},"manage_stock":{"type":"boolean","description":"Can Manage Stock"},"low_stock_date":{"type":"string"},"is_decimal_divided":{"type":"boolean"},"stock_status_changed_auto":{"type":"integer"},"extension_attributes":{"$ref":"#/definitions/catalog-inventory-data-stock-item-extension-interface"}},"required":["qty","is_in_stock","is_qty_decimal","show_default_notification_message","use_config_min_qty","min_qty","use_config_min_sale_qty","min_sale_qty","use_config_max_sale_qty","max_sale_qty","use_config_backorders","backorders","use_config_notify_stock_qty","notify_stock_qty","use_config_qty_increments","qty_increments","use_config_enable_qty_inc","enable_qty_increments","use_config_manage_stock","manage_stock","low_stock_date","is_decimal_divided","stock_status_changed_auto"]},"catalog-inventory-data-stock-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\CatalogInventory\\Api\\Data\\StockItemInterface"},"bundle-data-option-interface":{"type":"object","description":"Interface OptionInterface","properties":{"option_id":{"type":"integer","description":"Option id"},"title":{"type":"string","description":"Option title"},"required":{"type":"boolean","description":"Is required option"},"type":{"type":"string","description":"Input type"},"position":{"type":"integer","description":"Option position"},"sku":{"type":"string","description":"Product sku"},"product_links":{"type":"array","description":"Product links","items":{"$ref":"#/definitions/bundle-data-link-interface"}},"extension_attributes":{"$ref":"#/definitions/bundle-data-option-extension-interface"}}},"bundle-data-link-interface":{"type":"object","description":"Interface LinkInterface","properties":{"id":{"type":"string","description":"The identifier"},"sku":{"type":"string","description":"Linked product sku"},"option_id":{"type":"integer","description":"Option id"},"qty":{"type":"number","description":"Qty"},"position":{"type":"integer","description":"Position"},"is_default":{"type":"boolean","description":"Is default"},"price":{"type":"number","description":"Price"},"price_type":{"type":"integer","description":"Price type"},"can_change_quantity":{"type":"integer","description":"Whether quantity could be changed"},"extension_attributes":{"$ref":"#/definitions/bundle-data-link-extension-interface"}},"required":["is_default","price","price_type"]},"bundle-data-link-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Bundle\\Api\\Data\\LinkInterface"},"bundle-data-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Bundle\\Api\\Data\\OptionInterface"},"downloadable-data-link-interface":{"type":"object","description":"","properties":{"id":{"type":"integer","description":"Sample(or link) id"},"title":{"type":"string"},"sort_order":{"type":"integer"},"is_shareable":{"type":"integer","description":"Shareable status"},"price":{"type":"number","description":"Price"},"number_of_downloads":{"type":"integer","description":"Of downloads per user"},"link_type":{"type":"string"},"link_file":{"type":"string","description":"relative file path"},"link_file_content":{"$ref":"#/definitions/downloadable-data-file-content-interface"},"link_url":{"type":"string","description":"Link url or null when type is 'file'"},"sample_type":{"type":"string"},"sample_file":{"type":"string","description":"relative file path"},"sample_file_content":{"$ref":"#/definitions/downloadable-data-file-content-interface"},"sample_url":{"type":"string","description":"file URL"},"extension_attributes":{"$ref":"#/definitions/downloadable-data-link-extension-interface"}},"required":["sort_order","is_shareable","price","link_type","sample_type"]},"downloadable-data-file-content-interface":{"type":"object","description":"","properties":{"file_data":{"type":"string","description":"Data (base64 encoded content)"},"name":{"type":"string","description":"File name"},"extension_attributes":{"$ref":"#/definitions/downloadable-data-file-content-extension-interface"}},"required":["file_data","name"]},"downloadable-data-file-content-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Downloadable\\Api\\Data\\File\\ContentInterface"},"downloadable-data-link-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Downloadable\\Api\\Data\\LinkInterface"},"downloadable-data-sample-interface":{"type":"object","description":"","properties":{"id":{"type":"integer","description":"Sample(or link) id"},"title":{"type":"string","description":"Title"},"sort_order":{"type":"integer","description":"Order index for sample"},"sample_type":{"type":"string"},"sample_file":{"type":"string","description":"relative file path"},"sample_file_content":{"$ref":"#/definitions/downloadable-data-file-content-interface"},"sample_url":{"type":"string","description":"file URL"},"extension_attributes":{"$ref":"#/definitions/downloadable-data-sample-extension-interface"}},"required":["title","sort_order","sample_type"]},"downloadable-data-sample-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Downloadable\\Api\\Data\\SampleInterface"},"gift-card-data-giftcard-amount-interface":{"type":"object","description":"Interface GiftcardAmountInterface: this interface is used to serialize and deserialize EAV attribute giftcard_amounts","properties":{"attribute_id":{"type":"integer"},"website_id":{"type":"integer"},"value":{"type":"number"},"website_value":{"type":"number"},"extension_attributes":{"$ref":"#/definitions/gift-card-data-giftcard-amount-extension-interface"}},"required":["attribute_id","website_id","value","website_value"]},"gift-card-data-giftcard-amount-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\GiftCard\\Api\\Data\\GiftcardAmountInterface"},"configurable-product-data-option-interface":{"type":"object","description":"Interface OptionInterface","properties":{"id":{"type":"integer"},"attribute_id":{"type":"string"},"label":{"type":"string"},"position":{"type":"integer"},"is_use_default":{"type":"boolean"},"values":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-option-value-interface"}},"extension_attributes":{"$ref":"#/definitions/configurable-product-data-option-extension-interface"},"product_id":{"type":"integer"}}},"configurable-product-data-option-value-interface":{"type":"object","description":"Interface OptionValueInterface","properties":{"value_index":{"type":"integer"},"extension_attributes":{"$ref":"#/definitions/configurable-product-data-option-value-extension-interface"}},"required":["value_index"]},"configurable-product-data-option-value-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\ConfigurableProduct\\Api\\Data\\OptionValueInterface"},"configurable-product-data-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\ConfigurableProduct\\Api\\Data\\OptionInterface"},"catalog-data-product-link-interface":{"type":"object","description":"","properties":{"sku":{"type":"string","description":"SKU"},"link_type":{"type":"string","description":"Link type"},"linked_product_sku":{"type":"string","description":"Linked product sku"},"linked_product_type":{"type":"string","description":"Linked product type (simple, virtual, etc)"},"position":{"type":"integer","description":"Linked item position"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-link-extension-interface"}},"required":["sku","link_type","linked_product_sku","linked_product_type","position"]},"catalog-data-product-link-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductLinkInterface","properties":{"qty":{"type":"number"}}},"catalog-data-product-custom-option-interface":{"type":"object","description":"","properties":{"product_sku":{"type":"string","description":"Product SKU"},"option_id":{"type":"integer","description":"Option id"},"title":{"type":"string","description":"Option title"},"type":{"type":"string","description":"Option type"},"sort_order":{"type":"integer","description":"Sort order"},"is_require":{"type":"boolean","description":"Is require"},"price":{"type":"number","description":"Price"},"price_type":{"type":"string","description":"Price type"},"sku":{"type":"string","description":"Sku"},"file_extension":{"type":"string"},"max_characters":{"type":"integer"},"image_size_x":{"type":"integer"},"image_size_y":{"type":"integer"},"values":{"type":"array","items":{"$ref":"#/definitions/catalog-data-product-custom-option-values-interface"}},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-custom-option-extension-interface"}},"required":["product_sku","title","type","sort_order","is_require"]},"catalog-data-product-custom-option-values-interface":{"type":"object","description":"","properties":{"title":{"type":"string","description":"Option title"},"sort_order":{"type":"integer","description":"Sort order"},"price":{"type":"number","description":"Price"},"price_type":{"type":"string","description":"Price type"},"sku":{"type":"string","description":"Sku"},"option_type_id":{"type":"integer","description":"Option type id"}},"required":["title","sort_order","price","price_type"]},"catalog-data-product-custom-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductCustomOptionInterface"},"catalog-data-product-attribute-media-gallery-entry-interface":{"type":"object","description":"","properties":{"id":{"type":"integer","description":"Gallery entry ID"},"media_type":{"type":"string","description":"Media type"},"label":{"type":"string","description":"Gallery entry alternative text"},"position":{"type":"integer","description":"Gallery entry position (sort order)"},"disabled":{"type":"boolean","description":"If gallery entry is hidden from product page"},"types":{"type":"array","description":"Gallery entry image types (thumbnail, image, small_image etc)","items":{"type":"string"}},"file":{"type":"string","description":"File path"},"content":{"$ref":"#/definitions/framework-data-image-content-interface"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-attribute-media-gallery-entry-extension-interface"}},"required":["media_type","label","position","disabled","types"]},"framework-data-image-content-interface":{"type":"object","description":"Image Content data interface","properties":{"base64_encoded_data":{"type":"string","description":"Media data (base64 encoded content)"},"type":{"type":"string","description":"MIME type"},"name":{"type":"string","description":"Image name"}},"required":["base64_encoded_data","type","name"]},"catalog-data-product-attribute-media-gallery-entry-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductAttributeMediaGalleryEntryInterface","properties":{"video_content":{"$ref":"#/definitions/framework-data-video-content-interface"}}},"framework-data-video-content-interface":{"type":"object","description":"Video Content data interface","properties":{"media_type":{"type":"string","description":"MIME type"},"video_provider":{"type":"string","description":"Provider"},"video_url":{"type":"string","description":"Video URL"},"video_title":{"type":"string","description":"Title"},"video_description":{"type":"string","description":"Video Description"},"video_metadata":{"type":"string","description":"Metadata"}},"required":["media_type","video_provider","video_url","video_title","video_description","video_metadata"]},"catalog-data-product-tier-price-interface":{"type":"object","description":"","properties":{"customer_group_id":{"type":"integer","description":"Customer group id"},"qty":{"type":"number","description":"Tier qty"},"value":{"type":"number","description":"Price value"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-tier-price-extension-interface"}},"required":["customer_group_id","qty","value"]},"catalog-data-product-tier-price-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductTierPriceInterface","properties":{"percentage_value":{"type":"number"},"website_id":{"type":"integer"}}},"catalog-data-product-search-results-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Attributes list.","items":{"$ref":"#/definitions/catalog-data-product-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-data-product-attribute-type-interface":{"type":"object","description":"","properties":{"value":{"type":"string","description":"Value"},"label":{"type":"string","description":"Type label"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-attribute-type-extension-interface"}},"required":["value","label"]},"catalog-data-product-attribute-type-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductAttributeTypeInterface"},"catalog-data-product-attribute-interface":{"type":"object","description":"","properties":{"is_wysiwyg_enabled":{"type":"boolean","description":"WYSIWYG flag"},"is_html_allowed_on_front":{"type":"boolean","description":"The HTML tags are allowed on the frontend"},"used_for_sort_by":{"type":"boolean","description":"It is used for sorting in product listing"},"is_filterable":{"type":"boolean","description":"It used in layered navigation"},"is_filterable_in_search":{"type":"boolean","description":"It is used in search results layered navigation"},"is_used_in_grid":{"type":"boolean","description":"It is used in catalog product grid"},"is_visible_in_grid":{"type":"boolean","description":"It is visible in catalog product grid"},"is_filterable_in_grid":{"type":"boolean","description":"It is filterable in catalog product grid"},"position":{"type":"integer","description":"Position"},"apply_to":{"type":"array","description":"Apply to value for the element","items":{"type":"string"}},"is_searchable":{"type":"string","description":"The attribute can be used in Quick Search"},"is_visible_in_advanced_search":{"type":"string","description":"The attribute can be used in Advanced Search"},"is_comparable":{"type":"string","description":"The attribute can be compared on the frontend"},"is_used_for_promo_rules":{"type":"string","description":"The attribute can be used for promo rules"},"is_visible_on_front":{"type":"string","description":"The attribute is visible on the frontend"},"used_in_product_listing":{"type":"string","description":"The attribute can be used in product listing"},"is_visible":{"type":"boolean","description":"Attribute is visible on frontend."},"scope":{"type":"string","description":"Attribute scope"},"extension_attributes":{"$ref":"#/definitions/catalog-data-eav-attribute-extension-interface"},"attribute_id":{"type":"integer","description":"Id of the attribute."},"attribute_code":{"type":"string","description":"Code of the attribute."},"frontend_input":{"type":"string","description":"HTML for input element."},"entity_type_id":{"type":"string","description":"Entity type id"},"is_required":{"type":"boolean","description":"Attribute is required."},"options":{"type":"array","description":"Options of the attribute (key => value pairs for select)","items":{"$ref":"#/definitions/eav-data-attribute-option-interface"}},"is_user_defined":{"type":"boolean","description":"Current attribute has been defined by a user."},"default_frontend_label":{"type":"string","description":"Frontend label for default store"},"frontend_labels":{"type":"array","description":"Frontend label for each store","items":{"$ref":"#/definitions/eav-data-attribute-frontend-label-interface"}},"note":{"type":"string","description":"The note attribute for the element."},"backend_type":{"type":"string","description":"Backend type."},"backend_model":{"type":"string","description":"Backend model"},"source_model":{"type":"string","description":"Source model"},"default_value":{"type":"string","description":"Default value for the element."},"is_unique":{"type":"string","description":"This is a unique attribute"},"frontend_class":{"type":"string","description":"Frontend class of attribute"},"validation_rules":{"type":"array","description":"Validation rules.","items":{"$ref":"#/definitions/eav-data-attribute-validation-rule-interface"}},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["attribute_code","frontend_input","entity_type_id","is_required","frontend_labels"]},"catalog-data-eav-attribute-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\EavAttributeInterface"},"eav-data-attribute-option-interface":{"type":"object","description":"Created from:","properties":{"label":{"type":"string","description":"Option label"},"value":{"type":"string","description":"Option value"},"sort_order":{"type":"integer","description":"Option order"},"is_default":{"type":"boolean","description":"Default"},"store_labels":{"type":"array","description":"Option label for store scopes","items":{"$ref":"#/definitions/eav-data-attribute-option-label-interface"}}},"required":["label","value"]},"eav-data-attribute-option-label-interface":{"type":"object","description":"Interface AttributeOptionLabelInterface","properties":{"store_id":{"type":"integer","description":"Store id"},"label":{"type":"string","description":"Option label"}}},"eav-data-attribute-frontend-label-interface":{"type":"object","description":"Interface AttributeFrontendLabelInterface","properties":{"store_id":{"type":"integer","description":"Store id"},"label":{"type":"string","description":"Option label"}}},"eav-data-attribute-validation-rule-interface":{"type":"object","description":"Interface AttributeValidationRuleInterface","properties":{"key":{"type":"string","description":"Object key"},"value":{"type":"string","description":"Object value"}},"required":["key","value"]},"catalog-data-product-attribute-search-results-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Attributes list.","items":{"$ref":"#/definitions/catalog-data-product-attribute-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-data-category-attribute-interface":{"type":"object","description":"","properties":{"is_wysiwyg_enabled":{"type":"boolean","description":"WYSIWYG flag"},"is_html_allowed_on_front":{"type":"boolean","description":"The HTML tags are allowed on the frontend"},"used_for_sort_by":{"type":"boolean","description":"It is used for sorting in product listing"},"is_filterable":{"type":"boolean","description":"It used in layered navigation"},"is_filterable_in_search":{"type":"boolean","description":"It is used in search results layered navigation"},"is_used_in_grid":{"type":"boolean","description":"It is used in catalog product grid"},"is_visible_in_grid":{"type":"boolean","description":"It is visible in catalog product grid"},"is_filterable_in_grid":{"type":"boolean","description":"It is filterable in catalog product grid"},"position":{"type":"integer","description":"Position"},"apply_to":{"type":"array","description":"Apply to value for the element","items":{"type":"string"}},"is_searchable":{"type":"string","description":"The attribute can be used in Quick Search"},"is_visible_in_advanced_search":{"type":"string","description":"The attribute can be used in Advanced Search"},"is_comparable":{"type":"string","description":"The attribute can be compared on the frontend"},"is_used_for_promo_rules":{"type":"string","description":"The attribute can be used for promo rules"},"is_visible_on_front":{"type":"string","description":"The attribute is visible on the frontend"},"used_in_product_listing":{"type":"string","description":"The attribute can be used in product listing"},"is_visible":{"type":"boolean","description":"Attribute is visible on frontend."},"scope":{"type":"string","description":"Attribute scope"},"extension_attributes":{"$ref":"#/definitions/catalog-data-eav-attribute-extension-interface"},"attribute_id":{"type":"integer","description":"Id of the attribute."},"attribute_code":{"type":"string","description":"Code of the attribute."},"frontend_input":{"type":"string","description":"HTML for input element."},"entity_type_id":{"type":"string","description":"Entity type id"},"is_required":{"type":"boolean","description":"Attribute is required."},"options":{"type":"array","description":"Options of the attribute (key => value pairs for select)","items":{"$ref":"#/definitions/eav-data-attribute-option-interface"}},"is_user_defined":{"type":"boolean","description":"Current attribute has been defined by a user."},"default_frontend_label":{"type":"string","description":"Frontend label for default store"},"frontend_labels":{"type":"array","description":"Frontend label for each store","items":{"$ref":"#/definitions/eav-data-attribute-frontend-label-interface"}},"note":{"type":"string","description":"The note attribute for the element."},"backend_type":{"type":"string","description":"Backend type."},"backend_model":{"type":"string","description":"Backend model"},"source_model":{"type":"string","description":"Source model"},"default_value":{"type":"string","description":"Default value for the element."},"is_unique":{"type":"string","description":"This is a unique attribute"},"frontend_class":{"type":"string","description":"Frontend class of attribute"},"validation_rules":{"type":"array","description":"Validation rules.","items":{"$ref":"#/definitions/eav-data-attribute-validation-rule-interface"}},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["attribute_code","frontend_input","entity_type_id","is_required","frontend_labels"]},"catalog-data-category-attribute-search-results-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Attributes list.","items":{"$ref":"#/definitions/catalog-data-category-attribute-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-data-product-type-interface":{"type":"object","description":"Product type details","properties":{"name":{"type":"string","description":"Product type code"},"label":{"type":"string","description":"Product type label"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-type-extension-interface"}},"required":["name","label"]},"catalog-data-product-type-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductTypeInterface"},"eav-data-attribute-group-search-results-interface":{"type":"object","description":"Interface AttributeGroupSearchResultsInterface","properties":{"items":{"type":"array","description":"Attribute sets list.","items":{"$ref":"#/definitions/eav-data-attribute-group-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"eav-data-attribute-group-interface":{"type":"object","description":"Interface AttributeGroupInterface","properties":{"attribute_group_id":{"type":"string","description":"Id"},"attribute_group_name":{"type":"string","description":"Name"},"attribute_set_id":{"type":"integer","description":"Attribute set id"},"extension_attributes":{"$ref":"#/definitions/eav-data-attribute-group-extension-interface"}}},"eav-data-attribute-group-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Eav\\Api\\Data\\AttributeGroupInterface","properties":{"attribute_group_code":{"type":"string"},"sort_order":{"type":"string"}}},"catalog-data-tier-price-interface":{"type":"object","description":"Tier price interface.","properties":{"price":{"type":"number","description":"Tier price."},"price_type":{"type":"string","description":"Tier price type."},"website_id":{"type":"integer","description":"Website id."},"sku":{"type":"string","description":"SKU."},"customer_group":{"type":"string","description":"Customer group."},"quantity":{"type":"number","description":"Quantity."},"extension_attributes":{"$ref":"#/definitions/catalog-data-tier-price-extension-interface"}},"required":["price","price_type","website_id","sku","customer_group","quantity"]},"catalog-data-tier-price-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\TierPriceInterface"},"catalog-data-price-update-result-interface":{"type":"object","description":"Interface returned in case of incorrect price passed to efficient price API.","properties":{"message":{"type":"string","description":"Error message, that contains description of error occurred during price update."},"parameters":{"type":"array","description":"Parameters, that could be displayed in error message placeholders.","items":{"type":"string"}},"extension_attributes":{"$ref":"#/definitions/catalog-data-price-update-result-extension-interface"}},"required":["message","parameters"]},"catalog-data-price-update-result-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\PriceUpdateResultInterface"},"catalog-data-base-price-interface":{"type":"object","description":"Price interface.","properties":{"price":{"type":"number","description":"Price."},"store_id":{"type":"integer","description":"Store id."},"sku":{"type":"string","description":"SKU."},"extension_attributes":{"$ref":"#/definitions/catalog-data-base-price-extension-interface"}},"required":["price","store_id","sku"]},"catalog-data-base-price-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\BasePriceInterface"},"catalog-data-cost-interface":{"type":"object","description":"Cost interface.","properties":{"cost":{"type":"number","description":"Cost value."},"store_id":{"type":"integer","description":"Store id."},"sku":{"type":"string","description":"SKU."},"extension_attributes":{"$ref":"#/definitions/catalog-data-cost-extension-interface"}},"required":["cost","store_id","sku"]},"catalog-data-cost-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\CostInterface"},"catalog-data-special-price-interface":{"type":"object","description":"Product Special Price Interface is used to encapsulate data that can be processed by efficient price API.","properties":{"price":{"type":"number","description":"Product special price value."},"store_id":{"type":"integer","description":"ID of store, that contains special price value."},"sku":{"type":"string","description":"SKU of product, that contains special price value."},"price_from":{"type":"string","description":"Start date for special price in Y-m-d H:i:s format."},"price_to":{"type":"string","description":"End date for special price in Y-m-d H:i:s format."},"extension_attributes":{"$ref":"#/definitions/catalog-data-special-price-extension-interface"}},"required":["price","store_id","sku","price_from","price_to"]},"catalog-data-special-price-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\SpecialPriceInterface"},"catalog-data-category-interface":{"type":"object","description":"","properties":{"id":{"type":"integer"},"parent_id":{"type":"integer","description":"Parent category ID"},"name":{"type":"string","description":"Category name"},"is_active":{"type":"boolean","description":"Whether category is active"},"position":{"type":"integer","description":"Category position"},"level":{"type":"integer","description":"Category level"},"children":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"path":{"type":"string"},"available_sort_by":{"type":"array","items":{"type":"string"}},"include_in_menu":{"type":"boolean"},"extension_attributes":{"$ref":"#/definitions/catalog-data-category-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["name"]},"catalog-data-category-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\CategoryInterface"},"catalog-data-category-tree-interface":{"type":"object","description":"","properties":{"id":{"type":"integer"},"parent_id":{"type":"integer","description":"Parent category ID"},"name":{"type":"string","description":"Category name"},"is_active":{"type":"boolean","description":"Whether category is active"},"position":{"type":"integer","description":"Category position"},"level":{"type":"integer","description":"Category level"},"product_count":{"type":"integer","description":"Product count"},"children_data":{"type":"array","items":{"$ref":"#/definitions/catalog-data-category-tree-interface"}}},"required":["parent_id","name","is_active","position","level","product_count","children_data"]},"catalog-data-category-search-results-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Categories","items":{"$ref":"#/definitions/catalog-data-category-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-data-product-custom-option-type-interface":{"type":"object","description":"","properties":{"label":{"type":"string","description":"Option type label"},"code":{"type":"string","description":"Option type code"},"group":{"type":"string","description":"Option type group"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-custom-option-type-extension-interface"}},"required":["label","code","group"]},"catalog-data-product-custom-option-type-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductCustomOptionTypeInterface"},"catalog-data-product-link-type-interface":{"type":"object","description":"","properties":{"code":{"type":"integer","description":"Link type code"},"name":{"type":"string","description":"Link type name"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-link-type-extension-interface"}},"required":["code","name"]},"catalog-data-product-link-type-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductLinkTypeInterface"},"catalog-data-product-link-attribute-interface":{"type":"object","description":"","properties":{"code":{"type":"string","description":"Attribute code"},"type":{"type":"string","description":"Attribute type"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-link-attribute-extension-interface"}},"required":["code","type"]},"catalog-data-product-link-attribute-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductLinkAttributeInterface"},"catalog-data-category-product-link-interface":{"type":"object","description":"","properties":{"sku":{"type":"string"},"position":{"type":"integer"},"category_id":{"type":"string","description":"Category id"},"extension_attributes":{"$ref":"#/definitions/catalog-data-category-product-link-extension-interface"}},"required":["category_id"]},"catalog-data-category-product-link-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\CategoryProductLinkInterface"},"catalog-data-product-website-link-interface":{"type":"object","description":"","properties":{"sku":{"type":"string"},"website_id":{"type":"integer","description":"Website ids"}},"required":["sku","website_id"]},"catalog-data-product-render-search-results-interface":{"type":"object","description":"Dto that holds render information about products","properties":{"items":{"type":"array","description":"List of products rendered information","items":{"$ref":"#/definitions/catalog-data-product-render-interface"}}},"required":["items"]},"catalog-data-product-render-interface":{"type":"object","description":"Represents Data Object which holds enough information to render product This information is put into part as Add To Cart or Add to Compare Data or Price Data","properties":{"add_to_cart_button":{"$ref":"#/definitions/catalog-data-product-render-button-interface"},"add_to_compare_button":{"$ref":"#/definitions/catalog-data-product-render-button-interface"},"price_info":{"$ref":"#/definitions/catalog-data-product-render-price-info-interface"},"images":{"type":"array","description":"Enough information, that needed to render image on front","items":{"$ref":"#/definitions/catalog-data-product-render-image-interface"}},"url":{"type":"string","description":"Product url"},"id":{"type":"integer","description":"Product identifier"},"name":{"type":"string","description":"Product name"},"type":{"type":"string","description":"Product type. Such as bundle, grouped, simple, etc..."},"is_salable":{"type":"string","description":"Information about product saleability (In Stock)"},"store_id":{"type":"integer","description":"Information about current store id or requested store id"},"currency_code":{"type":"string","description":"Current or desired currency code to product"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-render-extension-interface"}},"required":["add_to_cart_button","add_to_compare_button","price_info","images","url","id","name","type","is_salable","store_id","currency_code","extension_attributes"]},"catalog-data-product-render-button-interface":{"type":"object","description":"Button interface. This interface represents all manner of product buttons: add to cart, add to compare, etc... The buttons describes by this interface should have interaction with backend","properties":{"post_data":{"type":"string","description":"Post data"},"url":{"type":"string","description":"Url, needed to add product to cart"},"required_options":{"type":"boolean","description":"Flag whether a product has options or not"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-render-button-extension-interface"}},"required":["post_data","url","required_options"]},"catalog-data-product-render-button-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductRender\\ButtonInterface"},"catalog-data-product-render-price-info-interface":{"type":"object","description":"Price interface.","properties":{"final_price":{"type":"number","description":"Final price"},"max_price":{"type":"number","description":"Max price of a product"},"max_regular_price":{"type":"number","description":"Max regular price"},"minimal_regular_price":{"type":"number","description":"Minimal regular price"},"special_price":{"type":"number","description":"Special price"},"minimal_price":{"type":"number"},"regular_price":{"type":"number","description":"Regular price"},"formatted_prices":{"$ref":"#/definitions/catalog-data-product-render-formatted-price-info-interface"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-render-price-info-extension-interface"}},"required":["final_price","max_price","max_regular_price","minimal_regular_price","special_price","minimal_price","regular_price","formatted_prices"]},"catalog-data-product-render-formatted-price-info-interface":{"type":"object","description":"Formatted Price interface. Aggregate formatted html with price representations. E.g.: <span class=\"price\">$9.00</span> Consider currency, rounding and html","properties":{"final_price":{"type":"string","description":"Html with final price"},"max_price":{"type":"string","description":"Max price of a product"},"minimal_price":{"type":"string","description":"The minimal price of the product or variation"},"max_regular_price":{"type":"string","description":"Max regular price"},"minimal_regular_price":{"type":"string","description":"Minimal regular price"},"special_price":{"type":"string","description":"Special price"},"regular_price":{"type":"string","description":"Price - is price of product without discounts and special price with taxes and fixed product tax"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-render-formatted-price-info-extension-interface"}},"required":["final_price","max_price","minimal_price","max_regular_price","minimal_regular_price","special_price","regular_price"]},"catalog-data-product-render-formatted-price-info-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductRender\\FormattedPriceInfoInterface"},"catalog-data-product-render-price-info-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductRender\\PriceInfoInterface","properties":{"msrp":{"$ref":"#/definitions/msrp-data-product-render-msrp-price-info-interface"},"tax_adjustments":{"$ref":"#/definitions/catalog-data-product-render-price-info-interface"},"weee_attributes":{"type":"array","items":{"$ref":"#/definitions/weee-data-product-render-weee-adjustment-attribute-interface"}},"weee_adjustment":{"type":"string"}}},"msrp-data-product-render-msrp-price-info-interface":{"type":"object","description":"Price interface.","properties":{"msrp_price":{"type":"string"},"is_applicable":{"type":"string"},"is_shown_price_on_gesture":{"type":"string"},"msrp_message":{"type":"string"},"explanation_message":{"type":"string"},"extension_attributes":{"$ref":"#/definitions/msrp-data-product-render-msrp-price-info-extension-interface"}},"required":["msrp_price","is_applicable","is_shown_price_on_gesture","msrp_message","explanation_message"]},"msrp-data-product-render-msrp-price-info-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Msrp\\Api\\Data\\ProductRender\\MsrpPriceInfoInterface"},"weee-data-product-render-weee-adjustment-attribute-interface":{"type":"object","description":"List of all weee attributes, their amounts, etc.., that product has","properties":{"amount":{"type":"string","description":"Weee attribute amount"},"tax_amount":{"type":"string","description":"Tax which is calculated to fixed product tax attribute"},"tax_amount_incl_tax":{"type":"string","description":"Tax amount of weee attribute"},"amount_excl_tax":{"type":"string","description":"Product amount exclude tax"},"attribute_code":{"type":"string","description":"Weee attribute code"},"extension_attributes":{"$ref":"#/definitions/weee-data-product-render-weee-adjustment-attribute-extension-interface"}},"required":["amount","tax_amount","tax_amount_incl_tax","amount_excl_tax","attribute_code","extension_attributes"]},"weee-data-product-render-weee-adjustment-attribute-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Weee\\Api\\Data\\ProductRender\\WeeeAdjustmentAttributeInterface"},"catalog-data-product-render-image-interface":{"type":"object","description":"Product Render image interface. Represents physical characteristics of image, that can be used in product listing or product view","properties":{"url":{"type":"string","description":"Image url"},"code":{"type":"string","description":"Image code"},"height":{"type":"number","description":"Image height"},"width":{"type":"number","description":"Image width in px"},"label":{"type":"string","description":"Image label"},"resized_width":{"type":"number","description":"Resize width"},"resized_height":{"type":"number","description":"Resize height"},"extension_attributes":{"$ref":"#/definitions/catalog-data-product-render-image-extension-interface"}},"required":["url","code","height","width","label","resized_width","resized_height"]},"catalog-data-product-render-image-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductRender\\ImageInterface"},"catalog-data-product-render-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductRenderInterface","properties":{"wishlist_button":{"$ref":"#/definitions/catalog-data-product-render-button-interface"},"review_html":{"type":"string"}}},"catalog-inventory-data-stock-status-collection-interface":{"type":"object","description":"Stock Status collection interface","properties":{"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/catalog-inventory-data-stock-status-interface"}},"search_criteria":{"$ref":"#/definitions/catalog-inventory-stock-status-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"catalog-inventory-data-stock-status-interface":{"type":"object","description":"Interface StockStatusInterface","properties":{"product_id":{"type":"integer"},"stock_id":{"type":"integer"},"qty":{"type":"integer"},"stock_status":{"type":"integer"},"stock_item":{"$ref":"#/definitions/catalog-inventory-data-stock-item-interface"},"extension_attributes":{"$ref":"#/definitions/catalog-inventory-data-stock-status-extension-interface"}},"required":["product_id","stock_id","qty","stock_status","stock_item"]},"catalog-inventory-data-stock-status-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\CatalogInventory\\Api\\Data\\StockStatusInterface"},"catalog-inventory-stock-status-criteria-interface":{"type":"object","description":"Interface StockStatusCriteriaInterface","properties":{"mapper_interface_name":{"type":"string","description":"Associated Mapper Interface name"},"criteria_list":{"type":"array","description":"Criteria objects added to current Composite Criteria","items":{"$ref":"#/definitions/framework-criteria-interface"}},"filters":{"type":"array","description":"List of filters","items":{"type":"string"}},"orders":{"type":"array","description":"Ordering criteria","items":{"type":"string"}},"limit":{"type":"array","description":"Limit","items":{"type":"string"}}},"required":["mapper_interface_name","criteria_list","filters","orders","limit"]},"framework-criteria-interface":{"type":"object","description":"Interface CriteriaInterface","properties":{"mapper_interface_name":{"type":"string","description":"Associated Mapper Interface name"},"criteria_list":{"type":"array","description":"Criteria objects added to current Composite Criteria","items":{"$ref":"#/definitions/framework-criteria-interface"}},"filters":{"type":"array","description":"List of filters","items":{"type":"string"}},"orders":{"type":"array","description":"Ordering criteria","items":{"type":"string"}},"limit":{"type":"array","description":"Limit","items":{"type":"string"}}},"required":["mapper_interface_name","criteria_list","filters","orders","limit"]},"bundle-data-option-type-interface":{"type":"object","description":"Interface OptionTypeInterface","properties":{"label":{"type":"string","description":"Type label"},"code":{"type":"string","description":"Type code"},"extension_attributes":{"$ref":"#/definitions/bundle-data-option-type-extension-interface"}},"required":["label","code"]},"bundle-data-option-type-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Bundle\\Api\\Data\\OptionTypeInterface"},"quote-data-cart-interface":{"type":"object","description":"Interface CartInterface","properties":{"id":{"type":"integer","description":"Cart/quote ID."},"created_at":{"type":"string","description":"Cart creation date and time. Otherwise, null."},"updated_at":{"type":"string","description":"Cart last update date and time. Otherwise, null."},"converted_at":{"type":"string","description":"Cart conversion date and time. Otherwise, null."},"is_active":{"type":"boolean","description":"Active status flag value. Otherwise, null."},"is_virtual":{"type":"boolean","description":"Virtual flag value. Otherwise, null."},"items":{"type":"array","description":"Array of items. Otherwise, null.","items":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"items_count":{"type":"integer","description":"Number of different items or products in the cart. Otherwise, null."},"items_qty":{"type":"number","description":"Total quantity of all cart items. Otherwise, null."},"customer":{"$ref":"#/definitions/customer-data-customer-interface"},"billing_address":{"$ref":"#/definitions/quote-data-address-interface"},"reserved_order_id":{"type":"integer","description":"Reserved order ID. Otherwise, null."},"orig_order_id":{"type":"integer","description":"Original order ID. Otherwise, null."},"currency":{"$ref":"#/definitions/quote-data-currency-interface"},"customer_is_guest":{"type":"boolean","description":"For guest customers, false for logged in customers"},"customer_note":{"type":"string","description":"Notice text"},"customer_note_notify":{"type":"boolean","description":"Customer notification flag"},"customer_tax_class_id":{"type":"integer","description":"Customer tax class ID."},"store_id":{"type":"integer","description":"Store identifier"},"extension_attributes":{"$ref":"#/definitions/quote-data-cart-extension-interface"}},"required":["id","customer","store_id"]},"quote-data-cart-item-interface":{"type":"object","description":"Interface CartItemInterface","properties":{"item_id":{"type":"integer","description":"Item ID. Otherwise, null."},"sku":{"type":"string","description":"Product SKU. Otherwise, null."},"qty":{"type":"number","description":"Product quantity."},"name":{"type":"string","description":"Product name. Otherwise, null."},"price":{"type":"number","description":"Product price. Otherwise, null."},"product_type":{"type":"string","description":"Product type. Otherwise, null."},"quote_id":{"type":"string","description":"Quote id."},"product_option":{"$ref":"#/definitions/quote-data-product-option-interface"},"extension_attributes":{"$ref":"#/definitions/quote-data-cart-item-extension-interface"}},"required":["qty","quote_id"]},"quote-data-product-option-interface":{"type":"object","description":"Product option interface","properties":{"extension_attributes":{"$ref":"#/definitions/quote-data-product-option-extension-interface"}}},"quote-data-product-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\ProductOptionInterface","properties":{"custom_options":{"type":"array","items":{"$ref":"#/definitions/catalog-data-custom-option-interface"}},"bundle_options":{"type":"array","items":{"$ref":"#/definitions/bundle-data-bundle-option-interface"}},"downloadable_option":{"$ref":"#/definitions/downloadable-data-downloadable-option-interface"},"giftcard_item_option":{"$ref":"#/definitions/gift-card-data-gift-card-option-interface"},"configurable_item_options":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-configurable-item-option-value-interface"}}}},"catalog-data-custom-option-interface":{"type":"object","description":"Interface CustomOptionInterface","properties":{"option_id":{"type":"string","description":"Option id"},"option_value":{"type":"string","description":"Option value"},"extension_attributes":{"$ref":"#/definitions/catalog-data-custom-option-extension-interface"}},"required":["option_id","option_value"]},"catalog-data-custom-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\CustomOptionInterface","properties":{"file_info":{"$ref":"#/definitions/framework-data-image-content-interface"}}},"bundle-data-bundle-option-interface":{"type":"object","description":"Interface BundleOptionInterface","properties":{"option_id":{"type":"integer","description":"Bundle option id."},"option_qty":{"type":"integer","description":"Bundle option quantity."},"option_selections":{"type":"array","description":"Bundle option selection ids.","items":{"type":"integer"}},"extension_attributes":{"$ref":"#/definitions/bundle-data-bundle-option-extension-interface"}},"required":["option_id","option_qty","option_selections"]},"bundle-data-bundle-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Bundle\\Api\\Data\\BundleOptionInterface"},"downloadable-data-downloadable-option-interface":{"type":"object","description":"Downloadable Option","properties":{"downloadable_links":{"type":"array","description":"The list of downloadable links","items":{"type":"integer"}}},"required":["downloadable_links"]},"gift-card-data-gift-card-option-interface":{"type":"object","description":"Interface GiftCardOptionInterface","properties":{"giftcard_amount":{"type":"string","description":"Gift card amount."},"custom_giftcard_amount":{"type":"number","description":"Gift card open amount value."},"giftcard_sender_name":{"type":"string","description":"Gift card sender name."},"giftcard_recipient_name":{"type":"string","description":"Gift card recipient name."},"giftcard_sender_email":{"type":"string","description":"Gift card sender email."},"giftcard_recipient_email":{"type":"string","description":"Gift card recipient email."},"giftcard_message":{"type":"string","description":"Giftcard message."},"extension_attributes":{"$ref":"#/definitions/gift-card-data-gift-card-option-extension-interface"}},"required":["giftcard_amount","giftcard_sender_name","giftcard_recipient_name","giftcard_sender_email","giftcard_recipient_email"]},"gift-card-data-gift-card-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\GiftCard\\Api\\Data\\GiftCardOptionInterface"},"configurable-product-data-configurable-item-option-value-interface":{"type":"object","description":"Interface ConfigurableItemOptionValueInterface","properties":{"option_id":{"type":"string","description":"Option SKU"},"option_value":{"type":"integer","description":"Item id"},"extension_attributes":{"$ref":"#/definitions/configurable-product-data-configurable-item-option-value-extension-interface"}},"required":["option_id"]},"configurable-product-data-configurable-item-option-value-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\ConfigurableProduct\\Api\\Data\\ConfigurableItemOptionValueInterface"},"quote-data-cart-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\CartItemInterface"},"quote-data-address-interface":{"type":"object","description":"Interface AddressInterface","properties":{"id":{"type":"integer","description":"Id"},"region":{"type":"string","description":"Region name"},"region_id":{"type":"integer","description":"Region id"},"region_code":{"type":"string","description":"Region code"},"country_id":{"type":"string","description":"Country id"},"street":{"type":"array","description":"Street","items":{"type":"string"}},"company":{"type":"string","description":"Company"},"telephone":{"type":"string","description":"Telephone number"},"fax":{"type":"string","description":"Fax number"},"postcode":{"type":"string","description":"Postcode"},"city":{"type":"string","description":"City name"},"firstname":{"type":"string","description":"First name"},"lastname":{"type":"string","description":"Last name"},"middlename":{"type":"string","description":"Middle name"},"prefix":{"type":"string","description":"Prefix"},"suffix":{"type":"string","description":"Suffix"},"vat_id":{"type":"string","description":"Vat id"},"customer_id":{"type":"integer","description":"Customer id"},"email":{"type":"string","description":"Billing/shipping email"},"same_as_billing":{"type":"integer","description":"Same as billing flag"},"customer_address_id":{"type":"integer","description":"Customer address id"},"save_in_address_book":{"type":"integer","description":"Save in address book flag"},"extension_attributes":{"$ref":"#/definitions/quote-data-address-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["region","region_id","region_code","country_id","street","telephone","postcode","city","firstname","lastname","email"]},"quote-data-address-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\AddressInterface","properties":{"gift_registry_id":{"type":"integer"}}},"quote-data-currency-interface":{"type":"object","description":"Interface CurrencyInterface","properties":{"global_currency_code":{"type":"string","description":"Global currency code"},"base_currency_code":{"type":"string","description":"Base currency code"},"store_currency_code":{"type":"string","description":"Store currency code"},"quote_currency_code":{"type":"string","description":"Quote currency code"},"store_to_base_rate":{"type":"number","description":"Store currency to base currency rate"},"store_to_quote_rate":{"type":"number","description":"Store currency to quote currency rate"},"base_to_global_rate":{"type":"number","description":"Base currency to global currency rate"},"base_to_quote_rate":{"type":"number","description":"Base currency to quote currency rate"},"extension_attributes":{"$ref":"#/definitions/quote-data-currency-extension-interface"}}},"quote-data-currency-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\CurrencyInterface"},"quote-data-cart-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\CartInterface","properties":{"shipping_assignments":{"type":"array","items":{"$ref":"#/definitions/quote-data-shipping-assignment-interface"}},"quote_api_test_attribute":{"$ref":"#/definitions/user-data-user-interface"}}},"quote-data-shipping-assignment-interface":{"type":"object","description":"Interface ShippingAssignmentInterface","properties":{"shipping":{"$ref":"#/definitions/quote-data-shipping-interface"},"items":{"type":"array","items":{"$ref":"#/definitions/quote-data-cart-item-interface"}},"extension_attributes":{"$ref":"#/definitions/quote-data-shipping-assignment-extension-interface"}},"required":["shipping","items"]},"quote-data-shipping-interface":{"type":"object","description":"Interface ShippingInterface","properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"},"method":{"type":"string","description":"Shipping method"},"extension_attributes":{"$ref":"#/definitions/quote-data-shipping-extension-interface"}},"required":["address","method"]},"quote-data-shipping-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\ShippingInterface"},"quote-data-shipping-assignment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\ShippingAssignmentInterface"},"user-data-user-interface":{"type":"object","description":"Admin user interface.","properties":{"id":{"type":"integer","description":"ID."},"first_name":{"type":"string","description":"First name."},"last_name":{"type":"string","description":"Last name."},"email":{"type":"string","description":"Email."},"user_name":{"type":"string","description":"User name."},"password":{"type":"string","description":"Password or password hash."},"created":{"type":"string","description":"User record creation date."},"modified":{"type":"string","description":"User record modification date."},"is_active":{"type":"integer","description":"If user is active."},"interface_locale":{"type":"string","description":"User interface locale."}},"required":["id","first_name","last_name","email","user_name","password","created","modified","is_active","interface_locale"]},"quote-data-cart-search-results-interface":{"type":"object","description":"Interface CartSearchResultsInterface","properties":{"items":{"type":"array","description":"Carts list.","items":{"$ref":"#/definitions/quote-data-cart-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"quote-data-payment-interface":{"type":"object","description":"Interface PaymentInterface","properties":{"po_number":{"type":"string","description":"Purchase order number"},"method":{"type":"string","description":"Payment method code"},"additional_data":{"type":"array","description":"Payment additional details","items":{"type":"string"}},"extension_attributes":{"$ref":"#/definitions/quote-data-payment-extension-interface"}},"required":["method"]},"quote-data-payment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\PaymentInterface","properties":{"agreement_ids":{"type":"array","items":{"type":"string"}}}},"quote-data-shipping-method-interface":{"type":"object","description":"Interface ShippingMethodInterface","properties":{"carrier_code":{"type":"string","description":"Shipping carrier code."},"method_code":{"type":"string","description":"Shipping method code."},"carrier_title":{"type":"string","description":"Shipping carrier title. Otherwise, null."},"method_title":{"type":"string","description":"Shipping method title. Otherwise, null."},"amount":{"type":"number","description":"Shipping amount in store currency."},"base_amount":{"type":"number","description":"Shipping amount in base currency."},"available":{"type":"boolean","description":"The value of the availability flag for the current shipping method."},"extension_attributes":{"$ref":"#/definitions/quote-data-shipping-method-extension-interface"},"error_message":{"type":"string","description":"Shipping Error message."},"price_excl_tax":{"type":"number","description":"Shipping price excl tax."},"price_incl_tax":{"type":"number","description":"Shipping price incl tax."}},"required":["carrier_code","method_code","amount","base_amount","available","error_message","price_excl_tax","price_incl_tax"]},"quote-data-shipping-method-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\ShippingMethodInterface"},"quote-data-payment-method-interface":{"type":"object","description":"Interface PaymentMethodInterface","properties":{"code":{"type":"string","description":"Payment method code"},"title":{"type":"string","description":"Payment method title"}},"required":["code","title"]},"quote-data-totals-interface":{"type":"object","description":"Interface TotalsInterface","properties":{"grand_total":{"type":"number","description":"Grand total in quote currency"},"base_grand_total":{"type":"number","description":"Grand total in base currency"},"subtotal":{"type":"number","description":"Subtotal in quote currency"},"base_subtotal":{"type":"number","description":"Subtotal in base currency"},"discount_amount":{"type":"number","description":"Discount amount in quote currency"},"base_discount_amount":{"type":"number","description":"Discount amount in base currency"},"subtotal_with_discount":{"type":"number","description":"Subtotal in quote currency with applied discount"},"base_subtotal_with_discount":{"type":"number","description":"Subtotal in base currency with applied discount"},"shipping_amount":{"type":"number","description":"Shipping amount in quote currency"},"base_shipping_amount":{"type":"number","description":"Shipping amount in base currency"},"shipping_discount_amount":{"type":"number","description":"Shipping discount amount in quote currency"},"base_shipping_discount_amount":{"type":"number","description":"Shipping discount amount in base currency"},"tax_amount":{"type":"number","description":"Tax amount in quote currency"},"base_tax_amount":{"type":"number","description":"Tax amount in base currency"},"weee_tax_applied_amount":{"type":"number","description":"Item weee tax applied amount in quote currency."},"shipping_tax_amount":{"type":"number","description":"Shipping tax amount in quote currency"},"base_shipping_tax_amount":{"type":"number","description":"Shipping tax amount in base currency"},"subtotal_incl_tax":{"type":"number","description":"Subtotal including tax in quote currency"},"base_subtotal_incl_tax":{"type":"number","description":"Subtotal including tax in base currency"},"shipping_incl_tax":{"type":"number","description":"Shipping including tax in quote currency"},"base_shipping_incl_tax":{"type":"number","description":"Shipping including tax in base currency"},"base_currency_code":{"type":"string","description":"Base currency code"},"quote_currency_code":{"type":"string","description":"Quote currency code"},"coupon_code":{"type":"string","description":"Applied coupon code"},"items_qty":{"type":"integer","description":"Items qty"},"items":{"type":"array","description":"Totals by items","items":{"$ref":"#/definitions/quote-data-totals-item-interface"}},"total_segments":{"type":"array","description":"Dynamically calculated totals","items":{"$ref":"#/definitions/quote-data-total-segment-interface"}},"extension_attributes":{"$ref":"#/definitions/quote-data-totals-extension-interface"}},"required":["weee_tax_applied_amount","total_segments"]},"quote-data-totals-item-interface":{"type":"object","description":"Interface TotalsItemInterface","properties":{"item_id":{"type":"integer","description":"Item id"},"price":{"type":"number","description":"Item price in quote currency."},"base_price":{"type":"number","description":"Item price in base currency."},"qty":{"type":"number","description":"Item quantity."},"row_total":{"type":"number","description":"Row total in quote currency."},"base_row_total":{"type":"number","description":"Row total in base currency."},"row_total_with_discount":{"type":"number","description":"Row total with discount in quote currency. Otherwise, null."},"tax_amount":{"type":"number","description":"Tax amount in quote currency. Otherwise, null."},"base_tax_amount":{"type":"number","description":"Tax amount in base currency. Otherwise, null."},"tax_percent":{"type":"number","description":"Tax percent. Otherwise, null."},"discount_amount":{"type":"number","description":"Discount amount in quote currency. Otherwise, null."},"base_discount_amount":{"type":"number","description":"Discount amount in base currency. Otherwise, null."},"discount_percent":{"type":"number","description":"Discount percent. Otherwise, null."},"price_incl_tax":{"type":"number","description":"Price including tax in quote currency. Otherwise, null."},"base_price_incl_tax":{"type":"number","description":"Price including tax in base currency. Otherwise, null."},"row_total_incl_tax":{"type":"number","description":"Row total including tax in quote currency. Otherwise, null."},"base_row_total_incl_tax":{"type":"number","description":"Row total including tax in base currency. Otherwise, null."},"options":{"type":"string","description":"Item price in quote currency."},"weee_tax_applied_amount":{"type":"number","description":"Item weee tax applied amount in quote currency."},"weee_tax_applied":{"type":"string","description":"Item weee tax applied in quote currency."},"extension_attributes":{"$ref":"#/definitions/quote-data-totals-item-extension-interface"},"name":{"type":"string","description":"Product name. Otherwise, null."}},"required":["item_id","price","base_price","qty","row_total","base_row_total","options","weee_tax_applied_amount","weee_tax_applied"]},"quote-data-totals-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\TotalsItemInterface"},"quote-data-total-segment-interface":{"type":"object","description":"Interface TotalsInterface","properties":{"code":{"type":"string","description":"Code"},"title":{"type":"string","description":"Total title"},"value":{"type":"number","description":"Total value"},"area":{"type":"string","description":"Display area code."},"extension_attributes":{"$ref":"#/definitions/quote-data-total-segment-extension-interface"}},"required":["code","value"]},"quote-data-total-segment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\TotalSegmentInterface","properties":{"gift_cards":{"type":"string"},"tax_grandtotal_details":{"type":"array","items":{"$ref":"#/definitions/tax-data-grand-total-details-interface"}},"gw_order_id":{"type":"string"},"gw_item_ids":{"type":"array","items":{"type":"string"}},"gw_allow_gift_receipt":{"type":"string"},"gw_add_card":{"type":"string"},"gw_price":{"type":"string"},"gw_base_price":{"type":"string"},"gw_items_price":{"type":"string"},"gw_items_base_price":{"type":"string"},"gw_card_price":{"type":"string"},"gw_card_base_price":{"type":"string"},"gw_base_tax_amount":{"type":"string"},"gw_tax_amount":{"type":"string"},"gw_items_base_tax_amount":{"type":"string"},"gw_items_tax_amount":{"type":"string"},"gw_card_base_tax_amount":{"type":"string"},"gw_card_tax_amount":{"type":"string"},"gw_price_incl_tax":{"type":"string"},"gw_base_price_incl_tax":{"type":"string"},"gw_card_price_incl_tax":{"type":"string"},"gw_card_base_price_incl_tax":{"type":"string"},"gw_items_price_incl_tax":{"type":"string"},"gw_items_base_price_incl_tax":{"type":"string"}}},"tax-data-grand-total-details-interface":{"type":"object","description":"Interface GrandTotalDetailsInterface","properties":{"amount":{"type":"number","description":"Tax amount value"},"rates":{"type":"array","description":"Tax rates info","items":{"$ref":"#/definitions/tax-data-grand-total-rates-interface"}},"group_id":{"type":"integer","description":"Group identifier"}},"required":["amount","rates","group_id"]},"tax-data-grand-total-rates-interface":{"type":"object","description":"Interface GrandTotalRatesInterface","properties":{"percent":{"type":"string","description":"Tax percentage value"},"title":{"type":"string","description":"Rate title"}},"required":["percent","title"]},"quote-data-totals-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\TotalsInterface","properties":{"coupon_label":{"type":"string"},"base_customer_balance_amount":{"type":"number"},"customer_balance_amount":{"type":"number"},"reward_points_balance":{"type":"number"},"reward_currency_amount":{"type":"number"},"base_reward_currency_amount":{"type":"number"}}},"quote-data-totals-additional-data-interface":{"type":"object","description":"Additional data for totals collection.","properties":{"extension_attributes":{"$ref":"#/definitions/quote-data-totals-additional-data-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}}},"quote-data-totals-additional-data-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Quote\\Api\\Data\\TotalsAdditionalDataInterface","properties":{"gift_messages":{"type":"array","items":{"$ref":"#/definitions/gift-message-data-message-interface"}}}},"gift-message-data-message-interface":{"type":"object","description":"Interface MessageInterface","properties":{"gift_message_id":{"type":"integer","description":"Gift message ID. Otherwise, null."},"customer_id":{"type":"integer","description":"Customer ID. Otherwise, null."},"sender":{"type":"string","description":"Sender name."},"recipient":{"type":"string","description":"Recipient name."},"message":{"type":"string","description":"Message text."},"extension_attributes":{"$ref":"#/definitions/gift-message-data-message-extension-interface"}},"required":["sender","recipient","message"]},"gift-message-data-message-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\GiftMessage\\Api\\Data\\MessageInterface","properties":{"entity_id":{"type":"string"},"entity_type":{"type":"string"},"wrapping_id":{"type":"integer"},"wrapping_allow_gift_receipt":{"type":"boolean"},"wrapping_add_printed_card":{"type":"boolean"}}},"framework-search-search-result-interface":{"type":"object","description":"Interface SearchResultInterface","properties":{"items":{"type":"array","items":{"$ref":"#/definitions/framework-search-document-interface"}},"aggregations":{"$ref":"#/definitions/framework-search-aggregation-interface"},"search_criteria":{"$ref":"#/definitions/framework-search-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","aggregations","search_criteria","total_count"]},"framework-search-document-interface":{"type":"object","description":"Interface \\Magento\\Framework\\Api\\Search\\DocumentInterface","properties":{"id":{"type":"integer"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["id"]},"framework-search-aggregation-interface":{"type":"object","description":"Faceted data","properties":{"buckets":{"type":"array","description":"All Document fields","items":{"$ref":"#/definitions/framework-search-bucket-interface"}},"bucket_names":{"type":"array","description":"Document field names","items":{"type":"string"}}},"required":["buckets","bucket_names"]},"framework-search-bucket-interface":{"type":"object","description":"Facet Bucket","properties":{"name":{"type":"string","description":"Field name"},"values":{"type":"array","description":"Field values","items":{"$ref":"#/definitions/framework-search-aggregation-value-interface"}}},"required":["name","values"]},"framework-search-aggregation-value-interface":{"type":"object","description":"Interface \\Magento\\Framework\\Api\\Search\\AggregationValueInterface","properties":{"value":{"type":"string","description":"Aggregation"},"metrics":{"type":"array","description":"Metrics","items":{"type":"string"}}},"required":["value","metrics"]},"framework-search-search-criteria-interface":{"type":"object","description":"Interface SearchCriteriaInterface","properties":{"request_name":{"type":"string"},"filter_groups":{"type":"array","description":"A list of filter groups.","items":{"$ref":"#/definitions/framework-search-filter-group"}},"sort_orders":{"type":"array","description":"Sort order.","items":{"$ref":"#/definitions/framework-sort-order"}},"page_size":{"type":"integer","description":"Page size."},"current_page":{"type":"integer","description":"Current page."}},"required":["request_name","filter_groups"]},"sales-data-order-interface":{"type":"object","description":"Order interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"adjustment_negative":{"type":"number","description":"Negative adjustment value."},"adjustment_positive":{"type":"number","description":"Positive adjustment value."},"applied_rule_ids":{"type":"string","description":"Applied rule IDs."},"base_adjustment_negative":{"type":"number","description":"Base negative adjustment value."},"base_adjustment_positive":{"type":"number","description":"Base positive adjustment value."},"base_currency_code":{"type":"string","description":"Base currency code."},"base_discount_amount":{"type":"number","description":"Base discount amount."},"base_discount_canceled":{"type":"number","description":"Base discount canceled."},"base_discount_invoiced":{"type":"number","description":"Base discount invoiced."},"base_discount_refunded":{"type":"number","description":"Base discount refunded."},"base_grand_total":{"type":"number","description":"Base grand total."},"base_discount_tax_compensation_amount":{"type":"number","description":"Base discount tax compensation amount."},"base_discount_tax_compensation_invoiced":{"type":"number","description":"Base discount tax compensation invoiced."},"base_discount_tax_compensation_refunded":{"type":"number","description":"Base discount tax compensation refunded."},"base_shipping_amount":{"type":"number","description":"Base shipping amount."},"base_shipping_canceled":{"type":"number","description":"Base shipping canceled."},"base_shipping_discount_amount":{"type":"number","description":"Base shipping discount amount."},"base_shipping_discount_tax_compensation_amnt":{"type":"number","description":"Base shipping discount tax compensation amount."},"base_shipping_incl_tax":{"type":"number","description":"Base shipping including tax."},"base_shipping_invoiced":{"type":"number","description":"Base shipping invoiced."},"base_shipping_refunded":{"type":"number","description":"Base shipping refunded."},"base_shipping_tax_amount":{"type":"number","description":"Base shipping tax amount."},"base_shipping_tax_refunded":{"type":"number","description":"Base shipping tax refunded."},"base_subtotal":{"type":"number","description":"Base subtotal."},"base_subtotal_canceled":{"type":"number","description":"Base subtotal canceled."},"base_subtotal_incl_tax":{"type":"number","description":"Base subtotal including tax."},"base_subtotal_invoiced":{"type":"number","description":"Base subtotal invoiced."},"base_subtotal_refunded":{"type":"number","description":"Base subtotal refunded."},"base_tax_amount":{"type":"number","description":"Base tax amount."},"base_tax_canceled":{"type":"number","description":"Base tax canceled."},"base_tax_invoiced":{"type":"number","description":"Base tax invoiced."},"base_tax_refunded":{"type":"number","description":"Base tax refunded."},"base_total_canceled":{"type":"number","description":"Base total canceled."},"base_total_due":{"type":"number","description":"Base total due."},"base_total_invoiced":{"type":"number","description":"Base total invoiced."},"base_total_invoiced_cost":{"type":"number","description":"Base total invoiced cost."},"base_total_offline_refunded":{"type":"number","description":"Base total offline refunded."},"base_total_online_refunded":{"type":"number","description":"Base total online refunded."},"base_total_paid":{"type":"number","description":"Base total paid."},"base_total_qty_ordered":{"type":"number","description":"Base total quantity ordered."},"base_total_refunded":{"type":"number","description":"Base total refunded."},"base_to_global_rate":{"type":"number","description":"Base-to-global rate."},"base_to_order_rate":{"type":"number","description":"Base-to-order rate."},"billing_address_id":{"type":"integer","description":"Billing address ID."},"can_ship_partially":{"type":"integer","description":"Can-ship-partially flag value."},"can_ship_partially_item":{"type":"integer","description":"Can-ship-partially-item flag value."},"coupon_code":{"type":"string","description":"Coupon code."},"created_at":{"type":"string","description":"Created-at timestamp."},"customer_dob":{"type":"string","description":"Customer date-of-birth (DOB)."},"customer_email":{"type":"string","description":"Customer email address."},"customer_firstname":{"type":"string","description":"Customer first name."},"customer_gender":{"type":"integer","description":"Customer gender."},"customer_group_id":{"type":"integer","description":"Customer group ID."},"customer_id":{"type":"integer","description":"Customer ID."},"customer_is_guest":{"type":"integer","description":"Customer-is-guest flag value."},"customer_lastname":{"type":"string","description":"Customer last name."},"customer_middlename":{"type":"string","description":"Customer middle name."},"customer_note":{"type":"string","description":"Customer note."},"customer_note_notify":{"type":"integer","description":"Customer-note-notify flag value."},"customer_prefix":{"type":"string","description":"Customer prefix."},"customer_suffix":{"type":"string","description":"Customer suffix."},"customer_taxvat":{"type":"string","description":"Customer value-added tax (VAT)."},"discount_amount":{"type":"number","description":"Discount amount."},"discount_canceled":{"type":"number","description":"Discount canceled."},"discount_description":{"type":"string","description":"Discount description."},"discount_invoiced":{"type":"number","description":"Discount invoiced."},"discount_refunded":{"type":"number","description":"Discount refunded amount."},"edit_increment":{"type":"integer","description":"Edit increment value."},"email_sent":{"type":"integer","description":"Email-sent flag value."},"entity_id":{"type":"integer","description":"Order ID."},"ext_customer_id":{"type":"string","description":"External customer ID."},"ext_order_id":{"type":"string","description":"External order ID."},"forced_shipment_with_invoice":{"type":"integer","description":"Forced-shipment-with-invoice flag value."},"global_currency_code":{"type":"string","description":"Global currency code."},"grand_total":{"type":"number","description":"Grand total."},"discount_tax_compensation_amount":{"type":"number","description":"Discount tax compensation amount."},"discount_tax_compensation_invoiced":{"type":"number","description":"Discount tax compensation invoiced amount."},"discount_tax_compensation_refunded":{"type":"number","description":"Discount tax compensation refunded amount."},"hold_before_state":{"type":"string","description":"Hold before state."},"hold_before_status":{"type":"string","description":"Hold before status."},"increment_id":{"type":"string","description":"Increment ID."},"is_virtual":{"type":"integer","description":"Is-virtual flag value."},"order_currency_code":{"type":"string","description":"Order currency code."},"original_increment_id":{"type":"string","description":"Original increment ID."},"payment_authorization_amount":{"type":"number","description":"Payment authorization amount."},"payment_auth_expiration":{"type":"integer","description":"Payment authorization expiration date."},"protect_code":{"type":"string","description":"Protect code."},"quote_address_id":{"type":"integer","description":"Quote address ID."},"quote_id":{"type":"integer","description":"Quote ID."},"relation_child_id":{"type":"string","description":"Relation child ID."},"relation_child_real_id":{"type":"string","description":"Relation child real ID."},"relation_parent_id":{"type":"string","description":"Relation parent ID."},"relation_parent_real_id":{"type":"string","description":"Relation parent real ID."},"remote_ip":{"type":"string","description":"Remote IP address."},"shipping_amount":{"type":"number","description":"Shipping amount."},"shipping_canceled":{"type":"number","description":"Shipping canceled amount."},"shipping_description":{"type":"string","description":"Shipping description."},"shipping_discount_amount":{"type":"number","description":"Shipping discount amount."},"shipping_discount_tax_compensation_amount":{"type":"number","description":"Shipping discount tax compensation amount."},"shipping_incl_tax":{"type":"number","description":"Shipping including tax amount."},"shipping_invoiced":{"type":"number","description":"Shipping invoiced amount."},"shipping_refunded":{"type":"number","description":"Shipping refunded amount."},"shipping_tax_amount":{"type":"number","description":"Shipping tax amount."},"shipping_tax_refunded":{"type":"number","description":"Shipping tax refunded amount."},"state":{"type":"string","description":"State."},"status":{"type":"string","description":"Status."},"store_currency_code":{"type":"string","description":"Store currency code."},"store_id":{"type":"integer","description":"Store ID."},"store_name":{"type":"string","description":"Store name."},"store_to_base_rate":{"type":"number","description":"Store-to-base rate."},"store_to_order_rate":{"type":"number","description":"Store-to-order rate."},"subtotal":{"type":"number","description":"Subtotal."},"subtotal_canceled":{"type":"number","description":"Subtotal canceled amount."},"subtotal_incl_tax":{"type":"number","description":"Subtotal including tax amount."},"subtotal_invoiced":{"type":"number","description":"Subtotal invoiced amount."},"subtotal_refunded":{"type":"number","description":"Subtotal refunded amount."},"tax_amount":{"type":"number","description":"Tax amount."},"tax_canceled":{"type":"number","description":"Tax canceled amount."},"tax_invoiced":{"type":"number","description":"Tax invoiced amount."},"tax_refunded":{"type":"number","description":"Tax refunded amount."},"total_canceled":{"type":"number","description":"Total canceled."},"total_due":{"type":"number","description":"Total due."},"total_invoiced":{"type":"number","description":"Total invoiced amount."},"total_item_count":{"type":"integer","description":"Total item count."},"total_offline_refunded":{"type":"number","description":"Total offline refunded amount."},"total_online_refunded":{"type":"number","description":"Total online refunded amount."},"total_paid":{"type":"number","description":"Total paid."},"total_qty_ordered":{"type":"number","description":"Total quantity ordered."},"total_refunded":{"type":"number","description":"Total amount refunded."},"updated_at":{"type":"string","description":"Updated-at timestamp."},"weight":{"type":"number","description":"Weight."},"x_forwarded_for":{"type":"string","description":"X-Forwarded-For field value."},"items":{"type":"array","description":"Array of items.","items":{"$ref":"#/definitions/sales-data-order-item-interface"}},"billing_address":{"$ref":"#/definitions/sales-data-order-address-interface"},"payment":{"$ref":"#/definitions/sales-data-order-payment-interface"},"status_histories":{"type":"array","description":"Array of status histories.","items":{"$ref":"#/definitions/sales-data-order-status-history-interface"}},"extension_attributes":{"$ref":"#/definitions/sales-data-order-extension-interface"}},"required":["base_grand_total","customer_email","grand_total","items"]},"sales-data-order-item-interface":{"type":"object","description":"Order item interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"additional_data":{"type":"string","description":"Additional data."},"amount_refunded":{"type":"number","description":"Amount refunded."},"applied_rule_ids":{"type":"string","description":"Applied rule IDs."},"base_amount_refunded":{"type":"number","description":"Base amount refunded."},"base_cost":{"type":"number","description":"Base cost."},"base_discount_amount":{"type":"number","description":"Base discount amount."},"base_discount_invoiced":{"type":"number","description":"Base discount invoiced."},"base_discount_refunded":{"type":"number","description":"Base discount refunded."},"base_discount_tax_compensation_amount":{"type":"number","description":"Base discount tax compensation amount."},"base_discount_tax_compensation_invoiced":{"type":"number","description":"Base discount tax compensation invoiced."},"base_discount_tax_compensation_refunded":{"type":"number","description":"Base discount tax compensation refunded."},"base_original_price":{"type":"number","description":"Base original price."},"base_price":{"type":"number","description":"Base price."},"base_price_incl_tax":{"type":"number","description":"Base price including tax."},"base_row_invoiced":{"type":"number","description":"Base row invoiced."},"base_row_total":{"type":"number","description":"Base row total."},"base_row_total_incl_tax":{"type":"number","description":"Base row total including tax."},"base_tax_amount":{"type":"number","description":"Base tax amount."},"base_tax_before_discount":{"type":"number","description":"Base tax before discount."},"base_tax_invoiced":{"type":"number","description":"Base tax invoiced."},"base_tax_refunded":{"type":"number","description":"Base tax refunded."},"base_weee_tax_applied_amount":{"type":"number","description":"Base WEEE tax applied amount."},"base_weee_tax_applied_row_amnt":{"type":"number","description":"Base WEEE tax applied row amount."},"base_weee_tax_disposition":{"type":"number","description":"Base WEEE tax disposition."},"base_weee_tax_row_disposition":{"type":"number","description":"Base WEEE tax row disposition."},"created_at":{"type":"string","description":"Created-at timestamp."},"description":{"type":"string","description":"Description."},"discount_amount":{"type":"number","description":"Discount amount."},"discount_invoiced":{"type":"number","description":"Discount invoiced."},"discount_percent":{"type":"number","description":"Discount percent."},"discount_refunded":{"type":"number","description":"Discount refunded."},"event_id":{"type":"integer","description":"Event ID."},"ext_order_item_id":{"type":"string","description":"External order item ID."},"free_shipping":{"type":"integer","description":"Free-shipping flag value."},"gw_base_price":{"type":"number","description":"GW base price."},"gw_base_price_invoiced":{"type":"number","description":"GW base price invoiced."},"gw_base_price_refunded":{"type":"number","description":"GW base price refunded."},"gw_base_tax_amount":{"type":"number","description":"GW base tax amount."},"gw_base_tax_amount_invoiced":{"type":"number","description":"GW base tax amount invoiced."},"gw_base_tax_amount_refunded":{"type":"number","description":"GW base tax amount refunded."},"gw_id":{"type":"integer","description":"GW ID."},"gw_price":{"type":"number","description":"GW price."},"gw_price_invoiced":{"type":"number","description":"GW price invoiced."},"gw_price_refunded":{"type":"number","description":"GW price refunded."},"gw_tax_amount":{"type":"number","description":"GW tax amount."},"gw_tax_amount_invoiced":{"type":"number","description":"GW tax amount invoiced."},"gw_tax_amount_refunded":{"type":"number","description":"GW tax amount refunded."},"discount_tax_compensation_amount":{"type":"number","description":"Discount tax compensation amount."},"discount_tax_compensation_canceled":{"type":"number","description":"Discount tax compensation canceled."},"discount_tax_compensation_invoiced":{"type":"number","description":"Discount tax compensation invoiced."},"discount_tax_compensation_refunded":{"type":"number","description":"Discount tax compensation refunded."},"is_qty_decimal":{"type":"integer","description":"Is-quantity-decimal flag value."},"is_virtual":{"type":"integer","description":"Is-virtual flag value."},"item_id":{"type":"integer","description":"Item ID."},"locked_do_invoice":{"type":"integer","description":"Locked DO invoice flag value."},"locked_do_ship":{"type":"integer","description":"Locked DO ship flag value."},"name":{"type":"string","description":"Name."},"no_discount":{"type":"integer","description":"No-discount flag value."},"order_id":{"type":"integer","description":"Order ID."},"original_price":{"type":"number","description":"Original price."},"parent_item_id":{"type":"integer","description":"Parent item ID."},"price":{"type":"number","description":"Price."},"price_incl_tax":{"type":"number","description":"Price including tax."},"product_id":{"type":"integer","description":"Product ID."},"product_type":{"type":"string","description":"Product type."},"qty_backordered":{"type":"number","description":"Quantity backordered."},"qty_canceled":{"type":"number","description":"Quantity canceled."},"qty_invoiced":{"type":"number","description":"Quantity invoiced."},"qty_ordered":{"type":"number","description":"Quantity ordered."},"qty_refunded":{"type":"number","description":"Quantity refunded."},"qty_returned":{"type":"number","description":"Quantity returned."},"qty_shipped":{"type":"number","description":"Quantity shipped."},"quote_item_id":{"type":"integer","description":"Quote item ID."},"row_invoiced":{"type":"number","description":"Row invoiced."},"row_total":{"type":"number","description":"Row total."},"row_total_incl_tax":{"type":"number","description":"Row total including tax."},"row_weight":{"type":"number","description":"Row weight."},"sku":{"type":"string","description":"SKU."},"store_id":{"type":"integer","description":"Store ID."},"tax_amount":{"type":"number","description":"Tax amount."},"tax_before_discount":{"type":"number","description":"Tax before discount."},"tax_canceled":{"type":"number","description":"Tax canceled."},"tax_invoiced":{"type":"number","description":"Tax invoiced."},"tax_percent":{"type":"number","description":"Tax percent."},"tax_refunded":{"type":"number","description":"Tax refunded."},"updated_at":{"type":"string","description":"Updated-at timestamp."},"weee_tax_applied":{"type":"string","description":"WEEE tax applied."},"weee_tax_applied_amount":{"type":"number","description":"WEEE tax applied amount."},"weee_tax_applied_row_amount":{"type":"number","description":"WEEE tax applied row amount."},"weee_tax_disposition":{"type":"number","description":"WEEE tax disposition."},"weee_tax_row_disposition":{"type":"number","description":"WEEE tax row disposition."},"weight":{"type":"number","description":"Weight."},"parent_item":{"$ref":"#/definitions/sales-data-order-item-interface"},"product_option":{"$ref":"#/definitions/catalog-data-product-option-interface"},"extension_attributes":{"$ref":"#/definitions/sales-data-order-item-extension-interface"}},"required":["sku"]},"catalog-data-product-option-interface":{"type":"object","description":"Product option interface","properties":{"extension_attributes":{"$ref":"#/definitions/catalog-data-product-option-extension-interface"}}},"catalog-data-product-option-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Catalog\\Api\\Data\\ProductOptionInterface","properties":{"custom_options":{"type":"array","items":{"$ref":"#/definitions/catalog-data-custom-option-interface"}},"bundle_options":{"type":"array","items":{"$ref":"#/definitions/bundle-data-bundle-option-interface"}},"downloadable_option":{"$ref":"#/definitions/downloadable-data-downloadable-option-interface"},"giftcard_item_option":{"$ref":"#/definitions/gift-card-data-gift-card-option-interface"},"configurable_item_options":{"type":"array","items":{"$ref":"#/definitions/configurable-product-data-configurable-item-option-value-interface"}}}},"sales-data-order-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\OrderItemInterface","properties":{"gift_message":{"$ref":"#/definitions/gift-message-data-message-interface"},"gw_id":{"type":"string"},"gw_base_price":{"type":"string"},"gw_price":{"type":"string"},"gw_base_tax_amount":{"type":"string"},"gw_tax_amount":{"type":"string"},"gw_base_price_invoiced":{"type":"string"},"gw_price_invoiced":{"type":"string"},"gw_base_tax_amount_invoiced":{"type":"string"},"gw_tax_amount_invoiced":{"type":"string"},"gw_base_price_refunded":{"type":"string"},"gw_price_refunded":{"type":"string"},"gw_base_tax_amount_refunded":{"type":"string"},"gw_tax_amount_refunded":{"type":"string"}}},"sales-data-order-address-interface":{"type":"object","description":"Order address interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"address_type":{"type":"string","description":"Address type."},"city":{"type":"string","description":"City."},"company":{"type":"string","description":"Company."},"country_id":{"type":"string","description":"Country ID."},"customer_address_id":{"type":"integer","description":"Country address ID."},"customer_id":{"type":"integer","description":"Customer ID."},"email":{"type":"string","description":"Email address."},"entity_id":{"type":"integer","description":"Order address ID."},"fax":{"type":"string","description":"Fax number."},"firstname":{"type":"string","description":"First name."},"lastname":{"type":"string","description":"Last name."},"middlename":{"type":"string","description":"Middle name."},"parent_id":{"type":"integer","description":"Parent ID."},"postcode":{"type":"string","description":"Postal code."},"prefix":{"type":"string","description":"Prefix."},"region":{"type":"string","description":"Region."},"region_code":{"type":"string","description":"Region code."},"region_id":{"type":"integer","description":"Region ID."},"street":{"type":"array","description":"Array of any street values. Otherwise, null.","items":{"type":"string"}},"suffix":{"type":"string","description":"Suffix."},"telephone":{"type":"string","description":"Telephone number."},"vat_id":{"type":"string","description":"VAT ID."},"vat_is_valid":{"type":"integer","description":"VAT-is-valid flag value."},"vat_request_date":{"type":"string","description":"VAT request date."},"vat_request_id":{"type":"string","description":"VAT request ID."},"vat_request_success":{"type":"integer","description":"VAT-request-success flag value."},"extension_attributes":{"$ref":"#/definitions/sales-data-order-address-extension-interface"}},"required":["address_type","city","country_id","firstname","lastname","postcode","telephone"]},"sales-data-order-address-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\OrderAddressInterface"},"sales-data-order-payment-interface":{"type":"object","description":"Order payment interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"account_status":{"type":"string","description":"Account status."},"additional_data":{"type":"string","description":"Additional data."},"additional_information":{"type":"array","description":"Array of additional information.","items":{"type":"string"}},"address_status":{"type":"string","description":"Address status."},"amount_authorized":{"type":"number","description":"Amount authorized."},"amount_canceled":{"type":"number","description":"Amount canceled."},"amount_ordered":{"type":"number","description":"Amount ordered."},"amount_paid":{"type":"number","description":"Amount paid."},"amount_refunded":{"type":"number","description":"Amount refunded."},"anet_trans_method":{"type":"string","description":"Anet transaction method."},"base_amount_authorized":{"type":"number","description":"Base amount authorized."},"base_amount_canceled":{"type":"number","description":"Base amount canceled."},"base_amount_ordered":{"type":"number","description":"Base amount ordered."},"base_amount_paid":{"type":"number","description":"Base amount paid."},"base_amount_paid_online":{"type":"number","description":"Base amount paid online."},"base_amount_refunded":{"type":"number","description":"Base amount refunded."},"base_amount_refunded_online":{"type":"number","description":"Base amount refunded online."},"base_shipping_amount":{"type":"number","description":"Base shipping amount."},"base_shipping_captured":{"type":"number","description":"Base shipping captured amount."},"base_shipping_refunded":{"type":"number","description":"Base shipping refunded amount."},"cc_approval":{"type":"string","description":"Credit card approval."},"cc_avs_status":{"type":"string","description":"Credit card avs status."},"cc_cid_status":{"type":"string","description":"Credit card CID status."},"cc_debug_request_body":{"type":"string","description":"Credit card debug request body."},"cc_debug_response_body":{"type":"string","description":"Credit card debug response body."},"cc_debug_response_serialized":{"type":"string","description":"Credit card debug response serialized."},"cc_exp_month":{"type":"string","description":"Credit card expiration month."},"cc_exp_year":{"type":"string","description":"Credit card expiration year."},"cc_last4":{"type":"string","description":"Last four digits of the credit card."},"cc_number_enc":{"type":"string","description":"Encrypted credit card number."},"cc_owner":{"type":"string","description":"Credit card number."},"cc_secure_verify":{"type":"string","description":"Credit card secure verify."},"cc_ss_issue":{"type":"string","description":"Credit card SS issue."},"cc_ss_start_month":{"type":"string","description":"Credit card SS start month."},"cc_ss_start_year":{"type":"string","description":"Credit card SS start year."},"cc_status":{"type":"string","description":"Credit card status."},"cc_status_description":{"type":"string","description":"Credit card status description."},"cc_trans_id":{"type":"string","description":"Credit card transaction ID."},"cc_type":{"type":"string","description":"Credit card type."},"echeck_account_name":{"type":"string","description":"eCheck account name."},"echeck_account_type":{"type":"string","description":"eCheck account type."},"echeck_bank_name":{"type":"string","description":"eCheck bank name."},"echeck_routing_number":{"type":"string","description":"eCheck routing number."},"echeck_type":{"type":"string","description":"eCheck type."},"entity_id":{"type":"integer","description":"Entity ID."},"last_trans_id":{"type":"string","description":"Last transaction ID."},"method":{"type":"string","description":"Method."},"parent_id":{"type":"integer","description":"Parent ID."},"po_number":{"type":"string","description":"PO number."},"protection_eligibility":{"type":"string","description":"Protection eligibility."},"quote_payment_id":{"type":"integer","description":"Quote payment ID."},"shipping_amount":{"type":"number","description":"Shipping amount."},"shipping_captured":{"type":"number","description":"Shipping captured."},"shipping_refunded":{"type":"number","description":"Shipping refunded."},"extension_attributes":{"$ref":"#/definitions/sales-data-order-payment-extension-interface"}},"required":["account_status","additional_information","cc_last4","method"]},"sales-data-order-payment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\OrderPaymentInterface","properties":{"vault_payment_token":{"$ref":"#/definitions/vault-data-payment-token-interface"}}},"vault-data-payment-token-interface":{"type":"object","description":"Gateway vault payment token interface.","properties":{"entity_id":{"type":"integer","description":"Entity ID."},"customer_id":{"type":"integer","description":"Customer ID."},"public_hash":{"type":"string","description":"Public hash"},"payment_method_code":{"type":"string","description":"Payment method code"},"type":{"type":"string","description":"Type"},"created_at":{"type":"string","description":"Token creation timestamp"},"expires_at":{"type":"string","description":"Token expiration timestamp"},"gateway_token":{"type":"string","description":"Gateway token ID"},"token_details":{"type":"string","description":"Token details"},"is_active":{"type":"boolean","description":"Is active."},"is_visible":{"type":"boolean","description":"Is visible."}},"required":["public_hash","payment_method_code","type","gateway_token","token_details","is_active","is_visible"]},"sales-data-order-status-history-interface":{"type":"object","description":"Order status history interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"comment":{"type":"string","description":"Comment."},"created_at":{"type":"string","description":"Created-at timestamp."},"entity_id":{"type":"integer","description":"Order status history ID."},"entity_name":{"type":"string","description":"Entity name."},"is_customer_notified":{"type":"integer","description":"Is-customer-notified flag value."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."},"parent_id":{"type":"integer","description":"Parent ID."},"status":{"type":"string","description":"Status."},"extension_attributes":{"$ref":"#/definitions/sales-data-order-status-history-extension-interface"}},"required":["comment","is_customer_notified","is_visible_on_front","parent_id"]},"sales-data-order-status-history-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\OrderStatusHistoryInterface"},"sales-data-order-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\OrderInterface","properties":{"shipping_assignments":{"type":"array","items":{"$ref":"#/definitions/sales-data-shipping-assignment-interface"}},"base_customer_balance_amount":{"type":"number"},"customer_balance_amount":{"type":"number"},"base_customer_balance_invoiced":{"type":"number"},"customer_balance_invoiced":{"type":"number"},"base_customer_balance_refunded":{"type":"number"},"customer_balance_refunded":{"type":"number"},"base_customer_balance_total_refunded":{"type":"number"},"customer_balance_total_refunded":{"type":"number"},"gift_cards":{"type":"array","items":{"$ref":"#/definitions/gift-card-account-data-gift-card-interface"}},"base_gift_cards_amount":{"type":"number"},"gift_cards_amount":{"type":"number"},"base_gift_cards_invoiced":{"type":"number"},"gift_cards_invoiced":{"type":"number"},"base_gift_cards_refunded":{"type":"number"},"gift_cards_refunded":{"type":"number"},"applied_taxes":{"type":"array","items":{"$ref":"#/definitions/tax-data-order-tax-details-applied-tax-interface"}},"item_applied_taxes":{"type":"array","items":{"$ref":"#/definitions/tax-data-order-tax-details-item-interface"}},"converting_from_quote":{"type":"boolean"},"gift_message":{"$ref":"#/definitions/gift-message-data-message-interface"},"gw_id":{"type":"string"},"gw_allow_gift_receipt":{"type":"string"},"gw_add_card":{"type":"string"},"gw_base_price":{"type":"string"},"gw_price":{"type":"string"},"gw_items_base_price":{"type":"string"},"gw_items_price":{"type":"string"},"gw_card_base_price":{"type":"string"},"gw_card_price":{"type":"string"},"gw_base_tax_amount":{"type":"string"},"gw_tax_amount":{"type":"string"},"gw_items_base_tax_amount":{"type":"string"},"gw_items_tax_amount":{"type":"string"},"gw_card_base_tax_amount":{"type":"string"},"gw_card_tax_amount":{"type":"string"},"gw_base_price_incl_tax":{"type":"string"},"gw_price_incl_tax":{"type":"string"},"gw_items_base_price_incl_tax":{"type":"string"},"gw_items_price_incl_tax":{"type":"string"},"gw_card_base_price_incl_tax":{"type":"string"},"gw_card_price_incl_tax":{"type":"string"},"gw_base_price_invoiced":{"type":"string"},"gw_price_invoiced":{"type":"string"},"gw_items_base_price_invoiced":{"type":"string"},"gw_items_price_invoiced":{"type":"string"},"gw_card_base_price_invoiced":{"type":"string"},"gw_card_price_invoiced":{"type":"string"},"gw_base_tax_amount_invoiced":{"type":"string"},"gw_tax_amount_invoiced":{"type":"string"},"gw_items_base_tax_invoiced":{"type":"string"},"gw_items_tax_invoiced":{"type":"string"},"gw_card_base_tax_invoiced":{"type":"string"},"gw_card_tax_invoiced":{"type":"string"},"gw_base_price_refunded":{"type":"string"},"gw_price_refunded":{"type":"string"},"gw_items_base_price_refunded":{"type":"string"},"gw_items_price_refunded":{"type":"string"},"gw_card_base_price_refunded":{"type":"string"},"gw_card_price_refunded":{"type":"string"},"gw_base_tax_amount_refunded":{"type":"string"},"gw_tax_amount_refunded":{"type":"string"},"gw_items_base_tax_refunded":{"type":"string"},"gw_items_tax_refunded":{"type":"string"},"gw_card_base_tax_refunded":{"type":"string"},"gw_card_tax_refunded":{"type":"string"}}},"sales-data-shipping-assignment-interface":{"type":"object","description":"Interface ShippingAssignmentInterface","properties":{"shipping":{"$ref":"#/definitions/sales-data-shipping-interface"},"items":{"type":"array","description":"Order items of shipping assignment","items":{"$ref":"#/definitions/sales-data-order-item-interface"}},"stock_id":{"type":"integer","description":"Stock id"},"extension_attributes":{"$ref":"#/definitions/sales-data-shipping-assignment-extension-interface"}},"required":["shipping","items"]},"sales-data-shipping-interface":{"type":"object","description":"Interface ShippingInterface","properties":{"address":{"$ref":"#/definitions/sales-data-order-address-interface"},"method":{"type":"string","description":"Shipping method"},"total":{"$ref":"#/definitions/sales-data-total-interface"},"extension_attributes":{"$ref":"#/definitions/sales-data-shipping-extension-interface"}}},"sales-data-total-interface":{"type":"object","description":"Interface TotalInterface","properties":{"base_shipping_amount":{"type":"number","description":"Base shipping amount."},"base_shipping_canceled":{"type":"number","description":"Base shipping canceled."},"base_shipping_discount_amount":{"type":"number","description":"Base shipping discount amount."},"base_shipping_discount_tax_compensation_amnt":{"type":"number","description":"Base shipping discount tax compensation amount."},"base_shipping_incl_tax":{"type":"number","description":"Base shipping including tax."},"base_shipping_invoiced":{"type":"number","description":"Base shipping invoiced."},"base_shipping_refunded":{"type":"number","description":"Base shipping refunded."},"base_shipping_tax_amount":{"type":"number","description":"Base shipping tax amount."},"base_shipping_tax_refunded":{"type":"number","description":"Base shipping tax refunded."},"shipping_amount":{"type":"number","description":"Shipping amount."},"shipping_canceled":{"type":"number","description":"Shipping canceled amount."},"shipping_discount_amount":{"type":"number","description":"Shipping discount amount."},"shipping_discount_tax_compensation_amount":{"type":"number","description":"Shipping discount tax compensation amount."},"shipping_incl_tax":{"type":"number","description":"Shipping including tax amount."},"shipping_invoiced":{"type":"number","description":"Shipping invoiced amount."},"shipping_refunded":{"type":"number","description":"Shipping refunded amount."},"shipping_tax_amount":{"type":"number","description":"Shipping tax amount."},"shipping_tax_refunded":{"type":"number","description":"Shipping tax refunded amount."},"extension_attributes":{"$ref":"#/definitions/sales-data-total-extension-interface"}}},"sales-data-total-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\TotalInterface"},"sales-data-shipping-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShippingInterface"},"sales-data-shipping-assignment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShippingAssignmentInterface"},"gift-card-account-data-gift-card-interface":{"type":"object","description":"Gift Card data","properties":{"id":{"type":"integer","description":"Id"},"code":{"type":"string","description":"Code"},"amount":{"type":"number","description":"Amount"},"base_amount":{"type":"number","description":"Base Amount"}},"required":["id","code","amount","base_amount"]},"tax-data-order-tax-details-applied-tax-interface":{"type":"object","description":"Interface OrderTaxDetailsAppliedTaxInterface","properties":{"code":{"type":"string","description":"Code"},"title":{"type":"string","description":"Title"},"percent":{"type":"number","description":"Tax Percent"},"amount":{"type":"number","description":"Tax amount"},"base_amount":{"type":"number","description":"Tax amount in base currency"},"extension_attributes":{"$ref":"#/definitions/tax-data-order-tax-details-applied-tax-extension-interface"}},"required":["amount","base_amount"]},"tax-data-order-tax-details-applied-tax-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\OrderTaxDetailsAppliedTaxInterface","properties":{"rates":{"type":"array","items":{"$ref":"#/definitions/tax-data-applied-tax-rate-interface"}}}},"tax-data-applied-tax-rate-interface":{"type":"object","description":"Applied tax rate interface.","properties":{"code":{"type":"string","description":"Code"},"title":{"type":"string","description":"Title"},"percent":{"type":"number","description":"Tax Percent"},"extension_attributes":{"$ref":"#/definitions/tax-data-applied-tax-rate-extension-interface"}}},"tax-data-applied-tax-rate-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\AppliedTaxRateInterface"},"tax-data-order-tax-details-item-interface":{"type":"object","description":"Interface OrderTaxDetailsItemInterface","properties":{"type":{"type":"string","description":"Type (shipping, product, weee, gift wrapping, etc)"},"item_id":{"type":"integer","description":"Item id if this item is a product"},"associated_item_id":{"type":"integer","description":"Associated item id if this item is associated with another item, null otherwise"},"applied_taxes":{"type":"array","description":"Applied taxes","items":{"$ref":"#/definitions/tax-data-order-tax-details-applied-tax-interface"}},"extension_attributes":{"$ref":"#/definitions/tax-data-order-tax-details-item-extension-interface"}}},"tax-data-order-tax-details-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\OrderTaxDetailsItemInterface"},"sales-data-order-search-result-interface":{"type":"object","description":"Order search result interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-order-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-order-status-history-search-result-interface":{"type":"object","description":"Order status history search result interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-order-status-history-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-order-item-search-result-interface":{"type":"object","description":"Order item search result interface. An order is a document that a web store issues to a customer. Magento generates a sales order that lists the product items, billing and shipping addresses, and shipping and payment methods. A corresponding external document, known as a purchase order, is emailed to the customer.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-order-item-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-invoice-interface":{"type":"object","description":"Invoice interface. An invoice is a record of the receipt of payment for an order.","properties":{"base_currency_code":{"type":"string","description":"Base currency code."},"base_discount_amount":{"type":"number","description":"Base discount amount."},"base_grand_total":{"type":"number","description":"Base grand total."},"base_discount_tax_compensation_amount":{"type":"number","description":"Base discount tax compensation amount."},"base_shipping_amount":{"type":"number","description":"Base shipping amount."},"base_shipping_discount_tax_compensation_amnt":{"type":"number","description":"Base shipping discount tax compensation amount."},"base_shipping_incl_tax":{"type":"number","description":"Base shipping including tax."},"base_shipping_tax_amount":{"type":"number","description":"Base shipping tax amount."},"base_subtotal":{"type":"number","description":"Base subtotal."},"base_subtotal_incl_tax":{"type":"number","description":"Base subtotal including tax."},"base_tax_amount":{"type":"number","description":"Base tax amount."},"base_total_refunded":{"type":"number","description":"Base total refunded."},"base_to_global_rate":{"type":"number","description":"Base-to-global rate."},"base_to_order_rate":{"type":"number","description":"Base-to-order rate."},"billing_address_id":{"type":"integer","description":"Billing address ID."},"can_void_flag":{"type":"integer","description":"Can void flag value."},"created_at":{"type":"string","description":"Created-at timestamp."},"discount_amount":{"type":"number","description":"Discount amount."},"discount_description":{"type":"string","description":"Discount description."},"email_sent":{"type":"integer","description":"Email-sent flag value."},"entity_id":{"type":"integer","description":"Invoice ID."},"global_currency_code":{"type":"string","description":"Global currency code."},"grand_total":{"type":"number","description":"Grand total."},"discount_tax_compensation_amount":{"type":"number","description":"Discount tax compensation amount."},"increment_id":{"type":"string","description":"Increment ID."},"is_used_for_refund":{"type":"integer","description":"Is-used-for-refund flag value."},"order_currency_code":{"type":"string","description":"Order currency code."},"order_id":{"type":"integer","description":"Order ID."},"shipping_address_id":{"type":"integer","description":"Shipping address ID."},"shipping_amount":{"type":"number","description":"Shipping amount."},"shipping_discount_tax_compensation_amount":{"type":"number","description":"Shipping discount tax compensation amount."},"shipping_incl_tax":{"type":"number","description":"Shipping including tax."},"shipping_tax_amount":{"type":"number","description":"Shipping tax amount."},"state":{"type":"integer","description":"State."},"store_currency_code":{"type":"string","description":"Store currency code."},"store_id":{"type":"integer","description":"Store ID."},"store_to_base_rate":{"type":"number","description":"Store-to-base rate."},"store_to_order_rate":{"type":"number","description":"Store-to-order rate."},"subtotal":{"type":"number","description":"Subtotal."},"subtotal_incl_tax":{"type":"number","description":"Subtotal including tax."},"tax_amount":{"type":"number","description":"Tax amount."},"total_qty":{"type":"number","description":"Total quantity."},"transaction_id":{"type":"string","description":"Transaction ID."},"updated_at":{"type":"string","description":"Updated-at timestamp."},"items":{"type":"array","description":"Array of invoice items.","items":{"$ref":"#/definitions/sales-data-invoice-item-interface"}},"comments":{"type":"array","description":"Array of any invoice comments. Otherwise, null.","items":{"$ref":"#/definitions/sales-data-invoice-comment-interface"}},"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-extension-interface"}},"required":["order_id","total_qty","items"]},"sales-data-invoice-item-interface":{"type":"object","description":"Invoice item interface. An invoice is a record of the receipt of payment for an order. An invoice item is a purchased item in an invoice.","properties":{"additional_data":{"type":"string","description":"Additional data."},"base_cost":{"type":"number","description":"Base cost."},"base_discount_amount":{"type":"number","description":"Base discount amount."},"base_discount_tax_compensation_amount":{"type":"number","description":"Base discount tax compensation amount."},"base_price":{"type":"number","description":"Base price."},"base_price_incl_tax":{"type":"number","description":"Base price including tax."},"base_row_total":{"type":"number","description":"Base row total."},"base_row_total_incl_tax":{"type":"number","description":"Base row total including tax."},"base_tax_amount":{"type":"number","description":"Base tax amount."},"description":{"type":"string","description":"Description."},"discount_amount":{"type":"number","description":"Discount amount."},"entity_id":{"type":"integer","description":"Invoice item ID."},"discount_tax_compensation_amount":{"type":"number","description":"Discount tax compensation amount."},"name":{"type":"string","description":"Name."},"parent_id":{"type":"integer","description":"Parent ID."},"price":{"type":"number","description":"Price."},"price_incl_tax":{"type":"number","description":"Price including tax."},"product_id":{"type":"integer","description":"Product ID."},"row_total":{"type":"number","description":"Row total."},"row_total_incl_tax":{"type":"number","description":"Row total including tax."},"sku":{"type":"string","description":"SKU."},"tax_amount":{"type":"number","description":"Tax amount."},"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-item-extension-interface"},"order_item_id":{"type":"integer","description":"Order item ID."},"qty":{"type":"number","description":"Quantity."}},"required":["sku","order_item_id","qty"]},"sales-data-invoice-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceItemInterface"},"sales-data-invoice-comment-interface":{"type":"object","description":"Invoice comment interface. An invoice is a record of the receipt of payment for an order. An invoice can include comments that detail the invoice history.","properties":{"is_customer_notified":{"type":"integer","description":"Is-customer-notified flag value."},"parent_id":{"type":"integer","description":"Parent ID."},"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-comment-extension-interface"},"comment":{"type":"string","description":"Comment."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."},"created_at":{"type":"string","description":"Created-at timestamp."},"entity_id":{"type":"integer","description":"Invoice ID."}},"required":["is_customer_notified","parent_id","comment","is_visible_on_front"]},"sales-data-invoice-comment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceCommentInterface"},"sales-data-invoice-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceInterface","properties":{"base_customer_balance_amount":{"type":"number"},"customer_balance_amount":{"type":"number"},"base_gift_cards_amount":{"type":"number"},"gift_cards_amount":{"type":"number"},"gw_base_price":{"type":"string"},"gw_price":{"type":"string"},"gw_items_base_price":{"type":"string"},"gw_items_price":{"type":"string"},"gw_card_base_price":{"type":"string"},"gw_card_price":{"type":"string"},"gw_base_tax_amount":{"type":"string"},"gw_tax_amount":{"type":"string"},"gw_items_base_tax_amount":{"type":"string"},"gw_items_tax_amount":{"type":"string"},"gw_card_base_tax_amount":{"type":"string"},"gw_card_tax_amount":{"type":"string"},"invoice_api_test_attribute":{"$ref":"#/definitions/user-data-user-interface"}}},"sales-data-invoice-search-result-interface":{"type":"object","description":"Invoice search result interface. An invoice is a record of the receipt of payment for an order.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-invoice-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-invoice-comment-search-result-interface":{"type":"object","description":"Invoice comment search result interface. An invoice is a record of the receipt of payment for an order. An invoice can include comments that detail the invoice history.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-invoice-comment-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-creditmemo-item-creation-interface":{"type":"object","description":"Interface CreditmemoItemCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-item-creation-extension-interface"},"order_item_id":{"type":"integer","description":"Order item ID."},"qty":{"type":"number","description":"Quantity."}},"required":["order_item_id","qty"]},"sales-data-creditmemo-item-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoItemCreationInterface"},"sales-data-creditmemo-comment-creation-interface":{"type":"object","description":"Interface CreditmemoCommentCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-comment-creation-extension-interface"},"comment":{"type":"string","description":"Comment."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."}},"required":["comment","is_visible_on_front"]},"sales-data-creditmemo-comment-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoCommentCreationInterface"},"sales-data-creditmemo-creation-arguments-interface":{"type":"object","description":"Interface CreditmemoCreationArgumentsInterface","properties":{"shipping_amount":{"type":"number","description":"Credit memo shipping amount."},"adjustment_positive":{"type":"number","description":"Credit memo positive adjustment."},"adjustment_negative":{"type":"number","description":"Credit memo negative adjustment."},"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-creation-arguments-extension-interface"}}},"sales-data-creditmemo-creation-arguments-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoCreationArgumentsInterface","properties":{"return_to_stock_items":{"type":"array","items":{"type":"integer"}}}},"sales-data-creditmemo-comment-search-result-interface":{"type":"object","description":"Credit memo comment search result interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases. A credit memo usually includes comments that detail why the credit memo amount was credited to the customer.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-creditmemo-comment-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-creditmemo-comment-interface":{"type":"object","description":"Credit memo comment interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases. A credit memo usually includes comments that detail why the credit memo amount was credited to the customer.","properties":{"comment":{"type":"string","description":"Comment."},"created_at":{"type":"string","description":"Created-at timestamp."},"entity_id":{"type":"integer","description":"Credit memo ID."},"is_customer_notified":{"type":"integer","description":"Is-customer-notified flag value."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."},"parent_id":{"type":"integer","description":"Parent ID."},"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-comment-extension-interface"}},"required":["comment","is_customer_notified","is_visible_on_front","parent_id"]},"sales-data-creditmemo-comment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoCommentInterface"},"sales-data-creditmemo-interface":{"type":"object","description":"Credit memo interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases.","properties":{"adjustment":{"type":"number","description":"Credit memo adjustment."},"adjustment_negative":{"type":"number","description":"Credit memo negative adjustment."},"adjustment_positive":{"type":"number","description":"Credit memo positive adjustment."},"base_adjustment":{"type":"number","description":"Credit memo base adjustment."},"base_adjustment_negative":{"type":"number","description":"Credit memo negative base adjustment."},"base_adjustment_positive":{"type":"number","description":"Credit memo positive base adjustment."},"base_currency_code":{"type":"string","description":"Credit memo base currency code."},"base_discount_amount":{"type":"number","description":"Credit memo base discount amount."},"base_grand_total":{"type":"number","description":"Credit memo base grand total."},"base_discount_tax_compensation_amount":{"type":"number","description":"Credit memo base discount tax compensation amount."},"base_shipping_amount":{"type":"number","description":"Credit memo base shipping amount."},"base_shipping_discount_tax_compensation_amnt":{"type":"number","description":"Credit memo base shipping discount tax compensation amount."},"base_shipping_incl_tax":{"type":"number","description":"Credit memo base shipping including tax."},"base_shipping_tax_amount":{"type":"number","description":"Credit memo base shipping tax amount."},"base_subtotal":{"type":"number","description":"Credit memo base subtotal."},"base_subtotal_incl_tax":{"type":"number","description":"Credit memo base subtotal including tax."},"base_tax_amount":{"type":"number","description":"Credit memo base tax amount."},"base_to_global_rate":{"type":"number","description":"Credit memo base-to-global rate."},"base_to_order_rate":{"type":"number","description":"Credit memo base-to-order rate."},"billing_address_id":{"type":"integer","description":"Credit memo billing address ID."},"created_at":{"type":"string","description":"Credit memo created-at timestamp."},"creditmemo_status":{"type":"integer","description":"Credit memo status."},"discount_amount":{"type":"number","description":"Credit memo discount amount."},"discount_description":{"type":"string","description":"Credit memo discount description."},"email_sent":{"type":"integer","description":"Credit memo email sent flag value."},"entity_id":{"type":"integer","description":"Credit memo ID."},"global_currency_code":{"type":"string","description":"Credit memo global currency code."},"grand_total":{"type":"number","description":"Credit memo grand total."},"discount_tax_compensation_amount":{"type":"number","description":"Credit memo discount tax compensation amount."},"increment_id":{"type":"string","description":"Credit memo increment ID."},"invoice_id":{"type":"integer","description":"Credit memo invoice ID."},"order_currency_code":{"type":"string","description":"Credit memo order currency code."},"order_id":{"type":"integer","description":"Credit memo order ID."},"shipping_address_id":{"type":"integer","description":"Credit memo shipping address ID."},"shipping_amount":{"type":"number","description":"Credit memo shipping amount."},"shipping_discount_tax_compensation_amount":{"type":"number","description":"Credit memo shipping discount tax compensation amount."},"shipping_incl_tax":{"type":"number","description":"Credit memo shipping including tax."},"shipping_tax_amount":{"type":"number","description":"Credit memo shipping tax amount."},"state":{"type":"integer","description":"Credit memo state."},"store_currency_code":{"type":"string","description":"Credit memo store currency code."},"store_id":{"type":"integer","description":"Credit memo store ID."},"store_to_base_rate":{"type":"number","description":"Credit memo store-to-base rate."},"store_to_order_rate":{"type":"number","description":"Credit memo store-to-order rate."},"subtotal":{"type":"number","description":"Credit memo subtotal."},"subtotal_incl_tax":{"type":"number","description":"Credit memo subtotal including tax."},"tax_amount":{"type":"number","description":"Credit memo tax amount."},"transaction_id":{"type":"string","description":"Credit memo transaction ID."},"updated_at":{"type":"string","description":"Credit memo updated-at timestamp."},"items":{"type":"array","description":"Array of credit memo items.","items":{"$ref":"#/definitions/sales-data-creditmemo-item-interface"}},"comments":{"type":"array","description":"Array of any credit memo comments. Otherwise, null.","items":{"$ref":"#/definitions/sales-data-creditmemo-comment-interface"}},"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-extension-interface"}},"required":["order_id","items"]},"sales-data-creditmemo-item-interface":{"type":"object","description":"Credit memo item interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases. A credit memo item is an invoiced item for which a merchant creates a credit memo.","properties":{"additional_data":{"type":"string","description":"Additional data."},"base_cost":{"type":"number","description":"The base cost for a credit memo item."},"base_discount_amount":{"type":"number","description":"The base discount amount for a credit memo item."},"base_discount_tax_compensation_amount":{"type":"number","description":"The base discount tax compensation amount for a credit memo item."},"base_price":{"type":"number","description":"The base price for a credit memo item."},"base_price_incl_tax":{"type":"number","description":"Base price including tax."},"base_row_total":{"type":"number","description":"Base row total."},"base_row_total_incl_tax":{"type":"number","description":"Base row total including tax."},"base_tax_amount":{"type":"number","description":"Base tax amount."},"base_weee_tax_applied_amount":{"type":"number","description":"Base WEEE tax applied amount."},"base_weee_tax_applied_row_amnt":{"type":"number","description":"Base WEEE tax applied row amount."},"base_weee_tax_disposition":{"type":"number","description":"Base WEEE tax disposition."},"base_weee_tax_row_disposition":{"type":"number","description":"Base WEEE tax row disposition."},"description":{"type":"string","description":"Description."},"discount_amount":{"type":"number","description":"Discount amount."},"entity_id":{"type":"integer","description":"Credit memo item ID."},"discount_tax_compensation_amount":{"type":"number","description":"Discount tax compensation amount."},"name":{"type":"string","description":"Name."},"order_item_id":{"type":"integer","description":"Order item ID."},"parent_id":{"type":"integer","description":"Parent ID."},"price":{"type":"number","description":"Price."},"price_incl_tax":{"type":"number","description":"Price including tax."},"product_id":{"type":"integer","description":"Product ID."},"qty":{"type":"number","description":"Quantity."},"row_total":{"type":"number","description":"Row total."},"row_total_incl_tax":{"type":"number","description":"Row total including tax."},"sku":{"type":"string","description":"SKU."},"tax_amount":{"type":"number","description":"Tax amount."},"weee_tax_applied":{"type":"string","description":"WEEE tax applied."},"weee_tax_applied_amount":{"type":"number","description":"WEEE tax applied amount."},"weee_tax_applied_row_amount":{"type":"number","description":"WEEE tax applied row amount."},"weee_tax_disposition":{"type":"number","description":"WEEE tax disposition."},"weee_tax_row_disposition":{"type":"number","description":"WEEE tax row disposition."},"extension_attributes":{"$ref":"#/definitions/sales-data-creditmemo-item-extension-interface"}},"required":["base_cost","base_price","entity_id","order_item_id","qty"]},"sales-data-creditmemo-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoItemInterface"},"sales-data-creditmemo-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\CreditmemoInterface","properties":{"base_customer_balance_amount":{"type":"number"},"customer_balance_amount":{"type":"number"},"base_gift_cards_amount":{"type":"number"},"gift_cards_amount":{"type":"number"},"gw_base_price":{"type":"string"},"gw_price":{"type":"string"},"gw_items_base_price":{"type":"string"},"gw_items_price":{"type":"string"},"gw_card_base_price":{"type":"string"},"gw_card_price":{"type":"string"},"gw_base_tax_amount":{"type":"string"},"gw_tax_amount":{"type":"string"},"gw_items_base_tax_amount":{"type":"string"},"gw_items_tax_amount":{"type":"string"},"gw_card_base_tax_amount":{"type":"string"},"gw_card_tax_amount":{"type":"string"}}},"sales-data-creditmemo-search-result-interface":{"type":"object","description":"Credit memo search result interface. After a customer places and pays for an order and an invoice has been issued, the merchant can create a credit memo to refund all or part of the amount paid for any returned or undelivered items. The memo restores funds to the customer account so that the customer can make future purchases.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-creditmemo-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-shipment-interface":{"type":"object","description":"Shipment interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package.","properties":{"billing_address_id":{"type":"integer","description":"Billing address ID."},"created_at":{"type":"string","description":"Created-at timestamp."},"customer_id":{"type":"integer","description":"Customer ID."},"email_sent":{"type":"integer","description":"Email-sent flag value."},"entity_id":{"type":"integer","description":"Shipment ID."},"increment_id":{"type":"string","description":"Increment ID."},"order_id":{"type":"integer","description":"Order ID."},"packages":{"type":"array","description":"Array of packages, if any. Otherwise, null.","items":{"$ref":"#/definitions/sales-data-shipment-package-interface"}},"shipment_status":{"type":"integer","description":"Shipment status."},"shipping_address_id":{"type":"integer","description":"Shipping address ID."},"shipping_label":{"type":"string","description":"Shipping label."},"store_id":{"type":"integer","description":"Store ID."},"total_qty":{"type":"number","description":"Total quantity."},"total_weight":{"type":"number","description":"Total weight."},"updated_at":{"type":"string","description":"Updated-at timestamp."},"items":{"type":"array","description":"Array of items.","items":{"$ref":"#/definitions/sales-data-shipment-item-interface"}},"tracks":{"type":"array","description":"Array of tracks.","items":{"$ref":"#/definitions/sales-data-shipment-track-interface"}},"comments":{"type":"array","description":"Array of comments.","items":{"$ref":"#/definitions/sales-data-shipment-comment-interface"}},"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-extension-interface"}},"required":["order_id","items","tracks","comments"]},"sales-data-shipment-package-interface":{"type":"object","description":"Shipment package interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package.","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-package-extension-interface"}}},"sales-data-shipment-package-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentPackageInterface"},"sales-data-shipment-item-interface":{"type":"object","description":"Shipment item interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package. A product is an item in a shipment.","properties":{"additional_data":{"type":"string","description":"Additional data."},"description":{"type":"string","description":"Description."},"entity_id":{"type":"integer","description":"Shipment item ID."},"name":{"type":"string","description":"Name."},"parent_id":{"type":"integer","description":"Parent ID."},"price":{"type":"number","description":"Price."},"product_id":{"type":"integer","description":"Product ID."},"row_total":{"type":"number","description":"Row total."},"sku":{"type":"string","description":"SKU."},"weight":{"type":"number","description":"Weight."},"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-item-extension-interface"},"order_item_id":{"type":"integer","description":"Order item ID."},"qty":{"type":"number","description":"Quantity."}},"required":["order_item_id","qty"]},"sales-data-shipment-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentItemInterface"},"sales-data-shipment-track-interface":{"type":"object","description":"Shipment track interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package. Merchants and customers can track shipments.","properties":{"order_id":{"type":"integer","description":"The order_id for the shipment package."},"created_at":{"type":"string","description":"Created-at timestamp."},"entity_id":{"type":"integer","description":"Shipment package ID."},"parent_id":{"type":"integer","description":"Parent ID."},"updated_at":{"type":"string","description":"Updated-at timestamp."},"weight":{"type":"number","description":"Weight."},"qty":{"type":"number","description":"Quantity."},"description":{"type":"string","description":"Description."},"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-track-extension-interface"},"track_number":{"type":"string","description":"Track number."},"title":{"type":"string","description":"Title."},"carrier_code":{"type":"string","description":"Carrier code."}},"required":["order_id","parent_id","weight","qty","description","track_number","title","carrier_code"]},"sales-data-shipment-track-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentTrackInterface"},"sales-data-shipment-comment-interface":{"type":"object","description":"Shipment comment interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package. A shipment document can contain comments.","properties":{"is_customer_notified":{"type":"integer","description":"Is-customer-notified flag value."},"parent_id":{"type":"integer","description":"Parent ID."},"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-comment-extension-interface"},"comment":{"type":"string","description":"Comment."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."},"created_at":{"type":"string","description":"Created-at timestamp."},"entity_id":{"type":"integer","description":"Invoice ID."}},"required":["is_customer_notified","parent_id","comment","is_visible_on_front"]},"sales-data-shipment-comment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentCommentInterface"},"sales-data-shipment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentInterface"},"sales-data-shipment-search-result-interface":{"type":"object","description":"Shipment search result interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-shipment-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-shipment-comment-search-result-interface":{"type":"object","description":"Shipment comment search result interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package. A shipment document can contain comments.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-shipment-comment-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-shipment-item-creation-interface":{"type":"object","description":"Input argument for shipment item creation Interface ShipmentItemCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-item-creation-extension-interface"},"order_item_id":{"type":"integer","description":"Order item ID."},"qty":{"type":"number","description":"Quantity."}},"required":["order_item_id","qty"]},"sales-data-shipment-item-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentItemCreationInterface"},"sales-data-shipment-comment-creation-interface":{"type":"object","description":"Interface ShipmentCommentCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-comment-creation-extension-interface"},"comment":{"type":"string","description":"Comment."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."}},"required":["comment","is_visible_on_front"]},"sales-data-shipment-comment-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentCommentCreationInterface"},"sales-data-shipment-track-creation-interface":{"type":"object","description":"Shipment Track Creation interface.","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-track-creation-extension-interface"},"track_number":{"type":"string","description":"Track number."},"title":{"type":"string","description":"Title."},"carrier_code":{"type":"string","description":"Carrier code."}},"required":["track_number","title","carrier_code"]},"sales-data-shipment-track-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentTrackCreationInterface"},"sales-data-shipment-package-creation-interface":{"type":"object","description":"Shipment package interface. A shipment is a delivery package that contains products. A shipment document accompanies the shipment. This document lists the products and their quantities in the delivery package.","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-package-creation-extension-interface"}}},"sales-data-shipment-package-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentPackageCreationInterface"},"sales-data-shipment-creation-arguments-interface":{"type":"object","description":"Interface for creation arguments for Shipment.","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-shipment-creation-arguments-extension-interface"}}},"sales-data-shipment-creation-arguments-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\ShipmentCreationArgumentsInterface"},"sales-data-transaction-interface":{"type":"object","description":"Transaction interface. A transaction is an interaction between a merchant and a customer such as a purchase, a credit, a refund, and so on.","properties":{"transaction_id":{"type":"integer","description":"Transaction ID."},"parent_id":{"type":"integer","description":"The parent ID for the transaction. Otherwise, null."},"order_id":{"type":"integer","description":"Order ID."},"payment_id":{"type":"integer","description":"Payment ID."},"txn_id":{"type":"string","description":"Transaction business ID."},"parent_txn_id":{"type":"string","description":"Parent transaction business ID."},"txn_type":{"type":"string","description":"Transaction type."},"is_closed":{"type":"integer","description":"Is-closed flag value."},"additional_information":{"type":"array","description":"Array of additional information. Otherwise, null.","items":{"type":"string"}},"created_at":{"type":"string","description":"Created-at timestamp."},"child_transactions":{"type":"array","description":"Array of child transactions.","items":{"$ref":"#/definitions/sales-data-transaction-interface"}},"extension_attributes":{"$ref":"#/definitions/sales-data-transaction-extension-interface"}},"required":["transaction_id","order_id","payment_id","txn_id","parent_txn_id","txn_type","is_closed","created_at","child_transactions"]},"sales-data-transaction-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\TransactionInterface"},"sales-data-transaction-search-result-interface":{"type":"object","description":"Transaction search result interface. A transaction is an interaction between a merchant and a customer such as a purchase, a credit, a refund, and so on.","properties":{"items":{"type":"array","description":"Array of collection items.","items":{"$ref":"#/definitions/sales-data-transaction-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-data-invoice-item-creation-interface":{"type":"object","description":"Input argument for invoice creation Interface InvoiceItemCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-item-creation-extension-interface"},"order_item_id":{"type":"integer","description":"Order item ID."},"qty":{"type":"number","description":"Quantity."}},"required":["order_item_id","qty"]},"sales-data-invoice-item-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceItemCreationInterface"},"sales-data-invoice-comment-creation-interface":{"type":"object","description":"Interface InvoiceCommentCreationInterface","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-comment-creation-extension-interface"},"comment":{"type":"string","description":"Comment."},"is_visible_on_front":{"type":"integer","description":"Is-visible-on-storefront flag value."}},"required":["comment","is_visible_on_front"]},"sales-data-invoice-comment-creation-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceCommentCreationInterface"},"sales-data-invoice-creation-arguments-interface":{"type":"object","description":"Interface for creation arguments for Invoice.","properties":{"extension_attributes":{"$ref":"#/definitions/sales-data-invoice-creation-arguments-extension-interface"}}},"sales-data-invoice-creation-arguments-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Sales\\Api\\Data\\InvoiceCreationArgumentsInterface"},"checkout-data-shipping-information-interface":{"type":"object","description":"Interface ShippingInformationInterface","properties":{"shipping_address":{"$ref":"#/definitions/quote-data-address-interface"},"billing_address":{"$ref":"#/definitions/quote-data-address-interface"},"shipping_method_code":{"type":"string","description":"Shipping method code"},"shipping_carrier_code":{"type":"string","description":"Carrier code"},"extension_attributes":{"$ref":"#/definitions/checkout-data-shipping-information-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["shipping_address","shipping_method_code","shipping_carrier_code"]},"checkout-data-shipping-information-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Checkout\\Api\\Data\\ShippingInformationInterface"},"checkout-data-payment-details-interface":{"type":"object","description":"Interface PaymentDetailsInterface","properties":{"payment_methods":{"type":"array","items":{"$ref":"#/definitions/quote-data-payment-method-interface"}},"totals":{"$ref":"#/definitions/quote-data-totals-interface"},"extension_attributes":{"$ref":"#/definitions/checkout-data-payment-details-extension-interface"}},"required":["payment_methods","totals"]},"checkout-data-payment-details-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Checkout\\Api\\Data\\PaymentDetailsInterface"},"checkout-data-totals-information-interface":{"type":"object","description":"Interface TotalsInformationInterface","properties":{"address":{"$ref":"#/definitions/quote-data-address-interface"},"shipping_method_code":{"type":"string","description":"Shipping method code"},"shipping_carrier_code":{"type":"string","description":"Carrier code"},"extension_attributes":{"$ref":"#/definitions/checkout-data-totals-information-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["address"]},"checkout-data-totals-information-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Checkout\\Api\\Data\\TotalsInformationInterface"},"checkout-agreements-data-agreement-interface":{"type":"object","description":"Interface AgreementInterface","properties":{"agreement_id":{"type":"integer","description":"Agreement ID."},"name":{"type":"string","description":"Agreement name."},"content":{"type":"string","description":"Agreement content."},"content_height":{"type":"string","description":"Agreement content height. Otherwise, null."},"checkbox_text":{"type":"string","description":"Agreement checkbox text."},"is_active":{"type":"boolean","description":"Agreement status."},"is_html":{"type":"boolean","description":"* true - HTML. * false - plain text."},"mode":{"type":"integer","description":"The agreement applied mode."},"extension_attributes":{"$ref":"#/definitions/checkout-agreements-data-agreement-extension-interface"}},"required":["agreement_id","name","content","checkbox_text","is_active","is_html","mode"]},"checkout-agreements-data-agreement-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\CheckoutAgreements\\Api\\Data\\AgreementInterface"},"gift-card-account-data-gift-card-account-interface":{"type":"object","description":"Gift Card Account data","properties":{"gift_cards":{"type":"array","description":"Cards codes","items":{"type":"string"}},"gift_cards_amount":{"type":"number","description":"Cards amount in quote currency"},"base_gift_cards_amount":{"type":"number","description":"Cards amount in base currency"},"gift_cards_amount_used":{"type":"number","description":"Cards amount used in quote currency"},"base_gift_cards_amount_used":{"type":"number","description":"Cards amount used in base currency"},"extension_attributes":{"$ref":"#/definitions/gift-card-account-data-gift-card-account-extension-interface"}},"required":["gift_cards","gift_cards_amount","base_gift_cards_amount","gift_cards_amount_used","base_gift_cards_amount_used"]},"gift-card-account-data-gift-card-account-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\GiftCardAccount\\Api\\Data\\GiftCardAccountInterface"},"tax-data-tax-rate-interface":{"type":"object","description":"Tax rate interface.","properties":{"id":{"type":"integer","description":"Id"},"tax_country_id":{"type":"string","description":"Country id"},"tax_region_id":{"type":"integer","description":"Region id"},"region_name":{"type":"string","description":"Region name"},"tax_postcode":{"type":"string","description":"Postcode"},"zip_is_range":{"type":"integer","description":"Zip is range"},"zip_from":{"type":"integer","description":"Zip range from"},"zip_to":{"type":"integer","description":"Zip range to"},"rate":{"type":"number","description":"Tax rate in percentage"},"code":{"type":"string","description":"Tax rate code"},"titles":{"type":"array","description":"Tax rate titles","items":{"$ref":"#/definitions/tax-data-tax-rate-title-interface"}},"extension_attributes":{"$ref":"#/definitions/tax-data-tax-rate-extension-interface"}},"required":["tax_country_id","rate","code"]},"tax-data-tax-rate-title-interface":{"type":"object","description":"Tax rate title interface.","properties":{"store_id":{"type":"string","description":"Store id"},"value":{"type":"string","description":"Title value"},"extension_attributes":{"$ref":"#/definitions/tax-data-tax-rate-title-extension-interface"}},"required":["store_id","value"]},"tax-data-tax-rate-title-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\TaxRateTitleInterface"},"tax-data-tax-rate-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\TaxRateInterface"},"tax-data-tax-rate-search-results-interface":{"type":"object","description":"Interface for tax rate search results.","properties":{"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/tax-data-tax-rate-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"tax-data-tax-rule-interface":{"type":"object","description":"Tax rule interface.","properties":{"id":{"type":"integer","description":"Id"},"code":{"type":"string","description":"Tax rule code"},"priority":{"type":"integer","description":"Priority"},"position":{"type":"integer","description":"Sort order."},"customer_tax_class_ids":{"type":"array","description":"Customer tax class id","items":{"type":"integer"}},"product_tax_class_ids":{"type":"array","description":"Product tax class id","items":{"type":"integer"}},"tax_rate_ids":{"type":"array","description":"Tax rate ids","items":{"type":"integer"}},"calculate_subtotal":{"type":"boolean","description":"Calculate subtotal."},"extension_attributes":{"$ref":"#/definitions/tax-data-tax-rule-extension-interface"}},"required":["code","priority","position","customer_tax_class_ids","product_tax_class_ids","tax_rate_ids"]},"tax-data-tax-rule-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\TaxRuleInterface"},"tax-data-tax-rule-search-results-interface":{"type":"object","description":"Interface for tax rule search results.","properties":{"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/tax-data-tax-rule-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"tax-data-tax-class-interface":{"type":"object","description":"Tax class interface.","properties":{"class_id":{"type":"integer","description":"Tax class ID."},"class_name":{"type":"string","description":"Tax class name."},"class_type":{"type":"string","description":"Tax class type."},"extension_attributes":{"$ref":"#/definitions/tax-data-tax-class-extension-interface"}},"required":["class_name","class_type"]},"tax-data-tax-class-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Tax\\Api\\Data\\TaxClassInterface"},"tax-data-tax-class-search-results-interface":{"type":"object","description":"Interface for tax class search results.","properties":{"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/tax-data-tax-class-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"gift-wrapping-data-wrapping-interface":{"type":"object","description":"Interface WrappingInterface","properties":{"wrapping_id":{"type":"integer"},"design":{"type":"string"},"status":{"type":"integer"},"base_price":{"type":"number"},"image_name":{"type":"string"},"image_base64_content":{"type":"string"},"base_currency_code":{"type":"string"},"website_ids":{"type":"array","items":{"type":"integer"}},"image_url":{"type":"string","description":"Wrapping image URL."},"extension_attributes":{"$ref":"#/definitions/gift-wrapping-data-wrapping-extension-interface"}},"required":["design","status","base_price"]},"gift-wrapping-data-wrapping-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\GiftWrapping\\Api\\Data\\WrappingInterface"},"gift-wrapping-data-wrapping-search-results-interface":{"type":"object","description":"Interface WrappingSearchResultsInterface","properties":{"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/gift-wrapping-data-wrapping-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-rule-data-rule-interface":{"type":"object","description":"Interface RuleInterface","properties":{"rule_id":{"type":"integer","description":"Rule id"},"name":{"type":"string","description":"Rule name"},"store_labels":{"type":"array","description":"Display label","items":{"$ref":"#/definitions/sales-rule-data-rule-label-interface"}},"description":{"type":"string","description":"Description"},"website_ids":{"type":"array","description":"A list of websites the rule applies to","items":{"type":"integer"}},"customer_group_ids":{"type":"array","description":"Ids of customer groups that the rule applies to","items":{"type":"integer"}},"from_date":{"type":"string","description":"The start date when the coupon is active"},"to_date":{"type":"string","description":"The end date when the coupon is active"},"uses_per_customer":{"type":"integer","description":"Number of uses per customer"},"is_active":{"type":"boolean","description":"The coupon is active"},"condition":{"$ref":"#/definitions/sales-rule-data-condition-interface"},"action_condition":{"$ref":"#/definitions/sales-rule-data-condition-interface"},"stop_rules_processing":{"type":"boolean","description":"To stop rule processing"},"is_advanced":{"type":"boolean","description":"Is this field needed"},"product_ids":{"type":"array","description":"Product ids","items":{"type":"integer"}},"sort_order":{"type":"integer","description":"Sort order"},"simple_action":{"type":"string","description":"Simple action of the rule"},"discount_amount":{"type":"number","description":"Discount amount"},"discount_qty":{"type":"number","description":"Maximum qty discount is applied"},"discount_step":{"type":"integer","description":"Discount step"},"apply_to_shipping":{"type":"boolean","description":"The rule applies to shipping"},"times_used":{"type":"integer","description":"How many times the rule has been used"},"is_rss":{"type":"boolean","description":"Whether the rule is in RSS"},"coupon_type":{"type":"string","description":"Coupon type"},"use_auto_generation":{"type":"boolean","description":"To auto generate coupon"},"uses_per_coupon":{"type":"integer","description":"Limit of uses per coupon"},"simple_free_shipping":{"type":"string","description":"To grant free shipping"},"extension_attributes":{"$ref":"#/definitions/sales-rule-data-rule-extension-interface"}},"required":["website_ids","customer_group_ids","uses_per_customer","is_active","stop_rules_processing","is_advanced","sort_order","discount_amount","discount_step","apply_to_shipping","times_used","is_rss","coupon_type","use_auto_generation","uses_per_coupon"]},"sales-rule-data-rule-label-interface":{"type":"object","description":"Interface RuleLabelInterface","properties":{"store_id":{"type":"integer","description":"StoreId"},"store_label":{"type":"string","description":"The label for the store"},"extension_attributes":{"$ref":"#/definitions/sales-rule-data-rule-label-extension-interface"}},"required":["store_id","store_label"]},"sales-rule-data-rule-label-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\SalesRule\\Api\\Data\\RuleLabelInterface"},"sales-rule-data-condition-interface":{"type":"object","description":"Interface ConditionInterface","properties":{"condition_type":{"type":"string","description":"Condition type"},"conditions":{"type":"array","description":"List of conditions","items":{"$ref":"#/definitions/sales-rule-data-condition-interface"}},"aggregator_type":{"type":"string","description":"The aggregator type"},"operator":{"type":"string","description":"The operator of the condition"},"attribute_name":{"type":"string","description":"The attribute name of the condition"},"value":{"type":"string","description":"The value of the condition"},"extension_attributes":{"$ref":"#/definitions/sales-rule-data-condition-extension-interface"}},"required":["condition_type","operator","value"]},"sales-rule-data-condition-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\SalesRule\\Api\\Data\\ConditionInterface"},"sales-rule-data-rule-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\SalesRule\\Api\\Data\\RuleInterface","properties":{"reward_points_delta":{"type":"integer"}}},"sales-rule-data-rule-search-result-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Rules.","items":{"$ref":"#/definitions/sales-rule-data-rule-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-rule-data-coupon-interface":{"type":"object","description":"Interface CouponInterface","properties":{"coupon_id":{"type":"integer","description":"Coupon id"},"rule_id":{"type":"integer","description":"The id of the rule associated with the coupon"},"code":{"type":"string","description":"Coupon code"},"usage_limit":{"type":"integer","description":"Usage limit"},"usage_per_customer":{"type":"integer","description":"Usage limit per customer"},"times_used":{"type":"integer","description":"The number of times the coupon has been used"},"expiration_date":{"type":"string","description":"Expiration date"},"is_primary":{"type":"boolean","description":"The coupon is primary coupon for the rule that it's associated with"},"created_at":{"type":"string","description":"When the coupon is created"},"type":{"type":"integer","description":"Of coupon"},"extension_attributes":{"$ref":"#/definitions/sales-rule-data-coupon-extension-interface"}},"required":["rule_id","times_used","is_primary"]},"sales-rule-data-coupon-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\SalesRule\\Api\\Data\\CouponInterface"},"sales-rule-data-coupon-search-result-interface":{"type":"object","description":"","properties":{"items":{"type":"array","description":"Rules.","items":{"$ref":"#/definitions/sales-rule-data-coupon-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"sales-rule-data-coupon-generation-spec-interface":{"type":"object","description":"CouponGenerationSpecInterface","properties":{"rule_id":{"type":"integer","description":"The id of the rule associated with the coupon"},"format":{"type":"string","description":"Format of generated coupon code"},"quantity":{"type":"integer","description":"Of coupons to generate"},"length":{"type":"integer","description":"Length of coupon code"},"prefix":{"type":"string","description":"The prefix"},"suffix":{"type":"string","description":"The suffix"},"delimiter_at_every":{"type":"integer","description":"The spacing where the delimiter should exist"},"delimiter":{"type":"string","description":"The delimiter"},"extension_attributes":{"$ref":"#/definitions/sales-rule-data-coupon-generation-spec-extension-interface"}},"required":["rule_id","format","quantity","length"]},"sales-rule-data-coupon-generation-spec-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\SalesRule\\Api\\Data\\CouponGenerationSpecInterface"},"sales-rule-data-coupon-mass-delete-result-interface":{"type":"object","description":"Coupon mass delete results interface.","properties":{"failed_items":{"type":"array","description":"List of failed items.","items":{"type":"string"}},"missing_items":{"type":"array","description":"List of missing items.","items":{"type":"string"}}},"required":["failed_items","missing_items"]},"rma-data-track-interface":{"type":"object","description":"Interface TrackInterface","properties":{"entity_id":{"type":"integer","description":"Entity id"},"rma_entity_id":{"type":"integer","description":"Rma entity id"},"track_number":{"type":"string","description":"Track number"},"carrier_title":{"type":"string","description":"Carrier title"},"carrier_code":{"type":"string","description":"Carrier code"},"extension_attributes":{"$ref":"#/definitions/rma-data-track-extension-interface"}},"required":["entity_id","rma_entity_id","track_number","carrier_title","carrier_code"]},"rma-data-track-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Rma\\Api\\Data\\TrackInterface"},"rma-data-track-search-result-interface":{"type":"object","description":"Interface TrackSearchResultInterface","properties":{"items":{"type":"array","description":"Rma list","items":{"$ref":"#/definitions/rma-data-track-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"rma-data-rma-interface":{"type":"object","description":"Interface RmaInterface","properties":{"increment_id":{"type":"string","description":"Entity_id"},"entity_id":{"type":"integer","description":"Entity_id"},"order_id":{"type":"integer","description":"Order_id"},"order_increment_id":{"type":"string","description":"Order_increment_id"},"store_id":{"type":"integer","description":"Store_id"},"customer_id":{"type":"integer","description":"Customer_id"},"date_requested":{"type":"string","description":"Date_requested"},"customer_custom_email":{"type":"string","description":"Customer_custom_email"},"items":{"type":"array","description":"Items","items":{"$ref":"#/definitions/rma-data-item-interface"}},"status":{"type":"string","description":"Status"},"comments":{"type":"array","description":"Comments list","items":{"$ref":"#/definitions/rma-data-comment-interface"}},"tracks":{"type":"array","description":"Tracks list","items":{"$ref":"#/definitions/rma-data-track-interface"}},"extension_attributes":{"$ref":"#/definitions/rma-data-rma-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["increment_id","entity_id","order_id","order_increment_id","store_id","customer_id","date_requested","customer_custom_email","items","status","comments","tracks"]},"rma-data-item-interface":{"type":"object","description":"Interface CategoryInterface","properties":{"entity_id":{"type":"integer","description":"Id"},"rma_entity_id":{"type":"integer","description":"RMA id"},"order_item_id":{"type":"integer","description":"Order_item_id"},"qty_requested":{"type":"integer","description":"Qty_requested"},"qty_authorized":{"type":"integer","description":"Qty_authorized"},"qty_approved":{"type":"integer","description":"Qty_approved"},"qty_returned":{"type":"integer","description":"Qty_returned"},"reason":{"type":"string","description":"Reason"},"condition":{"type":"string","description":"Condition"},"resolution":{"type":"string","description":"Resolution"},"status":{"type":"string","description":"Status"},"extension_attributes":{"$ref":"#/definitions/rma-data-item-extension-interface"}},"required":["entity_id","rma_entity_id","order_item_id","qty_requested","qty_authorized","qty_approved","qty_returned","reason","condition","resolution","status"]},"rma-data-item-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Rma\\Api\\Data\\ItemInterface"},"rma-data-comment-interface":{"type":"object","description":"Interface CommentInterface","properties":{"comment":{"type":"string","description":"Comment"},"rma_entity_id":{"type":"integer","description":"Rma Id"},"created_at":{"type":"string","description":"Created_at"},"entity_id":{"type":"integer","description":"Entity_id"},"customer_notified":{"type":"boolean","description":"Is_customer_notified"},"visible_on_front":{"type":"boolean","description":"Is_visible_on_front"},"status":{"type":"string","description":"Status"},"admin":{"type":"boolean","description":"Is_admin"},"extension_attributes":{"$ref":"#/definitions/rma-data-comment-extension-interface"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["comment","rma_entity_id","created_at","entity_id","customer_notified","visible_on_front","status","admin"]},"rma-data-comment-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Rma\\Api\\Data\\CommentInterface"},"rma-data-rma-extension-interface":{"type":"object","description":"ExtensionInterface class for @see \\Magento\\Rma\\Api\\Data\\RmaInterface"},"rma-data-comment-search-result-interface":{"type":"object","description":"Interface CommentSearchResultInterface","properties":{"items":{"type":"array","description":"Rma Status History list","items":{"$ref":"#/definitions/rma-data-comment-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"rma-data-rma-search-result-interface":{"type":"object","description":"Interface RmaSearchResultInterface","properties":{"items":{"type":"array","description":"Rma list","items":{"$ref":"#/definitions/rma-data-rma-interface"}},"search_criteria":{"$ref":"#/definitions/framework-search-criteria-interface"},"total_count":{"type":"integer","description":"Total count."}},"required":["items","search_criteria","total_count"]},"framework-metadata-object-interface":{"type":"object","description":"Provides metadata about an attribute.","properties":{"attribute_code":{"type":"string","description":"Code of the attribute."}},"required":["attribute_code"]},"test-module1-v1-entity-item":{"type":"object","description":"","properties":{"item_id":{"type":"integer"},"name":{"type":"string"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["item_id","name"]},"test-module1-v2-entity-item":{"type":"object","description":"","properties":{"id":{"type":"integer"},"name":{"type":"string"},"price":{"type":"string"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["id","name","price"]},"test-module2-v1-entity-item":{"type":"object","description":"","properties":{"id":{"type":"integer"},"name":{"type":"string"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["id","name"]},"test-module3-v1-entity-parameter":{"type":"object","description":"","properties":{"name":{"type":"string","description":"$name"},"value":{"type":"string","description":"$value"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["name","value"]},"test-module3-v1-entity-wrapped-error-parameter":{"type":"object","description":"","properties":{"field_name":{"type":"string","description":"$name"},"value":{"type":"string","description":"$value"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["field_name","value"]},"test-module4-v1-entity-data-object-response":{"type":"object","description":"","properties":{"entity_id":{"type":"integer"},"name":{"type":"string"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["entity_id","name"]},"test-module4-v1-entity-data-object-request":{"type":"object","description":"","properties":{"name":{"type":"string"},"entity_id":{"type":"integer"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["name"]},"test-module4-v1-entity-nested-data-object-request":{"type":"object","description":"","properties":{"details":{"$ref":"#/definitions/test-module4-v1-entity-data-object-request"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["details"]},"test-module4-v1-entity-extensible-request-interface":{"type":"object","description":"","properties":{"name":{"type":"string"},"entity_id":{"type":"integer"}},"required":["name"]},"test-module5-v1-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object short description. Data Object long multi line description.","properties":{"entity_id":{"type":"integer","description":"Item ID"},"name":{"type":"string","description":"Item name"},"enabled":{"type":"boolean","description":"If entity is enabled"},"orders":{"type":"boolean","description":"If current entity has a property defined"},"custom_attributes":{"type":"array","description":"Custom attributes values.","items":{"$ref":"#/definitions/framework-attribute-interface"}}},"required":["entity_id","enabled","orders"]},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object short description. Data Object long multi line description.","properties":{"price":{"type":"integer"}},"required":["price"]},"test-module-ms-cdata-item-interface":{"type":"object","description":"","properties":{"item_id":{"type":"integer"},"name":{"type":"string"}},"required":["item_id","name"]}}} \ No newline at end of file diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/definition.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/definition.mustache deleted file mode 100644 index e61212219..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/definition.mustache +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../DataGenerator/etc/dataOperation.xsd"> - <operation name="{{ operationName }}" dataType="{{ operationDataType }}" type="{{ operationType }}"> - {{> field2 }} - {{> array1 }} - </operation> -</config> \ No newline at end of file diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/operation.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/operation.mustache deleted file mode 100644 index 5114f233a..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/operation.mustache +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - /** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../DataGenerator/etc/dataOperation.xsd"> - <operation name="{{ operationName }}" dataType="{{ operationDataType }}" type="{{ operationType }}" auth="{{ auth }}" url="{{ operationUrl }}" method="{{ method }}"> - <contentType>application/json</contentType> - {{> field }} - {{> param }} - {{> array }} - </operation> -</config> \ No newline at end of file diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array1.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array1.mustache deleted file mode 100644 index 3669c78d0..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array1.mustache +++ /dev/null @@ -1,12 +0,0 @@ -{{! -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# arrays1 }} -<array key="{{ arrayKey }}"> - {{> value }} - {{> arrays2 }} -</array> -{{/ arrays1 }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array2.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array2.mustache deleted file mode 100644 index 072b430fb..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array2.mustache +++ /dev/null @@ -1,12 +0,0 @@ -{{! -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# arrays2 }} -<array key="{{ arrayKey }}"> - {{> value }} - {{> arrays3 }} -</array> -{{/ arrays2 }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array3.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array3.mustache deleted file mode 100644 index 401dbbcbd..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/array3.mustache +++ /dev/null @@ -1,12 +0,0 @@ -{{! -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{! No array is nested more than 2 level in Magento2 swagger spec. }} -{{# arrays3 }} -<array key="{{ arrayKey }}"> - {{> value }} -</array> -{{/ arrays3 }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field.mustache deleted file mode 100644 index 29a822d05..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field.mustache +++ /dev/null @@ -1,9 +0,0 @@ -{{! -/** - * Copyright ? Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# fields }} -<field key="{{ fieldName }}" required="{{ isRequired }}">{{ fieldType }}</field> -{{/ fields }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field2.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field2.mustache deleted file mode 100644 index bf4f6c2a5..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/field2.mustache +++ /dev/null @@ -1,9 +0,0 @@ -{{! -/** - * Copyright ? Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# fields }} -<field key="{{ fieldName }}">{{ fieldType }}</field> -{{/ fields }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/param.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/param.mustache deleted file mode 100644 index be5f4a3ef..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/param.mustache +++ /dev/null @@ -1,9 +0,0 @@ -{{! -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# params }} -<param key="{{ paramName }}">{{ paramType }}</param> -{{/ params }} \ No newline at end of file diff --git a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/value.mustache b/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/value.mustache deleted file mode 100644 index def0c03ff..000000000 --- a/src/Magento/FunctionalTestingFramework/Util/MetadataGenerator/Swagger/views/partials/value.mustache +++ /dev/null @@ -1,9 +0,0 @@ -{{! -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -}} -{{# values }} -<value>{{ value }}</value> -{{/ values }} diff --git a/src/Magento/FunctionalTestingFramework/Util/MftfGlobals.php b/src/Magento/FunctionalTestingFramework/Util/MftfGlobals.php new file mode 100644 index 000000000..d59df5c11 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Util/MftfGlobals.php @@ -0,0 +1,160 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Util; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; + +/** + * MFTF Globals + */ +class MftfGlobals +{ + /** + * Magento Base URL + * + * @var string null + */ + private static $baseUrl = null; + + /** + * Magento Backend Base URL + * + * @var string null + */ + private static $backendBaseUrl = null; + + /** + * Magento Web API Base URL + * + * @var string null + */ + private static $webApiBaseUrl = null; + + /** + * Returns Magento Base URL + * + * @param boolean $withTrailingSeparator + * @return string + * @throws TestFrameworkException + */ + public static function getBaseUrl($withTrailingSeparator = true) + { + if (!self::$baseUrl) { + try { + $url = getenv('MAGENTO_BASE_URL'); + if ($url) { + self::$baseUrl = UrlFormatter::format($url, false); + } + } catch (TestFrameworkException $e) { + } + } + + if (self::$baseUrl) { + return UrlFormatter::format(self::$baseUrl, $withTrailingSeparator); + } + + throw new TestFrameworkException( + 'Unable to retrieve Magento Base URL. Please check .env and set:' + . PHP_EOL + . '"MAGENTO_BASE_URL"' + ); + } + + /** + * Return Magento Backend Base URL + * + * @param boolean $withTrailingSeparator + * @return string + * @throws TestFrameworkException + */ + public static function getBackendBaseUrl($withTrailingSeparator = true) + { + if (!self::$backendBaseUrl) { + try { + $bUrl = getenv('MAGENTO_BACKEND_BASE_URL'); + if ($bUrl) { + self::$backendBaseUrl = UrlFormatter::format($bUrl, false); + } else { + $baseUrl = getenv('MAGENTO_BASE_URL'); + $backendName = getenv('MAGENTO_BACKEND_NAME'); + if ($baseUrl && $backendName) { + self::$backendBaseUrl = UrlFormatter::format( + UrlFormatter::format($baseUrl) . $backendName, + false + ); + } + } + } catch (TestFrameworkException $e) { + } + } + + if (self::$backendBaseUrl) { + return UrlFormatter::format(self::$backendBaseUrl, $withTrailingSeparator); + } + + throw new TestFrameworkException( + 'Unable to retrieve Magento Backend Base URL. Please check .env and set either:' + . PHP_EOL + . '"MAGENTO_BASE_URL" and "MAGENTO_BACKEND_NAME"' + . PHP_EOL + . 'or' + . PHP_EOL + . '"MAGENTO_BACKEND_BASE_URL"' + ); + } + + /** + * Return Web API Base URL + * + * @param boolean $withTrailingSeparator + * @return string + * @throws TestFrameworkException + */ + public static function getWebApiBaseUrl($withTrailingSeparator = true) + { + if (!self::$webApiBaseUrl) { + try { + $webapiHost = getenv('MAGENTO_RESTAPI_SERVER_HOST'); + $webapiPort = getenv("MAGENTO_RESTAPI_SERVER_PORT"); + $webapiProtocol = getenv("MAGENTO_RESTAPI_SERVER_PROTOCOL"); + + if ($webapiHost && $webapiProtocol) { + $baseUrl = UrlFormatter::format( + sprintf('%s://%s', $webapiProtocol, $webapiHost), + false + ); + } elseif ($webapiHost) { + $baseUrl = UrlFormatter::format($webapiHost, false); + } + + if (!isset($baseUrl)) { + $baseUrl = MftfGlobals::getBaseUrl(false); + } + + if ($webapiPort) { + $baseUrl .= ':' . $webapiPort; + } + + self::$webApiBaseUrl = $baseUrl . '/rest'; + } catch (TestFrameworkException $e) { + } + } + if (self::$webApiBaseUrl) { + return UrlFormatter::format(self::$webApiBaseUrl, $withTrailingSeparator); + } + throw new TestFrameworkException( + 'Unable to retrieve Magento Web API Base URL. Please check .env and set either:' + . PHP_EOL + . '"MAGENTO_BASE_URL"' + . PHP_EOL + . 'or' + . PHP_EOL + . '"MAGENTO_RESTAPI_SERVER_HOST"' + ); + } +} diff --git a/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php b/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php index 80b556f9a..b7386a586 100644 --- a/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Util/ModulePathExtractor.php @@ -90,7 +90,7 @@ private function extractKeyByPath($path) } foreach ($this->testModulePaths as $key => $value) { - if ($value == $shortenedPath) { + if (substr($path, 0, strlen($value)) == $value) { return $key; } } diff --git a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php index aa9a08ddb..ecdf19613 100644 --- a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php +++ b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver.php @@ -11,7 +11,9 @@ use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; -use Symfony\Component\HttpFoundation\Response; +use Magento\FunctionalTestingFramework\DataTransport\Auth\WebApiAuth; +use \Magento\FunctionalTestingFramework\Util\ModuleResolver\AlphabeticSequenceSorter; +use \Magento\FunctionalTestingFramework\Util\ModuleResolver\SequenceSorterInterface; /** * Class ModuleResolver, resolve module path based on enabled modules of target Magento instance. @@ -23,9 +25,9 @@ class ModuleResolver { /** - * Environment field name for module whitelist. + * Environment field name for module allowlist. */ - const MODULE_WHITELIST = 'MODULE_WHITELIST'; + const MODULE_ALLOWLIST = 'MODULE_ALLOWLIST'; /** * Environment field name for custom module paths. @@ -54,12 +56,6 @@ class ModuleResolver . 'tests' . DIRECTORY_SEPARATOR . 'functional'; - const DEPRECATED_DEV_TESTS = DIRECTORY_SEPARATOR - . self:: DEV_TESTS - . DIRECTORY_SEPARATOR - . "Magento" - . DIRECTORY_SEPARATOR - . "FunctionalTest"; /** * Enabled modules. @@ -136,7 +132,7 @@ class ModuleResolver * * @var array */ - protected $moduleBlacklist = [ + protected $moduleBlocklist = [ 'SampleTests', 'SampleTemplates' ]; @@ -180,9 +176,12 @@ public static function getInstance() private function __construct() { $objectManager = \Magento\FunctionalTestingFramework\ObjectManagerFactory::getObjectManager(); - $this->sequenceSorter = $objectManager->get( - \Magento\FunctionalTestingFramework\Util\ModuleResolver\SequenceSorterInterface::class - ); + + if (MftfApplicationConfig::getConfig()->getPhase() == MftfApplicationConfig::UNIT_TEST_PHASE) { + $this->sequenceSorter = $objectManager->get(AlphabeticSequenceSorter::class); + } else { + $this->sequenceSorter = $objectManager->get(SequenceSorterInterface::class); + } } /** @@ -201,7 +200,7 @@ public function getEnabledModules() $this->printMagentoVersionInfo(); } - $token = $this->getAdminToken(); + $token = WebApiAuth::getAdminToken(); $url = UrlFormatter::format(getenv('MAGENTO_BASE_URL')) . $this->moduleUrl; @@ -271,7 +270,7 @@ public function getModulesPath($verbosePath = false) return $this->enabledModulePaths; } - $enabledModules = array_merge($this->getEnabledModules(), $this->getModuleWhitelist()); + $enabledModules = array_merge($this->getEnabledModules(), $this->getModuleAllowlist()); $enabledDirectoryPaths = $this->flipAndFilterModulePathsArray($allModulePaths, $enabledModules); $this->enabledModulePaths = $this->applyCustomModuleMethods($enabledDirectoryPaths); @@ -290,18 +289,18 @@ public function sortFilesByModuleSequence(array $files) } /** - * Return an array of module whitelist that not exist in target Magento instance. + * Return an array of module allowlist that not exist in target Magento instance. * * @return array */ - protected function getModuleWhitelist() + protected function getModuleAllowlist() { - $moduleWhitelist = getenv(self::MODULE_WHITELIST); + $moduleAllowlist = getenv(self::MODULE_ALLOWLIST); - if (empty($moduleWhitelist)) { + if (empty($moduleAllowlist)) { return []; } - return array_map('trim', explode(',', $moduleWhitelist)); + return array_map('trim', explode(',', $moduleAllowlist)); } /** @@ -321,15 +320,16 @@ private function aggregateTestModulePaths() $modulePath = defined('TESTS_MODULE_PATH') ? TESTS_MODULE_PATH : TESTS_BP; $modulePath = FilePathFormatter::format($modulePath, false); + // If $modulePath is DEV_TESTS path, we don't need to search by pattern + if (strpos($modulePath, self::DEV_TESTS) === false) { + $codePathsToPattern[$modulePath] = ''; + } + $vendorCodePath = DIRECTORY_SEPARATOR . self::VENDOR; - $appCodePath = DIRECTORY_SEPARATOR . self::APP_CODE; + $codePathsToPattern[$magentoBaseCodePath . $vendorCodePath] = self::TEST_MFTF_PATTERN; - $codePathsToPattern = [ - $modulePath => '', - $magentoBaseCodePath . $vendorCodePath => self::TEST_MFTF_PATTERN, - $magentoBaseCodePath . $appCodePath => self::TEST_MFTF_PATTERN, - $magentoBaseCodePath . self::DEPRECATED_DEV_TESTS => '' - ]; + $appCodePath = DIRECTORY_SEPARATOR . self::APP_CODE; + $codePathsToPattern[$magentoBaseCodePath . $appCodePath] = self::TEST_MFTF_PATTERN; foreach ($codePathsToPattern as $codePath => $pattern) { $allModulePaths = array_merge_recursive($allModulePaths, $this->globRelevantPaths($codePath, $pattern)); @@ -374,22 +374,6 @@ private function globRelevantPaths($testPath, $pattern) } } - /* TODO uncomment this to show deprecation warning when we ready to fully deliver test packaging feature - if (strpos($testPath, self::DEPRECATED_DEV_TESTS) !== false && !empty($modulePaths)) { - $deprecatedPath = ltrim(self::DEPRECATED_DEV_TESTS, DIRECTORY_SEPARATOR); - $suggestedPath = self::DEV_TESTS . DIRECTORY_SEPARATOR . 'Magento'; - $message = "DEPRECATION: Found MFTF test modules in the deprecated path: $deprecatedPath." - . " Move these test modules to $suggestedPath."; - - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->warning($message); - } - // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE) { - print ("\n$message\n\n"); - } - } - */ return $modulePaths; } @@ -556,10 +540,10 @@ private function flipAndSortModulePathsArray($objectArray, $sort, $inFlippedArra foreach ($objectArray as $path => $modules) { if (is_array($modules) && count($modules) > 1) { // The "one path => many module names" case is designed to be strictly used when it's - // impossible to write tests in dedicated modules. Due to performance consideration and there - // is no real usage of this currently, we will use the first module name for the path. - // TODO: consider saving all module names if this information is needed in the future. - $module = $modules[0]; + // impossible to write tests in dedicated modules. + // For now we will set module name based on path. + // TODO: Consider saving all module names if this information is needed in the future. + $module = $this->findVendorAndModuleNameFromPath($path); } elseif (is_array($modules)) { if (strpos($modules[0], '_') === false) { $module = $this->findVendorNameFromPath($path) . '_' . $modules[0]; @@ -701,66 +685,6 @@ private function printMagentoVersionInfo() ); } - /** - * Get the API token for admin. - * - * @return string|boolean - */ - public function getAdminToken() - { - $login = $_ENV['MAGENTO_ADMIN_USERNAME'] ?? null; - $password = $_ENV['MAGENTO_ADMIN_PASSWORD'] ?? null; - if (!$login || !$password || !$this->getBackendUrl()) { - $message = "Cannot retrieve API token without credentials and base url, please fill out .env."; - $context = [ - "MAGENTO_BASE_URL" => getenv("MAGENTO_BASE_URL"), - "MAGENTO_BACKEND_BASE_URL" => getenv("MAGENTO_BACKEND_BASE_URL"), - "MAGENTO_ADMIN_USERNAME" => getenv("MAGENTO_ADMIN_USERNAME"), - "MAGENTO_ADMIN_PASSWORD" => getenv("MAGENTO_ADMIN_PASSWORD"), - ]; - throw new TestFrameworkException($message, $context); - } - - $url = $this->getBackendUrl() . $this->adminTokenUrl; - $data = [ - 'username' => $login, - 'password' => $password - ]; - $headers = [ - 'Content-Type: application/json', - ]; - - $ch = curl_init($url); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - - $response = curl_exec($ch); - $responseCode = curl_getinfo($ch)['http_code']; - - if ($responseCode !== 200) { - if ($responseCode == 0) { - $details = "Could not find Magento Backend Instance at MAGENTO_BACKEND_BASE_URL or MAGENTO_BASE_URL"; - } else { - $details = $responseCode . " " . Response::$statusTexts[$responseCode]; - } - - $message = "Could not retrieve API token from Magento Instance ({$details})"; - $context = [ - "tokenUrl" => $url, - "responseCode" => $responseCode, - "MAGENTO_ADMIN_USERNAME" => getenv("MAGENTO_ADMIN_USERNAME"), - "MAGENTO_ADMIN_PASSWORD" => getenv("MAGENTO_ADMIN_PASSWORD"), - ]; - throw new TestFrameworkException($message, $context); - } - - return json_decode($response); - } - /** * A wrapping method for any custom logic which needs to be applied to the module list * @@ -769,7 +693,7 @@ public function getAdminToken() */ protected function applyCustomModuleMethods($modulesPath) { - $modulePathsResult = $this->removeBlacklistModules($modulesPath); + $modulePathsResult = $this->removeBlocklistModules($modulesPath); $customModulePaths = $this->getCustomModulePaths(); array_map(function ($key, $value) { @@ -786,17 +710,17 @@ protected function applyCustomModuleMethods($modulesPath) } /** - * Remove blacklist modules from input module paths. + * Remove blocklist modules from input module paths. * * @param array $modulePaths * @return string[] */ - private function removeBlacklistModules($modulePaths) + private function removeBlocklistModules($modulePaths) { $modulePathsResult = $modulePaths; foreach ($modulePathsResult as $moduleName => $modulePath) { - // Remove module if it is in blacklist - if (in_array($moduleName, $this->getModuleBlacklist())) { + // Remove module if it is in blocklist + if (in_array($moduleName, $this->getModuleBlocklist())) { unset($modulePathsResult[$moduleName]); LoggingUtil::getInstance()->getLogger(ModuleResolver::class)->info( "excluding module", @@ -830,13 +754,13 @@ private function getCustomModulePaths() } /** - * Getter for moduleBlacklist. + * Getter for moduleBlocklist. * * @return string[] */ - private function getModuleBlacklist() + private function getModuleBlocklist() { - return $this->moduleBlacklist; + return $this->moduleBlocklist; } /** @@ -883,23 +807,6 @@ private function getRegisteredModuleList() return []; } - /** - * Returns custom Backend URL if set, fallback to Magento Base URL - * @return string|null - */ - private function getBackendUrl() - { - try { - if (getenv('MAGENTO_BACKEND_BASE_URL')) { - return UrlFormatter::format(getenv('MAGENTO_BACKEND_BASE_URL')); - } else { - return UrlFormatter::format(getenv('MAGENTO_BASE_URL')); - } - } catch (TestFrameworkException $e) { - return null; - } - } - /** * Find vendor and module name from path * diff --git a/src/Magento/FunctionalTestingFramework/Util/ModuleResolver/AlphabeticSequenceSorter.php b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver/AlphabeticSequenceSorter.php new file mode 100644 index 000000000..67e909062 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Util/ModuleResolver/AlphabeticSequenceSorter.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Util\ModuleResolver; + +/** + * Alphabetic sequence sorter. + */ +class AlphabeticSequenceSorter implements SequenceSorterInterface +{ + /** + * Sort files alphabetically. + * + * @param array $paths + * @return array + */ + public function sort(array $paths) + { + asort($paths); + return $paths; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Util/Path/UrlFormatter.php b/src/Magento/FunctionalTestingFramework/Util/Path/UrlFormatter.php index 2ff1e430b..c7b60b6ab 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Path/UrlFormatter.php +++ b/src/Magento/FunctionalTestingFramework/Util/Path/UrlFormatter.php @@ -11,7 +11,7 @@ class UrlFormatter implements FormatterInterface { /** - * Return formatted url path from input string, or false on error + * Return formatted url path from input string * * @param string $url * @param boolean $withTrailingSeparator diff --git a/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php b/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php new file mode 100644 index 000000000..14f9c27e0 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Util/Script/ScriptUtil.php @@ -0,0 +1,296 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\FunctionalTestingFramework\Util\Script; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Exceptions\XmlException; +use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; +use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; +use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; +use Symfony\Component\Finder\Finder; +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Magento\FunctionalTestingFramework\Util\ModuleResolver; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; +use Magento\FunctionalTestingFramework\Page\Handlers\PageObjectHandler; +use Magento\FunctionalTestingFramework\Page\Handlers\SectionObjectHandler; +use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; +use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; +use Magento\FunctionalTestingFramework\Util\TestGenerator; + +/** + * ScriptUtil class that contains helper functions for static and upgrade scripts + * + * @package Magento\FunctionalTestingFramework\Util\Script + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ScriptUtil +{ + const ACTIONGROUP_ARGUMENT_REGEX_PATTERN = '/<argument[^\/>]*name="([^"\']*)/'; + const ROOT_SUITE_DIR = 'tests/_suite'; + const DEV_TESTS_DIR = 'dev/tests/acceptance/'; + + /** + * Return all installed Magento module paths + * + * @return array + * @throws TestFrameworkException + */ + public function getAllModulePaths() + { + MftfApplicationConfig::create( + true, + MftfApplicationConfig::UNIT_TEST_PHASE, + false, + MftfApplicationConfig::LEVEL_DEFAULT, + true + ); + + return ModuleResolver::getInstance()->getModulesPath(); + } + + /** + * Prints out given errors to file, and returns summary result string + * @param array $errors + * @param string $filePath + * @param string $message + * @return string + */ + public function printErrorsToFile($errors, $filePath, $message) + { + if (empty($errors)) { + return $message . ": No errors found."; + } + + $dirname = dirname($filePath); + if (!file_exists($dirname)) { + mkdir($dirname, 0777, true); + } + + $fileResource = fopen($filePath, 'w'); + + foreach ($errors as $test => $error) { + fwrite($fileResource, $error[0] . PHP_EOL); + } + + fclose($fileResource); + $errorCount = count($errors); + $output = $message . ": Errors found across {$errorCount} file(s). Error details output to {$filePath}"; + + return $output; + } + + /** + * Return all XML files for $scope in given module paths, empty array if no path is valid + * + * @param array $modulePaths + * @param string $scope + * @return Finder|array + */ + public function getModuleXmlFilesByScope($modulePaths, $scope) + { + $found = false; + $scopePath = DIRECTORY_SEPARATOR . ucfirst($scope) . DIRECTORY_SEPARATOR; + $finder = new Finder(); + + foreach ($modulePaths as $modulePath) { + if (!realpath($modulePath . $scopePath)) { + continue; + } + $finder->files()->followLinks()->in($modulePath . $scopePath)->name("*.xml"); + $found = true; + } + return $found ? $finder->files() : []; + } + + /** + * Return suite XML files in TESTS_BP/ROOT_SUITE_DIR directory + * + * @return Finder|array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getRootSuiteXmlFiles() + { + $rootSuitePaths = []; + $defaultTestPath = null; + $devTestsPath = null; + + try { + $defaultTestPath = FilePathFormatter::format(TESTS_BP); + } catch (TestFrameworkException $e) { + } + + try { + $devTestsPath = FilePathFormatter::format(MAGENTO_BP) . self::DEV_TESTS_DIR; + } catch (TestFrameworkException $e) { + } + + if ($defaultTestPath) { + $rootSuitePaths[] = $defaultTestPath . self::ROOT_SUITE_DIR; + } + + if ($devTestsPath && realpath($devTestsPath) && $devTestsPath !== $defaultTestPath) { + $rootSuitePaths[] = $devTestsPath . self::ROOT_SUITE_DIR; + } + + $found = false; + $finder = new Finder(); + foreach ($rootSuitePaths as $rootSuitePath) { + if (!realpath($rootSuitePath)) { + continue; + } + $finder->files()->followLinks()->in($rootSuitePath)->name("*.xml"); + $found = true; + } + + return $found ? $finder->files() : []; + } + + /** + * Resolve entity reference in {{entity.field}} or {{entity.field('param')}} + * + * @param array $braceReferences + * @param string $contents + * @param boolean $resolveSectionElement + * @return array + * @throws XmlException + */ + public function resolveEntityReferences($braceReferences, $contents, $resolveSectionElement = false) + { + $entities = []; + foreach ($braceReferences as $reference) { + // trim `{{data.field}}` to `data` + preg_match('/{{([^.]+)/', $reference, $entityName); + // Double check that {{data.field}} isn't an argument for an ActionGroup + $entity = $this->findEntity($entityName[1]); + preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $contents, $possibleArgument); + if (array_search($entityName[1], $possibleArgument[1]) !== false) { + continue; + } + if ($entity !== null) { + $entities[$entity->getName()] = $entity; + if ($resolveSectionElement) { + if (get_class($entity) === SectionObject::class) { + // trim `{{data.field}}` to `field` + preg_match('/.([^.]+)}}/', $reference, $elementName); + /** @var ElementObject $element */ + /** @var SectionObject $entity */ + $element = $entity->getElement($elementName[1]); + if ($element) { + $entities[$entity->getName() . '.' . $elementName[1]] = $element; + } + } + } + } + } + return $entities; + } + + /** + * Drill down into params in {{ref.params('string', $data.key$, entity.reference)}} to resolve entity reference + * + * @param array $braceReferences + * @param string $contents + * @param boolean $resolveSectionElement + * @return array + * @throws XmlException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function resolveParametrizedReferences($braceReferences, $contents, $resolveSectionElement = false) + { + $entities = []; + foreach ($braceReferences as $parameterizedReference) { + preg_match( + ActionObject::ACTION_ATTRIBUTE_VARIABLE_REGEX_PARAMETER, + $parameterizedReference, + $arguments + ); + $splitArguments = explode(',', ltrim(rtrim($arguments[0], ")"), "(")); + foreach ($splitArguments as $argument) { + // Do nothing for 'string' or $persisted.data$ + if (preg_match(ActionObject::STRING_PARAMETER_REGEX, $argument)) { + continue; + } elseif (preg_match(TestGenerator::PERSISTED_OBJECT_NOTATION_REGEX, $argument)) { + continue; + } + // trim `data.field` to `data` + preg_match('/([^.]+)/', $argument, $entityName); + // Double check that {{data.field}} isn't an argument for an ActionGroup + $entity = $this->findEntity($entityName[1]); + preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $contents, $possibleArgument); + if (array_search($entityName[1], $possibleArgument[1]) !== false) { + continue; + } + if ($entity !== null) { + $entities[$entity->getName()] = $entity; + if ($resolveSectionElement) { + if (get_class($entity) === SectionObject::class) { + // trim `data.field` to `field` + preg_match('/.([^.]+)/', $argument, $elementName); + /** @var ElementObject $element */ + /** @var SectionObject $entity */ + $element = $entity->getElement($elementName[1]); + if ($element) { + $entities[$entity->getName() . '.' . $elementName[1]] = $element; + } + } + } + } + } + } + return $entities; + } + + /** + * Resolve entity by names + * + * @param array $references + * @return array + * @throws XmlException + */ + public function resolveEntityByNames($references) + { + $entities = []; + foreach ($references as $reference) { + $entity = $this->findEntity($reference); + if ($entity !== null) { + $entities[$entity->getName()] = $entity; + } + } + return $entities; + } + + /** + * Attempts to find any MFTF entity by its name. Returns null if none are found + * + * @param string $name + * @return mixed + * @throws XmlException + */ + public function findEntity($name) + { + if ($name == '_ENV' || $name == '_CREDS') { + return null; + } + + if (DataObjectHandler::getInstance()->getObject($name)) { + return DataObjectHandler::getInstance()->getObject($name); + } elseif (PageObjectHandler::getInstance()->getObject($name)) { + return PageObjectHandler::getInstance()->getObject($name); + } elseif (SectionObjectHandler::getInstance()->getObject($name)) { + return SectionObjectHandler::getInstance()->getObject($name); + } elseif (ActionGroupObjectHandler::getInstance()->getObject($name)) { + return ActionGroupObjectHandler::getInstance()->getObject($name); + } + + try { + return TestObjectHandler::getInstance()->getObject($name); + } catch (TestReferenceException $e) { + } + return null; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Util/Sorter/ParallelGroupSorter.php b/src/Magento/FunctionalTestingFramework/Util/Sorter/ParallelGroupSorter.php index 8f4cac8a2..fa30837cb 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Sorter/ParallelGroupSorter.php +++ b/src/Magento/FunctionalTestingFramework/Util/Sorter/ParallelGroupSorter.php @@ -232,7 +232,7 @@ private function getSuiteToSize($suiteNamesToTests) * * E.g. * Input {suitename = 'sample', tests = ['test1' => 100,'test2' => 150, 'test3' => 300], linelimit = 275} - * Result { ['sample_01' => ['test3' => 300], 'sample_02' => ['test2' => 150, 'test1' => 100]] } + * Result { ['sample_01_G' => ['test3' => 300], 'sample_02_G' => ['test2' => 150, 'test1' => 100]] } * * @param string $suiteName * @param array $tests @@ -252,8 +252,8 @@ private function splitTestSuite($suiteName, $tests, $maxTime) } $group = $this->createTestGroup($maxTime, $test, $size, $availableTests); - $splitSuites["{$suiteName}_${splitCount}"] = $group; - $this->addSuiteToConfig($suiteName, "{$suiteName}_${splitCount}", $group); + $splitSuites["{$suiteName}_${splitCount}_G"] = $group; + $this->addSuiteToConfig($suiteName, "{$suiteName}_${splitCount}_G", $group); $availableTests = array_diff_key($availableTests, $group); $splitCount++; diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 2e7d265fa..8253a75ba 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -25,6 +25,8 @@ use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; +use Mustache_Engine; +use Mustache_Loader_FilesystemLoader; /** * Class TestGenerator @@ -60,7 +62,12 @@ class TestGenerator const ARRAY_WRAP_OPEN = '['; const ARRAY_WRAP_CLOSE = ']'; - const MFTF_3_O_0_DEPRECATION_MESSAGE = ' is DEPRECATED and will be removed in MFTF 3.0.0.'; + /** + * Array with helpers classes and methods. + * + * @var array + */ + private $customHelpers = []; /** * Actor name for AcceptanceTest @@ -270,6 +277,7 @@ public function assembleTestPhp($testObject) $cestPhp .= $classAnnotationsPhp; $cestPhp .= sprintf("class %s\n", $className); $cestPhp .= "{\n"; + $cestPhp .= $this->generateInjectMethod(); $cestPhp .= $hookPhp; $cestPhp .= $testsPhp; $cestPhp .= "}\n"; @@ -277,6 +285,35 @@ public function assembleTestPhp($testObject) return $cestPhp; } + /** + * Generates _injectMethod based on $this->customHelpers. + * + * @return string + */ + private function generateInjectMethod() + { + if (empty($this->customHelpers)) { + return ""; + } + + $mustacheEngine = new Mustache_Engine([ + 'loader' => new Mustache_Loader_FilesystemLoader( + dirname(__DIR__) . DIRECTORY_SEPARATOR . "Helper" . DIRECTORY_SEPARATOR . 'views' + ) + ]); + + $argumentsWithType = []; + $arguments = []; + foreach ($this->customHelpers as $customHelperVar => $customHelperType) { + $argumentsWithType[] = $customHelperType . ' ' . $customHelperVar; + $arguments[] = ['type' => $customHelperType, 'var' => $customHelperVar]; + } + $mustacheData['argumentsWithTypes'] = implode(', ' . PHP_EOL, $argumentsWithType); + $mustacheData['arguments'] = $arguments; + + return $mustacheEngine->render('TestInjectMethod', $mustacheData); + } + /** * Load ALL Test objects. Loop over and pass each to the assembleTestPhp function. * @@ -573,6 +610,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $function = null; $time = null; $locale = null; + $currency = null; $username = null; $password = null; $width = null; @@ -617,7 +655,11 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $sortOrder = $customActionAttributes['sortOrder']; } - if (isset($customActionAttributes['userInput']) && isset($customActionAttributes['url'])) { + if (isset($customActionAttributes['userInput']) + && isset($customActionAttributes['locale']) + && isset($customActionAttributes['currency'])) { + $input = $this->parseUserInput($customActionAttributes['userInput']); + } elseif (isset($customActionAttributes['userInput']) && isset($customActionAttributes['url'])) { $input = $this->addUniquenessFunctionCall($customActionAttributes['userInput']); $url = $this->addUniquenessFunctionCall($customActionAttributes['url']); } elseif (isset($customActionAttributes['userInput'])) { @@ -625,9 +667,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } elseif (isset($customActionAttributes['url'])) { $input = $this->addUniquenessFunctionCall($customActionAttributes['url']); $url = $this->addUniquenessFunctionCall($customActionAttributes['url']); - } elseif (isset($customActionAttributes['expectedValue'])) { - //For old Assert backwards Compatibility, remove when deprecating - $assertExpected = $this->addUniquenessFunctionCall($customActionAttributes['expectedValue']); } elseif (isset($customActionAttributes['regex'])) { $input = $this->addUniquenessFunctionCall($customActionAttributes['regex']); } @@ -719,10 +758,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } if (isset($customActionAttributes['function'])) { - $function = $this->addUniquenessFunctionCall( - $customActionAttributes['function'], - $actionObject->getType() !== "executeInSelenium" - ); + $function = $this->addUniquenessFunctionCall($customActionAttributes['function']); if (in_array($actionObject->getType(), ActionObject::FUNCTION_CLOSURE_ACTIONS)) { // Argument must be a closure function, not a string. $function = trim($function, '"'); @@ -741,6 +777,10 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $locale = $this->wrapWithDoubleQuotes($customActionAttributes['locale']); } + if (isset($customActionAttributes['currency'])) { + $currency = $this->wrapWithDoubleQuotes($customActionAttributes['currency']); + } + if (isset($customActionAttributes['username'])) { $username = $this->wrapWithDoubleQuotes($customActionAttributes['username']); } @@ -782,6 +822,45 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } switch ($actionObject->getType()) { + case "helper": + if (!in_array($customActionAttributes['class'], $this->customHelpers)) { + $this->customHelpers['$' . $stepKey] = $customActionAttributes['class']; + } + + $arguments = []; + $classReader = new \Magento\FunctionalTestingFramework\Helper\Code\ClassReader(); + $parameters = $classReader->getParameters( + $customActionAttributes['class'], + $customActionAttributes['method'] + ); + $errors = []; + foreach ($parameters as $parameter) { + if (array_key_exists($parameter['variableName'], $customActionAttributes)) { + $value = $customActionAttributes[$parameter['variableName']]; + $arguments[] = $this->addUniquenessFunctionCall( + $value, + $parameter['type'] === 'string' || $parameter['type'] === null + ); + } elseif ($parameter['isOptional']) { + $value = $parameter['optionalValue']; + $arguments[] = str_replace(PHP_EOL, '', var_export($value, true)); + } else { + $errors[] = 'Argument \'' . $parameter['variableName'] . '\' for method ' + . $customActionAttributes['class'] . '::' . $customActionAttributes['method'] + . ' is not found.'; + } + } + if (!empty($errors)) { + throw new TestFrameworkException(implode(PHP_EOL, $errors)); + } + $testSteps .= sprintf( + "\t\t$%s->comment('[%s] %s()');" . PHP_EOL, + $actor, + $stepKey, + $customActionAttributes['class'] . '::' . $customActionAttributes['method'] + ); + $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $arguments); + break; case "createData": $entity = $customActionAttributes['entity']; @@ -1011,6 +1090,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato break; case "selectOption": case "unselectOption": + case "seeNumberOfElements": $testSteps .= $this->wrapFunctionCall( $actor, $actionObject, @@ -1048,11 +1128,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $parameterArray ); break; - case "executeInSelenium": - $this->deprecationMessages[] = "DEPRECATED ACTION in Test: at step {$stepKey} 'executeInSelenium'" - . self::MFTF_3_O_0_DEPRECATION_MESSAGE; - $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $function); - break; case "executeJS": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, @@ -1061,17 +1136,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $function ); break; - case "performOn": - $this->deprecationMessages[] = "DEPRECATED ACTION in Test: at step {$stepKey} 'performOn'" - . self::MFTF_3_O_0_DEPRECATION_MESSAGE; - $testSteps .= $this->wrapFunctionCall( - $actor, - $actionObject, - $selector, - $function, - $time - ); - break; case "waitForElementChange": $testSteps .= $this->wrapFunctionCall( $actor, @@ -1108,13 +1172,14 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $selector ); break; - case "formatMoney": + case "formatCurrency": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, $actionObject, $input, - $locale + $locale, + $currency ); break; case "mSetLocale": @@ -1141,6 +1206,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato ); break; case "grabPageSource": + case "getOTP": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, @@ -1190,15 +1256,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato case "seeOptionIsSelected": $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $selector, $input); break; - case "seeNumberOfElements": - $testSteps .= $this->wrapFunctionCall( - $actor, - $actionObject, - $selector, - $input, - $parameterArray - ); - break; case "seeInPageSource": case "dontSeeInPageSource": case "seeInSource": @@ -1218,15 +1275,12 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $visible ); break; - case "assertEquals": case "assertGreaterOrEquals": case "assertGreaterThan": case "assertGreaterThanOrEqual": - case "assertInternalType": case "assertLessOrEquals": case "assertLessThan": case "assertLessThanOrEqual": - case "assertNotEquals": case "assertInstanceOf": case "assertNotInstanceOf": case "assertNotRegExp": @@ -1240,6 +1294,10 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato case "assertCount": case "assertContains": case "assertNotContains": + case "assertStringContainsString": + case "assertStringContainsStringIgnoringCase": + case "assertStringNotContainsString": + case "assertStringNotContainsStringIgnoringCase": case "expectException": $testSteps .= $this->wrapFunctionCall( $actor, @@ -1250,6 +1308,31 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $assertDelta ); break; + case "assertEquals": + case "assertNotEquals": + case "assertEqualsIgnoringCase": + case "assertNotEqualsIgnoringCase": + case "assertEqualsCanonicalizing": + case "assertNotEqualsCanonicalizing": + $testSteps .= $this->wrapFunctionCall( + $actor, + $actionObject, + $assertExpected, + $assertActual, + $assertMessage + ); + break; + case "assertEqualsWithDelta": + case "assertNotEqualsWithDelta": + $testSteps .= $this->wrapFunctionCall( + $actor, + $actionObject, + $assertExpected, + $assertActual, + $assertDelta, + $assertMessage + ); + break; case "assertElementContainsAttribute": // If a blank string or null is passed in we need to pass a blank string to the function. if (empty($assertExpected)) { @@ -1280,16 +1363,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $assertMessage ); break; - case "assertArraySubset": - $testSteps .= $this->wrapFunctionCall( - $actor, - $actionObject, - $assertExpected, - $assertActual, - $assertIsStrict, - $assertMessage - ); - break; case "fail": $testSteps .= $this->wrapFunctionCall( $actor, @@ -1358,9 +1431,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $testSteps .= $dateGenerateCode; break; - case "skipReadinessCheck": - $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $customActionAttributes['state']); - break; case "comment": $input = $input === null ? strtr($value, ['$' => '\$', '{' => '\{', '}' => '\}']) : $input; // Combining userInput from native XML comment and <comment/> action to fall-through 'default' case @@ -1868,7 +1938,15 @@ private function addDollarSign($input) private function wrapFunctionCall($actor, $action, ...$args) { $isFirst = true; - $output = sprintf("\t\t$%s->%s(", $actor, $action->getType()); + $isActionHelper = $action->getType() === 'helper'; + $actionType = $action->getType(); + if ($isActionHelper) { + $actor = "this->helperContainer->get('" . $action->getCustomActionAttributes()['class'] . "')"; + $args = $args[0]; + $actionType = $action->getCustomActionAttributes()['method']; + } + + $output = sprintf("\t\t$%s->%s(", $actor, $actionType); for ($i = 0; $i < count($args); $i++) { if (null === $args[$i]) { continue; @@ -2202,4 +2280,27 @@ private function hasDecimalPoint(string $outStr) { return strpos($outStr, localeconv()['decimal_point']) !== false; } + + /** + * Parse action attribute `userInput` + * + * @param string $userInput + * @return string + */ + private function parseUserInput($userInput) + { + $floatPattern = '/^\s*([+-]?[0-9]*\.?[0-9]+)\s*$/'; + preg_match($floatPattern, $userInput, $float); + if (isset($float[1])) { + return $float[1]; + } + + $intPattern = '/^\s*([+-]?[0-9]+)\s*$/'; + preg_match($intPattern, $userInput, $int); + if (isset($int[1])) { + return $int[1]; + } + + return $this->addUniquenessFunctionCall($userInput); + } } diff --git a/src/Magento/FunctionalTestingFramework/Util/Validation/NameValidationUtil.php b/src/Magento/FunctionalTestingFramework/Util/Validation/NameValidationUtil.php index 60b4660fb..cf9f34164 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Validation/NameValidationUtil.php +++ b/src/Magento/FunctionalTestingFramework/Util/Validation/NameValidationUtil.php @@ -6,14 +6,41 @@ namespace Magento\FunctionalTestingFramework\Util\Validation; +use Exception; use Magento\FunctionalTestingFramework\Exceptions\XmlException; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; class NameValidationUtil { const PHP_CLASS_REGEX_PATTERN = '/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/'; + const DATA_ENTITY_NAME = "data entity name"; + const DATA_ENTITY_KEY = "data entity key"; + const METADATA_OPERATION_NAME = "metadata operation name"; + const PAGE = "Page"; + const SECTION = "Section"; + const SECTION_ELEMENT_NAME = "section element name"; + const ACTION_GROUP_NAME = "action group name"; + const TEST_NAME = "test name"; + + /** + * The number of violations this instance has detected. + * + * @var integer + */ + private $count; + /** - * Function which runs a validation against the blacklisted char defined in this class. Validation occurs to insure + * NameValidationUtil constructor. + * + */ + public function __construct() + { + $this->count = 0; + } + + /** + * Function which runs a validation against the blocklisted char defined in this class. Validation occurs to insure * allure report does not error/future devOps builds do not error against illegal char. * * @param string $name @@ -50,4 +77,110 @@ public static function validateName($name, $type) throw new XmlException($errorMessage); } } + + /** + * Validates that the string is PascalCase. + * + * @param string $str + * @param string $type + * @param string $filename + * @throws Exception + * @return void + */ + public function validatePascalCase($str, $type, $filename = null) + { + if (!is_string($str) || !ctype_upper($str[0])) { + $message = "The {$type} {$str} should be PascalCase with an uppercase first letter."; + + if ($filename !== null) { + $message .= " See file {$filename}."; + } + + LoggingUtil::getInstance()->getLogger(self::class)->notification( + $message, + [], + false + ); + + $this->count++; + } + } + + /** + * Validates that the string is camelCase. + * + * @param string $str + * @param string $type + * @param string $filename + * @throws Exception + * @return void + */ + public function validateCamelCase($str, $type, $filename = null) + { + if (!is_string($str) || !ctype_lower($str[0])) { + $message = "The {$type} {$str} should be camelCase with a lowercase first letter."; + + if ($filename !== null) { + $message .= " See file {$filename}."; + } + + LoggingUtil::getInstance()->getLogger(self::class)->notification( + $message, + [], + false + ); + + $this->count++; + } + } + + /** + * Validates that the string is of the pattern {Admin or Storefront}{Description}{Type}. + * + * @param string $str + * @param string $type + * @param string $filename + * @throws Exception + * @return void + */ + public function validateAffixes($str, $type, $filename = null) + { + $isPrefixAdmin = substr($str, 0, 5) === "Admin"; + $isPrefixStorefront = substr($str, 0, 10) === "Storefront"; + $isSuffixType = substr($str, -strlen($type)) === $type; + + if ((!$isPrefixAdmin && !$isPrefixStorefront) || !$isSuffixType) { + $message = "The {$type} name {$str} should follow the pattern {Admin or Storefront}{Description}{$type}."; + + if ($filename !== null) { + $message .= " See file {$filename}."; + } + + LoggingUtil::getInstance()->getLogger(self::class)->notification( + $message, + [], + false + ); + + $this->count++; + } + } + + /** + * Outputs the number of validations detected by this instance. + * + * @param string $type + * @throws Exception + * @return void + */ + public function summarize($type) + { + if ($this->count > 0) { + LoggingUtil::getInstance()->getLogger(self::class)->notification( + "{$this->count} {$type} violations detected. See mftf.log for details.", + [], + true + ); + } + } } diff --git a/src/Magento/FunctionalTestingFramework/Util/Validation/SingleNodePerFileValidationUtil.php b/src/Magento/FunctionalTestingFramework/Util/Validation/SingleNodePerFileValidationUtil.php new file mode 100644 index 000000000..c560349be --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Util/Validation/SingleNodePerFileValidationUtil.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Util\Validation; + +use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; + +/** + * Class SingleNodePerDocumentValidationUtil + * @package Magento\FunctionalTestingFramework\Util\Validation + */ +class SingleNodePerFileValidationUtil +{ + /** + * ExceptionColletor used to catch errors + * + * @var ExceptionCollector + */ + private $exceptionCollector; + + /** + * SingleNodePerDocumentValidationUtil constructor + * + * @param ExceptionCollector $exceptionCollector + */ + public function __construct($exceptionCollector) + { + $this->exceptionCollector = $exceptionCollector; + } + + /** + * Validate single node per dom document for a given tag name + * + * @param \DOMDocument $dom + * @param string $tag + * @param string $filename + * @return void + */ + public function validateSingleNodeForTag($dom, $tag, $filename = '') + { + $tagNodes = $dom->getElementsByTagName($tag); + $count = $tagNodes->length; + if ($count == 1) { + return; + } + + $errorMsg = "Single <{$tag}> node per xml file. {$count} found in file: {$filename}\n"; + $this->exceptionCollector->addError($filename, $errorMsg); + } +} diff --git a/src/Magento/FunctionalTestingFramework/_bootstrap.php b/src/Magento/FunctionalTestingFramework/_bootstrap.php index a5ce1f931..b655fb28e 100644 --- a/src/Magento/FunctionalTestingFramework/_bootstrap.php +++ b/src/Magento/FunctionalTestingFramework/_bootstrap.php @@ -51,7 +51,10 @@ $env->setEnvironmentVariable('DEFAULT_TIMEZONE', DEFAULT_TIMEZONE); defined('WAIT_TIMEOUT') || define('WAIT_TIMEOUT', 30); - $env->setEnvironmentVariable('WAIT_TIMEOUT', 30); + $env->setEnvironmentVariable('WAIT_TIMEOUT', WAIT_TIMEOUT); + + defined('VERBOSE_ARTIFACTS') || define('VERBOSE_ARTIFACTS', false); + $env->setEnvironmentVariable('VERBOSE_ARTIFACTS', VERBOSE_ARTIFACTS); try { new DateTimeZone(DEFAULT_TIMEZONE); @@ -66,7 +69,7 @@ // define TEST_PATH and TEST_MODULE_PATH defined('TESTS_BP') || define('TESTS_BP', realpath(MAGENTO_BP . DIRECTORY_SEPARATOR . 'dev/tests/acceptance')); -$RELATIVE_TESTS_MODULE_PATH = '/tests/functional/Magento/FunctionalTest'; +$RELATIVE_TESTS_MODULE_PATH = '/tests/functional/Magento'; defined('TESTS_MODULE_PATH') || define( 'TESTS_MODULE_PATH', realpath(TESTS_BP . $RELATIVE_TESTS_MODULE_PATH)