diff --git a/CHANGELOG.md b/CHANGELOG.md index c8c4ca9b8..fe6bd9822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ Magento Functional Testing Framework Changelog ================================================ + +2.6.0 +----- + +* Traceability + * MFTF generated cest files are fully compatible for Codeception `dry-run`. +* Modularity + * `mftf generate:tests` and `mftf run:test` commands now accept suite scoped test names in format `[suitename:testname]...`. +* Maintainability + * Support `deprecated` syntax for the following test entities: + * Test + * Action Group + * Data + * Metadata + * Page + * Section + * Section Element + * See DevDocs for details + * Improved `mftf static-checks` command to allow executing all or specific static checks. + * Added a new static check that checks and reports unused arguments in action groups. +* Customizability + * AWS Secrets Manager has been added as an additional credential storage. + * See DevDocs for details + +### Fixes +* Fixed missing before, after, failed steps in cest file when generating tests with `--allow-skipped` option. +* Fixed suites and tests display issue in Allure `Suites` page after `mftf run:group` command. +* `createData` action now shows a meaningful error message at runtime when the entity does not exist. + +### GitHub Issues/Pull requests: +* [#537](https://github.com/magento/magento2-functional-testing-framework/pull/537) -- Refactor of TestGenerator class +* [#538](https://github.com/magento/magento2-functional-testing-framework/pull/538) -- FEATURE: command to execute Cron Jobs + 2.5.4 ----- [Demo Video](https://www.youtube.com/watch?v=tguvkw1HWKg) diff --git a/composer.json b/composer.json index 158287fbf..e6d081114 100755 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "magento/magento2-functional-testing-framework", "description": "Magento2 Functional Testing Framework", "type": "library", - "version": "2.5.4", + "version": "2.6.0", "license": "AGPL-3.0", "keywords": ["magento", "automation", "functional", "testing"], "config": { @@ -11,7 +11,10 @@ "require": { "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", "ext-curl": "*", + "ext-json": "*", + "ext-openssl": "*", "allure-framework/allure-codeception": "~1.3.0", + "aws/aws-sdk-php": "^3.132", "codeception/codeception": "~2.4.5", "composer/composer": "^1.4", "consolidation/robo": "^1.0.0", diff --git a/composer.lock b/composer.lock index 8f2fcb8e9..051ab6441 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "59e95cc1ae6311e93111bd7ced180d29", + "content-hash": "859ddf6506836faaabb056ae7b377c63", "packages": [ { "name": "allure-framework/allure-codeception", @@ -109,6 +109,90 @@ ], "time": "2016-12-07T12:15:46+00:00" }, + { + "name": "aws/aws-sdk-php", + "version": "3.132.2", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "f890689c6db27625522ea2e7e9b8420b6fccb063" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f890689c6db27625522ea2e7e9b8420b6fccb063", + "reference": "f890689c6db27625522ea2e7e9b8420b6fccb063", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4.1", + "mtdowling/jmespath.php": "^2.5", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "time": "2020-01-09T19:09:31+00:00" + }, { "name": "behat/gherkin", "version": "v4.4.5", @@ -1626,6 +1710,7 @@ "selenium", "webdriver" ], + "abandoned": "php-webdriver/webdriver", "time": "2018-05-16T17:37:13+00:00" }, { @@ -2542,8 +2627,66 @@ "bcmath", "math" ], + "abandoned": "brick/math", "time": "2017-02-16T16:54:46+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.5.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "52168cb9472de06979613d365c7f1ab8798be895" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/52168cb9472de06979613d365c7f1ab8798be895", + "reference": "52168cb9472de06979613d365c7f1ab8798be895", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "symfony/polyfill-mbstring": "^1.4" + }, + "require-dev": { + "composer/xdebug-handler": "^1.2", + "phpunit/phpunit": "^4.8.36|^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "time": "2019-12-30T18:03:34+00:00" + }, { "name": "mustache/mustache", "version": "v2.12.0", @@ -6542,7 +6685,9 @@ "prefer-lowest": false, "platform": { "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", - "ext-curl": "*" + "ext-curl": "*", + "ext-json": "*", + "ext-openssl": "*" }, "platform-dev": [] } diff --git a/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml new file mode 100644 index 000000000..908808a8c --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/ActionGroup/DeprecatedCommentActionGroup.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml new file mode 100644 index 000000000..5835a78af --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/DeprecatedMessageData.xml @@ -0,0 +1,14 @@ + + + + + + Introduction to the Magento Functional Testing Framework + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml b/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml new file mode 100644 index 000000000..eb77e73bc --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Data/MessageData.xml @@ -0,0 +1,14 @@ + + + + + + Introduction to the Magento Functional Testing Framework + + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml b/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml new file mode 100644 index 000000000..ee47fe954 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Page/DeprecatedMFTFDocPage.xml @@ -0,0 +1,14 @@ + + + + + +
+ + diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml b/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml index cf82b69e9..15af0fa39 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Section/ContentSection.xml @@ -10,5 +10,6 @@ xsi:noNamespaceSchemaLocation="../../../../../../../src/Magento/FunctionalTestingFramework/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 new file mode 100644 index 000000000..cc316d6ed --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Section/DeprecatedContentSection.xml @@ -0,0 +1,14 @@ + + + + +
+ +
+
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml new file mode 100644 index 000000000..bf0078df4 --- /dev/null +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DeprecatedDevDocsTest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + <description value="[Deprecated] Magento Functional Testing Framework Documentation is available."/> + <severity value="CRITICAL"/> + <group value="mftf"/> + </annotations> + + <!-- Open MFTF DevDocs Page --> + <amOnPage stepKey="openMFTFDevDocPage" url="{{DeprecatedMFTFDocPage.url}}" /> + <see stepKey="verifyPageIntroText" selector="{{DeprecatedContentSection.pageIntro}}" userInput="{{DeprecatedMessageData.message}}" /> + <actionGroup ref="DeprecatedCommentActionGroup" stepKey="commentActionGroup" /> + </test> +</tests> diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml index 3bdeeb9e8..c6b2575b9 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml @@ -21,6 +21,6 @@ <!-- Open MFTF DevDocs Page --> <amOnPage stepKey="openMFTFDevDocPage" url="{{MFTFDocPage.url}}" /> - <see stepKey="verifyPageIntroText" selector="{{contentSection.pageIntro}}" userInput="Introduction to the Magento Functional Testing Framework" /> + <see stepKey="verifyPageIntroText" selector="{{contentSection.pageIntro}}" userInput="{{MessageData.message}}" /> </test> </tests> diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php index 1b1686ce2..234f677e8 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Console/BaseGenerateCommandTest.php @@ -156,6 +156,24 @@ public function testThreeTestOneSuiteOneGroupMix() $this->assertEquals($expected, $actual); } + public function testSuiteToTestSyntax() + { + $testOne = new TestObject('Test1', [], [], []); + $suiteOne = new SuiteObject( + 'Suite1', + ['Test1' => $testOne], + [], + [] + ); + + $testArray = ['Test1' => $testOne]; + $suiteArray = ['Suite1' => $suiteOne]; + $this->mockHandlers($testArray, $suiteArray); + $actual = json_decode($this->callTestConfig(['Suite1:Test1']), true); + $expected = ['tests' => null, 'suites' => ['Suite1' => ['Test1']]]; + $this->assertEquals($expected, $actual); + } + /** * Mock handlers to skip parsing * @param array $testArray diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php index 6c3823466..592b87f4e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/PersistedObjectHandlerTest.php @@ -32,6 +32,30 @@ public function setUp() TestLoggingUtil::getInstance()->setMockLoggingUtil(); } + public function testCreateEntityWithNonExistingName() + { + // Test Data and Variables + $entityName = "InvalidEntity"; + $entityStepKey = "StepKey"; + $scope = PersistedObjectHandler::TEST_SCOPE; + + $exceptionMessage = "Entity \"" . $entityName . "\" does not exist." . + "\nException occurred executing action at StepKey \"" . $entityStepKey . "\""; + + $this->expectException(TestReferenceException::class); + + $this->expectExceptionMessage($exceptionMessage); + + $handler = PersistedObjectHandler::getInstance(); + + // Call method + $handler->createEntity( + $entityStepKey, + $scope, + $entityName + ); + } + public function testCreateSimpleEntity() { // Test Data and Variables diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php new file mode 100644 index 000000000..e1f4e4879 --- /dev/null +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorageTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers\SecretStorage; + +use Aws\SecretsManager\SecretsManagerClient; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\AwsSecretsManagerStorage; +use Aws\Result; +use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use ReflectionClass; + +class AwsSecretsManagerStorageTest extends MagentoTestCase +{ + /** + * Test encryption/decryption functionality in AwsSecretsManagerStorage class. + */ + public function testEncryptAndDecrypt() + { + // Setup test data + $testProfile = 'profile'; + $testRegion = 'region'; + $testLongKey = 'magento/myKey'; + $testShortKey = 'myKey'; + $testValue = 'myValue'; + $data = [ + 'Name' => 'mftf/magento/' . $testShortKey, + 'SecretString' => json_encode([$testShortKey => $testValue]) + ]; + /** @var Result */ + $result = new Result($data); + + $mockClient = $this->getMockBuilder(SecretsManagerClient::class) + ->disableOriginalConstructor() + ->setMethods(['__call']) + ->getMock(); + + $mockClient->expects($this->once()) + ->method('__call') + ->willReturnCallback(function ($name, $args) use ($result) { + return $result; + }); + + /** @var SecretsManagerClient */ + $credentialStorage = new AwsSecretsManagerStorage($testRegion, $testProfile); + $reflection = new ReflectionClass($credentialStorage); + $reflection_property = $reflection->getProperty('client'); + $reflection_property->setAccessible(true); + $reflection_property->setValue($credentialStorage, $mockClient); + + // Test getEncryptedValue() + $encryptedCred = $credentialStorage->getEncryptedValue($testLongKey); + + // Assert the value we've gotten is in fact not identical to our test value + $this->assertNotEquals($testValue, $encryptedCred); + + // Test getDecryptedValue() + $actualValue = $credentialStorage->getDecryptedValue($encryptedCred); + + // Assert that we are able to successfully decrypt our secret value + $this->assertEquals($testValue, $actualValue); + } +} diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php index 29158b0f5..e3f820ede 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Suite/SuiteGeneratorTest.php @@ -6,6 +6,7 @@ namespace Tests\unit\Magento\FunctionalTestFramework\Suite; use AspectMock\Test as AspectMock; +use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; use Magento\FunctionalTestingFramework\ObjectManager\ObjectManager; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Suite\SuiteGenerator; @@ -17,6 +18,7 @@ use Magento\FunctionalTestingFramework\Test\Parsers\TestDataParser; use Magento\FunctionalTestingFramework\Util\Manifest\DefaultTestManifest; use Magento\FunctionalTestingFramework\Util\MagentoTestCase; +use Magento\FunctionalTestingFramework\Util\Manifest\TestManifestFactory; use tests\unit\Util\SuiteDataArrayBuilder; use tests\unit\Util\TestDataArrayBuilder; use tests\unit\Util\TestLoggingUtil; @@ -143,6 +145,73 @@ public function testGenerateEmptySuite() $mockSuiteGenerator->generateSuite("basicTestSuite"); } + public function testInvalidSuiteTestPair() + { + // Mock Suite1 => Test1 and Suite2 => Test2 + $suiteDataArrayBuilder = new SuiteDataArrayBuilder(); + $mockData = $suiteDataArrayBuilder + ->withName('Suite1') + ->includeGroups(['group1']) + ->build(); + $suiteDataArrayBuilder = new SuiteDataArrayBuilder(); + $mockData2 = $suiteDataArrayBuilder + ->withName('Suite2') + ->includeGroups(['group2']) + ->build(); + $mockSuiteData = array_merge_recursive($mockData, $mockData2); + + $testDataArrayBuilder = new TestDataArrayBuilder(); + $mockSimpleTest = $testDataArrayBuilder + ->withName('Test1') + ->withAnnotations(['group' => [['value' => 'group1']]]) + ->withTestActions() + ->build(); + $testDataArrayBuilder = new TestDataArrayBuilder(); + $mockSimpleTest2 = $testDataArrayBuilder + ->withName('Test2') + ->withAnnotations(['group' => [['value' => 'group2']]]) + ->withTestActions() + ->build(); + $mockTestData = ['tests' => array_merge($mockSimpleTest, $mockSimpleTest2)]; + $this->setMockTestAndSuiteParserOutput($mockTestData, $mockSuiteData); + + // Make invalid manifest + $suiteConfig = ['Suite2' => ['Test1']]; + $manifest = TestManifestFactory::makeManifest('default', $suiteConfig); + + // Set up Expected Exception + $this->expectException(TestReferenceException::class); + $this->expectExceptionMessageRegExp('(Suite: "Suite2" Tests: "Test1")'); + + // parse and generate suite object with mocked data and manifest + $mockSuiteGenerator = SuiteGenerator::getInstance(); + $mockSuiteGenerator->generateAllSuites($manifest); + } + + public function testNonExistentSuiteTestPair() + { + $testDataArrayBuilder = new TestDataArrayBuilder(); + $mockSimpleTest = $testDataArrayBuilder + ->withName('Test1') + ->withAnnotations(['group' => [['value' => 'group1']]]) + ->withTestActions() + ->build(); + $mockTestData = ['tests' => array_merge($mockSimpleTest)]; + $this->setMockTestAndSuiteParserOutput($mockTestData, []); + + // Make invalid manifest + $suiteConfig = ['Suite3' => ['Test1']]; + $manifest = TestManifestFactory::makeManifest('default', $suiteConfig); + + // Set up Expected Exception + $this->expectException(TestReferenceException::class); + $this->expectExceptionMessageRegExp('#Suite3 is not defined#'); + + // parse and generate suite object with mocked data and manifest + $mockSuiteGenerator = SuiteGenerator::getInstance(); + $mockSuiteGenerator->generateAllSuites($manifest); + } + /** * Function used to set mock for parser return and force init method to run between tests. * diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php index 39e80d556..67f6f2b43 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Handlers/TestObjectHandlerTest.php @@ -92,7 +92,7 @@ public function testGetTestObject() [ 'features' => ['NO MODULE DETECTED'], 'group' => ['test'], - 'description' => ['<br><br><b><font size=+0.9>Test files</font></b><br><br>'] + 'description' => ['test_files' => '<h3>Test files</h3>', 'deprecated' => []] ], [ TestObjectExtractor::TEST_BEFORE_HOOK => $expectedBeforeHookObject, diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php index cadc1c6a8..8f8eee749 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/TestGeneratorTest.php @@ -9,6 +9,7 @@ use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; +use Magento\FunctionalTestingFramework\Test\Objects\TestHookObject; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; use Magento\FunctionalTestingFramework\Util\MagentoTestCase; use Magento\FunctionalTestingFramework\Util\TestGenerator; @@ -76,14 +77,26 @@ public function testAllowSkipped() $actionObject = new ActionObject('fakeAction', 'comment', [ 'userInput' => $actionInput ]); + $beforeActionInput = 'beforeInput'; + $beforeActionObject = new ActionObject('beforeAction', 'comment', [ + 'userInput' => $beforeActionInput + ]); $annotations = ['skip' => ['issue']]; - $testObject = new TestObject("sampleTest", ["merge123" => $actionObject], $annotations, [], "filename"); + $beforeHook = new TestHookObject("before", "sampleTest", ['beforeAction' => $beforeActionObject]); + $testObject = new TestObject( + "sampleTest", + ["fakeAction" => $actionObject], + $annotations, + ["before" => $beforeHook], + "filename" + ); $testGeneratorObject = TestGenerator::getInstance("", ["sampleTest" => $testObject]); $output = $testGeneratorObject->assembleTestPhp($testObject); $this->assertNotContains('This test is skipped', $output); $this->assertContains($actionInput, $output); + $this->assertContains($beforeActionInput, $output); } } diff --git a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt index d7e31b5f2..23e0f0b69 100644 --- a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt +++ b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupContainsStepKeyInArgTextCest { diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt index 127b9cc59..da3d84daf 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupMergedViaInsertAfterCest { diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt index 1486d042e..22e8148d9 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupMergedViaInsertBeforeCest { diff --git a/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt b/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt index d11d5c238..efd5a8cb5 100644 --- a/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt +++ b/dev/tests/verification/Resources/ActionGroupSkipReadiness.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupSkipReadinessCest { diff --git a/dev/tests/verification/Resources/ActionGroupToExtend.txt b/dev/tests/verification/Resources/ActionGroupToExtend.txt index d7e72260d..29d08c0b6 100644 --- a/dev/tests/verification/Resources/ActionGroupToExtend.txt +++ b/dev/tests/verification/Resources/ActionGroupToExtend.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupToExtendCest { diff --git a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt index 96134fd86..b64822cf6 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupUsingCreateDataCest { @@ -26,24 +24,8 @@ class ActionGroupUsingCreateDataCest public function _before(AcceptanceTester $I) { $I->comment("Entering Action Group [Key1] actionGroupWithCreateData"); - $I->comment("[createCategoryKey1] create 'ApiCategory' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createCategoryKey1", - "hook", - "ApiCategory", - [], - [] - ); - - $I->comment("[createConfigProductKey1] create 'ApiConfigurableProduct' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createConfigProductKey1", - "hook", - "ApiConfigurableProduct", - ["createCategoryKey1"], - [] - ); - + $I->createEntity("createCategoryKey1", "hook", "ApiCategory", [], []); // stepKey: createCategoryKey1 + $I->createEntity("createConfigProductKey1", "hook", "ApiConfigurableProduct", ["createCategoryKey1"], []); // stepKey: createConfigProductKey1 $I->comment("Exiting Action Group [Key1] actionGroupWithCreateData"); } diff --git a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt index b69ee6c9d..5eb67f577 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupUsingNestedArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt index c0498101d..bb6404315 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupWithDataOverrideTestCest { @@ -26,15 +24,7 @@ class ActionGroupWithDataOverrideTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt index 01a87104d..6b22f83e0 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupWithDataTestCest { @@ -26,15 +24,7 @@ class ActionGroupWithDataTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt index ce8a4aed8..ca5f72cc0 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Default Argument Value and Hardcoded Value in Param") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithDefaultArgumentAndStringSelectorParamCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt index b7bef0135..f3ad492b0 100644 --- a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,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("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithMultipleParameterSelectorsFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt index 6b81a187f..0f69c40e8 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With No Argument") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithNoArgumentsCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt index 6125c7697..533e14b9d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupWithNoDefaultTestCest { @@ -26,15 +24,7 @@ class ActionGroupWithNoDefaultTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt index 163ebc6ba..acc6aa58a 100644 --- a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt +++ b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithParameterizedElementWithHyphenCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt index de7af8209..ac20299a8 100644 --- a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementsWithStepKeyReferences.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithParameterizedElementsWithStepKeyReferencesCest { @@ -31,18 +29,10 @@ class ActionGroupWithParameterizedElementsWithStepKeyReferencesCest $I->comment("Entering Action Group [actionGroup] actionGroupWithParametrizedSelectors"); $testVariableActionGroup = $I->executeJS("return 1"); // stepKey: testVariableActionGroup $testVariable2ActionGroup = $I->executeJS("return 'test'"); // stepKey: testVariable2ActionGroup - $I->comment("[createSimpleDataActionGroup] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createSimpleDataActionGroup", - "test", - "simpleData", - [], - [] - ); - + $I->createEntity("createSimpleDataActionGroup", "test", "simpleData", [], []); // stepKey: createSimpleDataActionGroup $I->click("#{$testVariable2ActionGroup} .John"); // stepKey: click1ActionGroup $I->click("#Doe-" . msq("simpleParamData") . "prename .{$testVariableActionGroup}"); // stepKey: click2ActionGroup - $I->seeElement("//div[@name='Tiberius'][@class={$testVariableActionGroup}][@data-element='{$testVariable2ActionGroup}'][" . PersistedObjectHandler::getInstance()->retrieveEntityField('createSimpleData', 'name', 'test') . "]"); // stepKey: see1ActionGroup + $I->seeElement("//div[@name='Tiberius'][@class={$testVariableActionGroup}][@data-element='{$testVariable2ActionGroup}'][" . $I->retrieveEntityField('createSimpleData', 'name', 'test') . "]"); // stepKey: see1ActionGroup $I->comment("Exiting Action Group [actionGroup] actionGroupWithParametrizedSelectors"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt index 9720595e0..e816da90b 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Passed Argument Value and Hardcoded Value in Param") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithPassedArgumentAndStringSelectorParamCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt index da0480379..7d0bb58e9 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupWithPersistedDataCest { @@ -26,15 +24,7 @@ class ActionGroupWithPersistedDataCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup @@ -73,21 +63,13 @@ class ActionGroupWithPersistedDataCest */ public function ActionGroupWithPersistedData(AcceptanceTester $I) { - $I->comment("[createPerson] create 'DefaultPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPerson", - "test", - "DefaultPerson", - [], - [] - ); - + $I->createEntity("createPerson", "test", "DefaultPerson", [], []); // stepKey: createPerson $I->comment("Entering Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test') . "/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test') . ".html"); // stepKey: amOnPage1ActionGroupWithPersistedData1 - $I->fillField("#foo", PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test')); // stepKey: fillField1ActionGroupWithPersistedData1 - $I->fillField("#bar", PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test')); // stepKey: fillField2ActionGroupWithPersistedData1 - $I->searchAndMultiSelectOption("#foo", [PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test')]); // stepKey: multi1ActionGroupWithPersistedData1 - $I->see("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test')); // stepKey: see1ActionGroupWithPersistedData1 + $I->amOnPage("/" . $I->retrieveEntityField('createPerson', 'firstname', 'test') . "/" . $I->retrieveEntityField('createPerson', 'lastname', 'test') . ".html"); // stepKey: amOnPage1ActionGroupWithPersistedData1 + $I->fillField("#foo", $I->retrieveEntityField('createPerson', 'firstname', 'test')); // stepKey: fillField1ActionGroupWithPersistedData1 + $I->fillField("#bar", $I->retrieveEntityField('createPerson', 'lastname', 'test')); // stepKey: fillField2ActionGroupWithPersistedData1 + $I->searchAndMultiSelectOption("#foo", [$I->retrieveEntityField('createPerson', 'firstname', 'test'), $I->retrieveEntityField('createPerson', 'lastname', 'test')]); // stepKey: multi1ActionGroupWithPersistedData1 + $I->see("#element ." . $I->retrieveEntityField('createPerson', 'firstname', 'test')); // stepKey: see1ActionGroupWithPersistedData1 $I->comment("Exiting Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt index a0b6d0074..f629f32f1 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithSectionAndDataAsArgumentsCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt index 4d3da18a4..10206867a 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Simple Data Usage From Default Argument") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithSimpleDataUsageFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt index d866c3992..54aec35a7 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Simple Data Usage From Passed Argument") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithSimpleDataUsageFromPassedArgumentCest { @@ -46,19 +44,19 @@ class ActionGroupWithSimpleDataUsageFromPassedArgumentCest $I->see("simpleData.firstname", "#element .simpleData.firstname"); // stepKey: see1ActionGroup2 $I->comment("Exiting Action Group [actionGroup2] actionGroupWithStringUsage"); $I->comment("Entering Action Group [actionGroup3] actionGroupWithStringUsage"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); // stepKey: see1ActionGroup3 + $I->see($I->retrieveEntityField('persisted', 'data', 'test'), "#element ." . $I->retrieveEntityField('persisted', 'data', 'test')); // stepKey: see1ActionGroup3 $I->comment("Exiting Action Group [actionGroup3] actionGroupWithStringUsage"); $I->comment("Entering Action Group [actionGroup4] actionGroupWithEntityUsage"); $I->see("John", "#element .John"); // stepKey: see1ActionGroup4 $I->comment("Exiting Action Group [actionGroup4] actionGroupWithEntityUsage"); $I->comment("Entering Action Group [actionGroup5] actionGroupWithEntityUsage"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname', 'test')); // stepKey: see1ActionGroup5 + $I->see($I->retrieveEntityField('simpleData', 'firstname', 'test'), "#element ." . $I->retrieveEntityField('simpleData', 'firstname', 'test')); // stepKey: see1ActionGroup5 $I->comment("Exiting Action Group [actionGroup5] actionGroupWithEntityUsage"); $I->comment("Entering Action Group [actionGroup6] actionGroupWithEntityUsage"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[0]', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[0]', 'test')); // stepKey: see1ActionGroup6 + $I->see($I->retrieveEntityField('simpleData', 'firstname[0]', 'test'), "#element ." . $I->retrieveEntityField('simpleData', 'firstname[0]', 'test')); // stepKey: see1ActionGroup6 $I->comment("Exiting Action Group [actionGroup6] actionGroupWithEntityUsage"); $I->comment("Entering Action Group [actionGroup7] actionGroupWithEntityUsage"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[data_index]', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[data_index]', 'test')); // stepKey: see1ActionGroup7 + $I->see($I->retrieveEntityField('simpleData', 'firstname[data_index]', 'test'), "#element ." . $I->retrieveEntityField('simpleData', 'firstname[data_index]', 'test')); // stepKey: see1ActionGroup7 $I->comment("Exiting Action Group [actionGroup7] actionGroupWithEntityUsage"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt index af7af43a4..c23b99cab 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Default Argument Value and Argument Value in Param") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithSingleParameterSelectorFromDefaultArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt index 096623789..4a0932b99 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With Passed Argument Value and Argument Value in Param") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithSingleParameterSelectorFromPassedArgumentCest { diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index d1cae1da4..8098142fd 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ActionGroupWithStepKeyReferencesCest { @@ -29,17 +27,9 @@ class ActionGroupWithStepKeyReferencesCest public function ActionGroupWithStepKeyReferences(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroup] FunctionActionGroupWithStepKeyReferences"); - $I->comment("[createSimpleDataActionGroup] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createSimpleDataActionGroup", - "test", - "simpleData", - [], - [] - ); - + $I->createEntity("createSimpleDataActionGroup", "test", "simpleData", [], []); // stepKey: createSimpleDataActionGroup $grabTextDataActionGroup = $I->grabTextFrom(".class"); // stepKey: grabTextDataActionGroup - $I->fillField(".{$grabTextDataActionGroup}", PersistedObjectHandler::getInstance()->retrieveEntityField('createSimpleDataActionGroup', 'field', 'test')); // stepKey: fill1ActionGroup + $I->fillField(".{$grabTextDataActionGroup}", $I->retrieveEntityField('createSimpleDataActionGroup', 'field', 'test')); // stepKey: fill1ActionGroup $I->comment("Invocation stepKey will not be appended in non stepKey instances"); $I->click($action0); // stepKey: action0ActionGroup $I->fillField($action1); // stepKey: action1ActionGroup @@ -53,38 +43,10 @@ class ActionGroupWithStepKeyReferencesCest $action5ActionGroup = $date->format("H:i:s"); $action6ActionGroup = $I->formatMoney($action6ActionGroup); // stepKey: action6ActionGroup - $I->comment("[action7ActionGroup] delete entity '{$action7ActionGroupActionGroup}'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "{$action7ActionGroupActionGroup}", - "test" - ); - - $I->comment("[action8ActionGroup] get '{$action8}' entity"); - PersistedObjectHandler::getInstance()->getEntity( - "action8ActionGroup", - "test", - "{$action8}", - [], - null - ); - - $I->comment("[action9ActionGroup] update '1' entity to '{$action9}'"); - PersistedObjectHandler::getInstance()->updateEntity( - "1", - "test", - "{$action9}", - [] - ); - - $I->comment("[action10ActionGroup] create '{$action10}' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "action10ActionGroup", - "test", - "{$action10}", - [], - [] - ); - + $I->deleteEntity("{$action7ActionGroupActionGroup}", "test"); // stepKey: action7ActionGroup + $I->getEntity("action8ActionGroup", "test", "{$action8}", [], null); // stepKey: action8ActionGroup + $I->updateEntity("1", "test", "{$action9}",[]); // stepKey: action9ActionGroup + $I->createEntity("action10ActionGroup", "test", "{$action10}", [], []); // stepKey: action10ActionGroup $action11ActionGroup = $I->grabAttributeFrom($action11ActionGroup, "someInput"); // stepKey: action11ActionGroup $action12ActionGroup = $I->grabCookie($action12ActionGroup, ['domain' => 'www.google.com']); // stepKey: action12ActionGroup $action13ActionGroup = $I->grabFromCurrentUrl($action13ActionGroup); // stepKey: action13ActionGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt index ef1a5636c..a8f80eae6 100644 --- a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ActionGroupWithTopLevelPersistedDataCest { @@ -26,15 +24,7 @@ class ActionGroupWithTopLevelPersistedDataCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup @@ -74,11 +64,11 @@ class ActionGroupWithTopLevelPersistedDataCest public function ActionGroupWithTopLevelPersistedData(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test') . "/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test') . ".html"); // stepKey: amOnPage1ActionGroupWithPersistedData1 - $I->fillField("#foo", PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test')); // stepKey: fillField1ActionGroupWithPersistedData1 - $I->fillField("#bar", PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test')); // stepKey: fillField2ActionGroupWithPersistedData1 - $I->searchAndMultiSelectOption("#foo", [PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test')]); // stepKey: multi1ActionGroupWithPersistedData1 - $I->see("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test')); // stepKey: see1ActionGroupWithPersistedData1 + $I->amOnPage("/" . $I->retrieveEntityField('createPersonParam', 'firstname', 'test') . "/" . $I->retrieveEntityField('createPersonParam', 'lastname', 'test') . ".html"); // stepKey: amOnPage1ActionGroupWithPersistedData1 + $I->fillField("#foo", $I->retrieveEntityField('createPersonParam', 'firstname', 'test')); // stepKey: fillField1ActionGroupWithPersistedData1 + $I->fillField("#bar", $I->retrieveEntityField('createPersonParam', 'lastname', 'test')); // stepKey: fillField2ActionGroupWithPersistedData1 + $I->searchAndMultiSelectOption("#foo", [$I->retrieveEntityField('createPersonParam', 'firstname', 'test'), $I->retrieveEntityField('createPersonParam', 'lastname', 'test')]); // stepKey: multi1ActionGroupWithPersistedData1 + $I->see("#element ." . $I->retrieveEntityField('createPersonParam', 'firstname', 'test')); // stepKey: see1ActionGroupWithPersistedData1 $I->comment("Exiting Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); } } diff --git a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt index 2da03b506..e45207249 100644 --- a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt +++ b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class ArgumentWithSameNameAsElementCest { @@ -26,15 +24,7 @@ class ArgumentWithSameNameAsElementCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/AssertTest.txt b/dev/tests/verification/Resources/AssertTest.txt index 28c38bc0b..bb29759d5 100644 --- a/dev/tests/verification/Resources/AssertTest.txt +++ b/dev/tests/verification/Resources/AssertTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/AssertTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/AssertTest.xml<br>") */ class AssertTestCest { @@ -25,15 +23,7 @@ class AssertTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createData1] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData1", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createData1", "hook", "ReplacementPerson", [], []); // stepKey: createData1 } /** @@ -45,15 +35,7 @@ class AssertTestCest */ public function AssertTest(AcceptanceTester $I) { - $I->comment("[createData2] create 'UniquePerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData2", - "test", - "UniquePerson", - [], - [] - ); - + $I->createEntity("createData2", "test", "UniquePerson", [], []); // stepKey: createData2 $grabTextFrom1 = $I->grabTextFrom(".copyright>span"); // stepKey: grabTextFrom1 $I->comment("custom asserts"); $I->assertArrayIsSorted(["1", "2", "3", "4", "5"], "asc"); // stepKey: assertSorted1 @@ -138,15 +120,15 @@ class AssertTestCest $I->expectException(new MyException('exception msg'), function() {$this->doSomethingBad();}); // stepKey: expectExceptionBackwardCompatible $I->comment("string type that use created data"); $I->comment("string type that use created data"); - $I->assertStringStartsWith("D", PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test') . ", " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test'), "fail"); // stepKey: assert1 - $I->assertStringStartsNotWith("W", PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test') . ", " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test'), "pass"); // stepKey: assert2 - $I->assertEquals(PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), "pass"); // stepKey: assert5 + $I->assertStringStartsWith("D", $I->retrieveEntityField('createData1', 'lastname', 'test') . ", " . $I->retrieveEntityField('createData1', 'firstname', 'test'), "fail"); // stepKey: assert1 + $I->assertStringStartsNotWith("W", $I->retrieveEntityField('createData2', 'firstname', 'test') . ", " . $I->retrieveEntityField('createData2', 'lastname', 'test'), "pass"); // stepKey: assert2 + $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([PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test')], [PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test'), "1"], "pass"); // stepKey: assert9 - $I->assertArraySubset([PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test')], [PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test'), "1"], "pass"); // stepKey: assert10 - $I->assertArrayHasKey("lastname", ['lastname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), 'firstname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test')], "pass"); // stepKey: assert3 - $I->assertArrayHasKey("lastname", ['lastname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test'), 'firstname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test')], "pass"); // stepKey: assert4 + $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"); $I->assertInstanceOf(User::class, $text, "pass"); // stepKey: assertInstanceOf $I->assertNotInstanceOf(User::class, 21, "pass"); // stepKey: assertNotInstanceOf @@ -156,8 +138,8 @@ class AssertTestCest $I->assertNull($text, "pass"); // stepKey: assertNull $I->expectException(new MyException('exception msg'), function() {$this->doSomethingBad();}); // stepKey: expectException $I->fail("fail"); // stepKey: fail - $I->fail(PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test') . " " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test')); // stepKey: assert7 - $I->fail(PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test')); // stepKey: assert8 + $I->fail($I->retrieveEntityField('createData2', 'firstname', 'test') . " " . $I->retrieveEntityField('createData2', 'lastname', 'test')); // stepKey: assert7 + $I->fail($I->retrieveEntityField('createData1', 'firstname', 'test') . " " . $I->retrieveEntityField('createData1', 'lastname', 'test')); // stepKey: assert8 $I->comment("assertElementContainsAttribute examples"); $I->assertElementContainsAttribute("#username", "class", "admin__control-text"); // stepKey: assertElementContainsAttribute1 $I->assertElementContainsAttribute("#username", "name", "login[username]"); // stepKey: assertElementContainsAttribute2 @@ -165,8 +147,8 @@ class AssertTestCest $I->assertElementContainsAttribute("#username", "data-validate", "{required:true}"); // stepKey: assertElementContainsAttribute4 $I->assertElementContainsAttribute(".admin__menu-overlay", "style", "display: none;"); // stepKey: assertElementContainsAttribute5 $I->assertElementContainsAttribute(".admin__menu-overlay", "border", "0"); // stepKey: assertElementContainsAttribute6 - $I->assertElementContainsAttribute("#username", "value", PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test')); // stepKey: assertElementContainsAttribute7 - $I->assertElementContainsAttribute("#username", "value", PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test')); // stepKey: assertElementContainsAttribute8 + $I->assertElementContainsAttribute("#username", "value", $I->retrieveEntityField('createData2', 'firstname', 'test')); // stepKey: assertElementContainsAttribute7 + $I->assertElementContainsAttribute("#username", "value", $I->retrieveEntityField('createData1', 'firstname', 'test')); // stepKey: assertElementContainsAttribute8 $I->comment("assert entity resolution"); $I->assertEquals("John", "Doe", "pass"); // stepKey: assertEqualsEntity } diff --git a/dev/tests/verification/Resources/BasicActionGroupTest.txt b/dev/tests/verification/Resources/BasicActionGroupTest.txt index 4bb9c1a95..7d8c40f0b 100644 --- a/dev/tests/verification/Resources/BasicActionGroupTest.txt +++ b/dev/tests/verification/Resources/BasicActionGroupTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class BasicActionGroupTestCest { @@ -26,15 +24,7 @@ class BasicActionGroupTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index bc7fe0b94..ac42f395e 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: A Functional Cest") * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/BasicFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/BasicFunctionalTest.xml<br>") */ class BasicFunctionalTestCest { @@ -76,14 +74,8 @@ class BasicFunctionalTestCest $I->clickWithRightButton("#element .4123#element", 200, 300); // stepKey: clickWithRightButtonKeyXY1 $I->closeTab(); // stepKey: closeTabKey1 $I->conditionalClick(".functionalTestSelector", ".functionalDependentTestSelector", true); // stepKey: conditionalClickKey1 - $I->comment("[deleteKey1] delete entity 'createKey1'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createKey1", - "test" - ); - - $I->deleteEntityByUrl("/V1/categories{$grabbedData}"); - + $I->deleteEntity("createKey1", "test"); // stepKey: deleteKey1 + $I->deleteEntityByUrl("/V1/categories{$grabbedData}"); // stepKey: deleteKey2 $I->dontSee("someInput", ".functionalTestSelector"); // stepKey: dontSeeKey1 $I->dontSeeCheckboxIsChecked(".functionalTestSelector"); // stepKey: dontSeeCheckboxIsCheckedKey1 $I->dontSeeCookie("someInput"); // stepKey: dontSeeCookieKey1 @@ -130,10 +122,16 @@ class BasicFunctionalTestCest $I->comment($magentoCli1); $magentoCli2 = $I->magentoCLI("maintenance:enable", 120, "\"stuffHere\""); // stepKey: magentoCli2 $I->comment($magentoCli2); - $magentoCli3 = $I->magentoCLISecret("config:set somePath " . CredentialStore::getInstance()->getSecret("someKey"), 60); // stepKey: magentoCli3 + $magentoCli3 = $I->magentoCLISecret("config:set somePath " . $I->getSecret("someKey"), 60); // stepKey: magentoCli3 $I->comment($magentoCli3); // stepKey: magentoCli3 - $magentoCli4 = $I->magentoCLISecret("config:set somePath " . CredentialStore::getInstance()->getSecret("someKey"), 120); // stepKey: magentoCli4 + $magentoCli4 = $I->magentoCLISecret("config:set somePath " . $I->getSecret("someKey"), 120); // stepKey: magentoCli4 $I->comment($magentoCli4); // stepKey: magentoCli4 + $cronAllGroups = $I->magentoCron("", 70); // stepKey: cronAllGroups + $I->comment($cronAllGroups); + $cronSingleGroup = $I->magentoCron("index", 70); // stepKey: cronSingleGroup + $I->comment($cronSingleGroup); + $cronMultipleGroups = $I->magentoCron("a b c", 70); // stepKey: cronMultipleGroups + $I->comment($cronMultipleGroups); $I->makeScreenshot("screenShotInput"); // stepKey: makeScreenshotKey1 $I->maximizeWindow(); // stepKey: maximizeWindowKey1 $I->moveBack(); // stepKey: moveBackKey1 diff --git a/dev/tests/verification/Resources/BasicMergeTest.txt b/dev/tests/verification/Resources/BasicMergeTest.txt index 5421efe33..8171cd892 100644 --- a/dev/tests/verification/Resources/BasicMergeTest.txt +++ b/dev/tests/verification/Resources/BasicMergeTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -18,7 +16,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; * @Title("[NO TESTCASEID]: BasicMergeTest") * @group functional * @group mergeTest - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/MergeFunctionalTest.xml<br>verification/TestModuleMerged/Test/MergeFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/MergeFunctionalTest.xml<br>verification/TestModuleMerged/Test/MergeFunctionalTest.xml<br>") */ class BasicMergeTestCest { diff --git a/dev/tests/verification/Resources/CharacterReplacementTest.txt b/dev/tests/verification/Resources/CharacterReplacementTest.txt index db3852b17..24d8e2ab1 100644 --- a/dev/tests/verification/Resources/CharacterReplacementTest.txt +++ b/dev/tests/verification/Resources/CharacterReplacementTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/CharacterReplacementTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/CharacterReplacementTest.xml<br>") */ class CharacterReplacementTestCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt index e03501707..86d81f848 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestAddHooks") * @group Parent - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestAddHooksCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt index a99843b48..08345bd86 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestMerging") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestMergingCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt b/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt index 1eec9e48c..4cca6ec06 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestNoParent.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestNoParent") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") * @group skip */ class ChildExtendedTestNoParentCest diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt index 20aa62e28..370ffe404 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestRemoveAction") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestRemoveActionCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt index 561fd24fa..50b6e030d 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestRemoveHookAction") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestRemoveHookActionCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt index 8d131a83f..ce32f6af1 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestReplace") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestReplaceCest { diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt index ae0b02c20..bbb6c5ef9 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestReplaceHook") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ChildExtendedTestReplaceHookCest { diff --git a/dev/tests/verification/Resources/DataActionsTest.txt b/dev/tests/verification/Resources/DataActionsTest.txt index 380db238d..84a94174a 100644 --- a/dev/tests/verification/Resources/DataActionsTest.txt +++ b/dev/tests/verification/Resources/DataActionsTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/DataActionsTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/DataActionsTest.xml<br>") */ class DataActionsTestCest { @@ -25,29 +23,9 @@ class DataActionsTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createdInBefore] create 'entity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdInBefore", - "hook", - "entity", - [], - [] - ); - - $I->comment("[updateInBefore] update 'createdInBefore' entity to 'entity'"); - PersistedObjectHandler::getInstance()->updateEntity( - "createdInBefore", - "hook", - "entity", - [] - ); - - $I->comment("[deleteInBefore] delete entity 'createdInBefore'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createdInBefore", - "hook" - ); - + $I->createEntity("createdInBefore", "hook", "entity", [], []); // stepKey: createdInBefore + $I->updateEntity("createdInBefore", "hook", "entity",[]); // stepKey: updateInBefore + $I->deleteEntity("createdInBefore", "hook"); // stepKey: deleteInBefore } /** @@ -59,42 +37,10 @@ class DataActionsTestCest */ public function DataActionsTest(AcceptanceTester $I) { - $I->comment("[createdInTest] create 'entity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdInTest", - "test", - "entity", - [], - [] - ); - - $I->comment("[updateInTest] update 'createdInTest' entity to 'entity'"); - PersistedObjectHandler::getInstance()->updateEntity( - "createdInTest", - "test", - "entity", - [] - ); - - $I->comment("[deleteInTest] delete entity 'createdInTest'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createdInTest", - "test" - ); - - $I->comment("[updatedDataOutOfScope] update 'createdInBefore' entity to 'entity'"); - PersistedObjectHandler::getInstance()->updateEntity( - "createdInBefore", - "test", - "entity", - [] - ); - - $I->comment("[deleteDataOutOfScope] delete entity 'createdInBefore'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createdInBefore", - "test" - ); - + $I->createEntity("createdInTest", "test", "entity", [], []); // stepKey: createdInTest + $I->updateEntity("createdInTest", "test", "entity",[]); // stepKey: updateInTest + $I->deleteEntity("createdInTest", "test"); // stepKey: deleteInTest + $I->updateEntity("createdInBefore", "test", "entity",[]); // stepKey: updatedDataOutOfScope + $I->deleteEntity("createdInBefore", "test"); // stepKey: deleteDataOutOfScope } } diff --git a/dev/tests/verification/Resources/DataReplacementTest.txt b/dev/tests/verification/Resources/DataReplacementTest.txt index 4b4531a4e..b75d93f0d 100644 --- a/dev/tests/verification/Resources/DataReplacementTest.txt +++ b/dev/tests/verification/Resources/DataReplacementTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/DataReplacementTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/DataReplacementTest.xml<br>") */ class DataReplacementTestCest { diff --git a/dev/tests/verification/Resources/DeprecatedEntitiesTest.txt b/dev/tests/verification/Resources/DeprecatedEntitiesTest.txt new file mode 100644 index 000000000..489cb66ea --- /dev/null +++ b/dev/tests/verification/Resources/DeprecatedEntitiesTest.txt @@ -0,0 +1,34 @@ +<?php +namespace Magento\AcceptanceTest\_default\Backend; + +use Magento\FunctionalTestingFramework\AcceptanceTester; +use \Codeception\Util\Locator; +use Yandex\Allure\Adapter\Annotation\Features; +use Yandex\Allure\Adapter\Annotation\Stories; +use Yandex\Allure\Adapter\Annotation\Title; +use Yandex\Allure\Adapter\Annotation\Description; +use Yandex\Allure\Adapter\Annotation\Parameter; +use Yandex\Allure\Adapter\Annotation\Severity; +use Yandex\Allure\Adapter\Model\SeverityLevel; +use Yandex\Allure\Adapter\Annotation\TestCaseId; + +/** + * @Description("<h3 class='y-label y-label_status_broken'>Deprecated Notice(s):</h3><ul><li>DEPRECATED ACTION GROUP in Test: DeprecatedActionGroup Deprecated action group</li><li>DEPRECATED SECTION in Test: {{DeprecatedSection.deprecatedElement}} Deprecated section</li><li>DEPRECATED ELEMENT in Test: {{DeprecatedSection.deprecatedElement}} Deprecated element</li><li>DEPRECATED DATA ENTITY in Test: {{DeprecatedData.field}} Data entity deprecated</li><li>DEPRECATED PAGE in Test: {{DeprecatedPage.url}} Deprecated page</li></ul><h3>Test files</h3>verification/TestModule/Test/DeprecatedEntitiesTest.xml<br>") + */ +class DeprecatedEntitiesTestCest +{ + /** + * @Features({"TestModule"}) + * @Parameter(name = "AcceptanceTester", value="$I") + * @param AcceptanceTester $I + * @return void + * @throws \Exception + */ + public function DeprecatedEntitiesTest(AcceptanceTester $I) + { + $I->comment("Entering Action Group [deprecatedActionGroup] DeprecatedActionGroup"); + $I->see("deprecated", "#element"); // stepKey: deprecatedSeeDeprecatedActionGroup + $I->comment("Exiting Action Group [deprecatedActionGroup] DeprecatedActionGroup"); + $I->amOnPage("/test.html"); // stepKey: amOnPage + } +} diff --git a/dev/tests/verification/Resources/DeprecatedTest.txt b/dev/tests/verification/Resources/DeprecatedTest.txt new file mode 100644 index 000000000..845d13912 --- /dev/null +++ b/dev/tests/verification/Resources/DeprecatedTest.txt @@ -0,0 +1,34 @@ +<?php +namespace Magento\AcceptanceTest\_default\Backend; + +use Magento\FunctionalTestingFramework\AcceptanceTester; +use \Codeception\Util\Locator; +use Yandex\Allure\Adapter\Annotation\Features; +use Yandex\Allure\Adapter\Annotation\Stories; +use Yandex\Allure\Adapter\Annotation\Title; +use Yandex\Allure\Adapter\Annotation\Description; +use Yandex\Allure\Adapter\Annotation\Parameter; +use Yandex\Allure\Adapter\Annotation\Severity; +use Yandex\Allure\Adapter\Model\SeverityLevel; +use Yandex\Allure\Adapter\Annotation\TestCaseId; + +/** + * @Description("<h3 class='y-label y-label_status_broken'>Deprecated Notice(s):</h3><ul><li>Test is deprecated</li><li>DEPRECATED ACTION GROUP in Test: DeprecatedActionGroup Deprecated action group</li><li>DEPRECATED SECTION in Test: {{DeprecatedSection.deprecatedElement}} Deprecated section</li><li>DEPRECATED ELEMENT in Test: {{DeprecatedSection.deprecatedElement}} Deprecated element</li><li>DEPRECATED DATA ENTITY in Test: {{DeprecatedData.field}} Data entity deprecated</li><li>DEPRECATED PAGE in Test: {{DeprecatedPage.url}} Deprecated page</li></ul><h3>Test files</h3>verification/TestModule/Test/DeprecatedTest.xml<br>") + */ +class DeprecatedTestCest +{ + /** + * @Features({"TestModule"}) + * @Parameter(name = "AcceptanceTester", value="$I") + * @param AcceptanceTester $I + * @return void + * @throws \Exception + */ + public function DeprecatedTest(AcceptanceTester $I) + { + $I->comment("Entering Action Group [deprecatedActionGroup] DeprecatedActionGroup"); + $I->see("deprecated", "#element"); // stepKey: deprecatedSeeDeprecatedActionGroup + $I->comment("Exiting Action Group [deprecatedActionGroup] DeprecatedActionGroup"); + $I->amOnPage("/test.html"); // stepKey: amOnPage + } +} diff --git a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt index 6b709a0cb..bbed61691 100644 --- a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt +++ b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExecuteInSeleniumTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExecuteInSeleniumTest.xml<br>") */ class ExecuteInSeleniumTestCest { diff --git a/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt b/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt index f7618cbf9..ad3696e00 100644 --- a/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt +++ b/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExecuteJsTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExecuteJsTest.xml<br>") */ class ExecuteJsEscapingTestCest { @@ -30,8 +28,8 @@ class ExecuteJsEscapingTestCest { $javaVariableEscape = $I->executeJS("return \$javascriptVariable"); // stepKey: javaVariableEscape $mftfVariableNotEscaped = $I->executeJS("return {$doNotEscape}"); // stepKey: mftfVariableNotEscaped - $persistedDataNotEscaped = $I->executeJS("return " . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); // stepKey: persistedDataNotEscaped - $hookPersistedDataNotEscaped = $I->executeJS("return " . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); // stepKey: hookPersistedDataNotEscaped - $addNewAttributeForRule = $I->executeJS("document.querySelector('entity option[value=" . PersistedObjectHandler::getInstance()->retrieveEntityField('productAttribute', 'attribute_code', 'test') . "]').setAttribute('selected', 'selected')"); // stepKey: addNewAttributeForRule + $persistedDataNotEscaped = $I->executeJS("return " . $I->retrieveEntityField('persisted', 'data', 'test')); // stepKey: persistedDataNotEscaped + $hookPersistedDataNotEscaped = $I->executeJS("return " . $I->retrieveEntityField('persisted', 'data', 'test')); // stepKey: hookPersistedDataNotEscaped + $addNewAttributeForRule = $I->executeJS("document.querySelector('entity option[value=" . $I->retrieveEntityField('productAttribute', 'attribute_code', 'test') . "]').setAttribute('selected', 'selected')"); // stepKey: addNewAttributeForRule } } diff --git a/dev/tests/verification/Resources/ExtendParentDataTest.txt b/dev/tests/verification/Resources/ExtendParentDataTest.txt index fb90599e3..70cb6b70b 100644 --- a/dev/tests/verification/Resources/ExtendParentDataTest.txt +++ b/dev/tests/verification/Resources/ExtendParentDataTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedDataTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedDataTest.xml<br>") */ class ExtendParentDataTestCest { @@ -28,15 +26,7 @@ class ExtendParentDataTestCest */ public function ExtendParentDataTest(AcceptanceTester $I) { - $I->comment("[simpleDataKey] create 'extendParentData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "simpleDataKey", - "test", - "extendParentData", - [], - [] - ); - + $I->createEntity("simpleDataKey", "test", "extendParentData", [], []); // stepKey: simpleDataKey $I->searchAndMultiSelectOption("#selector", ["otherName"]); // stepKey: getName $I->searchAndMultiSelectOption("#selector", ["extendName"]); // stepKey: getNameExtend $I->searchAndMultiSelectOption("#selector", ["item"]); // stepKey: emptyPost diff --git a/dev/tests/verification/Resources/ExtendedActionGroup.txt b/dev/tests/verification/Resources/ExtendedActionGroup.txt index 7456d99ce..8996526ba 100644 --- a/dev/tests/verification/Resources/ExtendedActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedActionGroup.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ExtendedActionGroupCest { diff --git a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt index f52a46c2f..e4a006c8f 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_suiteExtends\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ExtendedChildTestInSuite") * @group ExtendedTestInSuite - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ExtendedChildTestInSuiteCest { diff --git a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt index 3dfeac8f3..1d5af7d3e 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ExtendedChildTestNotInSuite") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ExtendedChildTestNotInSuiteCest { diff --git a/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt b/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt index 21212ba1a..d09e9a0b6 100644 --- a/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt +++ b/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -27,14 +25,7 @@ class ExtendParentDataTestCest */ public function ExtendParentDataTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: simpleDataKey"); - PersistedObjectHandler::getInstance()->createEntity( - "simpleDataKey", - "test", - "extendParentData", - [], - [] - ); + $I->createEntity("simpleDataKey", "test", "extendParentData", [], []); // stepKey: simpleDataKey $I->searchAndMultiSelectOption("#selector", ["otherName"]); $I->searchAndMultiSelectOption("#selector", ["extendName"]); $I->searchAndMultiSelectOption("#selector", ["item"]); diff --git a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt index a9c971b96..fde8842e7 100644 --- a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupTest.xml<br>") */ class ExtendedRemoveActionGroupCest { diff --git a/dev/tests/verification/Resources/ExtendingSkippedTest.txt b/dev/tests/verification/Resources/ExtendingSkippedTest.txt index 681af0fef..93e9b6a60 100644 --- a/dev/tests/verification/Resources/ExtendingSkippedTest.txt +++ b/dev/tests/verification/Resources/ExtendingSkippedTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ChildExtendedTestSkippedParent") * @group Child - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ExtendingSkippedTestCest { diff --git a/dev/tests/verification/Resources/HookActionsTest.txt b/dev/tests/verification/Resources/HookActionsTest.txt index 231353bc9..0b77325c1 100644 --- a/dev/tests/verification/Resources/HookActionsTest.txt +++ b/dev/tests/verification/Resources/HookActionsTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/HookActionsTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/HookActionsTest.xml<br>") */ class HookActionsTestCest { @@ -25,30 +23,9 @@ class HookActionsTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[sampleCreateBefore] create 'sampleCreatedEntity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "sampleCreateBefore", - "hook", - "sampleCreatedEntity", - [], - [] - ); - - $I->comment("[sampleDeleteBefore] delete entity 'sampleCreateBefore'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "sampleCreateBefore", - "hook" - ); - - $I->comment("[sampleCreateForAfter] create 'sampleCreatedEntity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "sampleCreateForAfter", - "hook", - "sampleCreatedEntity", - [], - [] - ); - + $I->createEntity("sampleCreateBefore", "hook", "sampleCreatedEntity", [], []); // stepKey: sampleCreateBefore + $I->deleteEntity("sampleCreateBefore", "hook"); // stepKey: sampleDeleteBefore + $I->createEntity("sampleCreateForAfter", "hook", "sampleCreatedEntity", [], []); // stepKey: sampleCreateForAfter } /** @@ -57,21 +34,8 @@ class HookActionsTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("[sampleCreateAfter] create 'sampleCreatedEntity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "sampleCreateAfter", - "hook", - "sampleCreatedEntity", - [], - [] - ); - - $I->comment("[sampleDeleteAfter] delete entity 'sampleCreateForAfter'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "sampleCreateForAfter", - "hook" - ); - + $I->createEntity("sampleCreateAfter", "hook", "sampleCreatedEntity", [], []); // stepKey: sampleCreateAfter + $I->deleteEntity("sampleCreateForAfter", "hook"); // stepKey: sampleDeleteAfter } /** diff --git a/dev/tests/verification/Resources/LocatorFunctionTest.txt b/dev/tests/verification/Resources/LocatorFunctionTest.txt index 00baeeac5..76c48a921 100644 --- a/dev/tests/verification/Resources/LocatorFunctionTest.txt +++ b/dev/tests/verification/Resources/LocatorFunctionTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/LocatorFunctionTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/LocatorFunctionTest.xml<br>") */ class LocatorFunctionTestCest { @@ -28,26 +26,18 @@ class LocatorFunctionTestCest */ public function LocatorFunctionTest(AcceptanceTester $I) { - $I->comment("[data] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "data", - "test", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("data", "test", "ReplacementPerson", [], []); // stepKey: data $I->click(Locator::contains("'label'", "'Name'")); // stepKey: SimpleLocator $I->click(Locator::contains("'label'", "'Name'")); // stepKey: SimpleLocatorNonShorthand $I->click(Locator::find("'img'", ['title' => 'diagram'])); // stepKey: ArrayLocator $I->click(Locator::contains("string", "'Name'")); // stepKey: OneParamLiteral $I->click(Locator::contains("John", "'Name'")); // stepKey: OneParamData - $I->click(Locator::contains(PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key', 'test'), "'Name'")); // stepKey: OneParamPersisted + $I->click(Locator::contains($I->retrieveEntityField('data', 'key', 'test'), "'Name'")); // stepKey: OneParamPersisted $I->click(Locator::contains("string1", "string2")); // stepKey: TwoParamLiteral $I->click(Locator::contains("John", "Doe")); // stepKey: TwoParamData - $I->click(Locator::contains(PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key2', 'test'))); // stepKey: TwoParamPersisted + $I->click(Locator::contains($I->retrieveEntityField('data', 'key1', 'test'), $I->retrieveEntityField('data', 'key2', 'test'))); // stepKey: TwoParamPersisted $I->click(Locator::contains("string1", "John")); // stepKey: TwoParamMix1 - $I->click(Locator::contains("string1", PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'))); // stepKey: TwoParamMix2 - $I->click(Locator::contains("John", PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'))); // stepKey: TwoParamMix3 + $I->click(Locator::contains("string1", $I->retrieveEntityField('data', 'key1', 'test'))); // stepKey: TwoParamMix2 + $I->click(Locator::contains("John", $I->retrieveEntityField('data', 'key1', 'test'))); // stepKey: TwoParamMix3 } } diff --git a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt index 7d3bfec09..a57ca4471 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/BasicFunctionalTest.xml<br>verification/TestModule/Test/MergeFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/BasicFunctionalTest.xml<br>verification/TestModule/Test/MergeFunctionalTest.xml<br>") */ class MergeMassViaInsertAfterCest { diff --git a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt index 42a0fcf89..7c6fdc906 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/BasicFunctionalTest.xml<br>verification/TestModule/Test/MergeFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/BasicFunctionalTest.xml<br>verification/TestModule/Test/MergeFunctionalTest.xml<br>") */ class MergeMassViaInsertBeforeCest { diff --git a/dev/tests/verification/Resources/MergeSkip.txt b/dev/tests/verification/Resources/MergeSkip.txt index fdfbdbfe4..b2a1b8918 100644 --- a/dev/tests/verification/Resources/MergeSkip.txt +++ b/dev/tests/verification/Resources/MergeSkip.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/MergeFunctionalTest.xml<br>verification/TestModuleMerged/Test/MergeFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/MergeFunctionalTest.xml<br>verification/TestModuleMerged/Test/MergeFunctionalTest.xml<br>") */ class MergeSkipCest { diff --git a/dev/tests/verification/Resources/MergedActionGroupTest.txt b/dev/tests/verification/Resources/MergedActionGroupTest.txt index 636c28627..a9c740127 100644 --- a/dev/tests/verification/Resources/MergedActionGroupTest.txt +++ b/dev/tests/verification/Resources/MergedActionGroupTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class MergedActionGroupTestCest { @@ -26,15 +24,7 @@ class MergedActionGroupTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/MergedReferencesTest.txt b/dev/tests/verification/Resources/MergedReferencesTest.txt index 794ba6370..b3fc29966 100644 --- a/dev/tests/verification/Resources/MergedReferencesTest.txt +++ b/dev/tests/verification/Resources/MergedReferencesTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: MergedReferencesTest") * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/MergeFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/MergeFunctionalTest.xml<br>") */ class MergedReferencesTestCest { diff --git a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt index 186cd404c..5f1db5081 100644 --- a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt +++ b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @group functional - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class MultipleActionGroupsTestCest { @@ -26,15 +24,7 @@ class MultipleActionGroupsTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createPersonParam", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createPersonParam", "hook", "ReplacementPerson", [], []); // stepKey: createPersonParam $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup diff --git a/dev/tests/verification/Resources/PageReplacementTest.txt b/dev/tests/verification/Resources/PageReplacementTest.txt index f6c6b1bac..cda119999 100644 --- a/dev/tests/verification/Resources/PageReplacementTest.txt +++ b/dev/tests/verification/Resources/PageReplacementTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/PageReplacementTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/PageReplacementTest.xml<br>") */ class PageReplacementTestCest { @@ -28,23 +26,15 @@ class PageReplacementTestCest */ public function PageReplacementTest(AcceptanceTester $I) { - $I->comment("[datakey] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "datakey", - "test", - "simpleData", - [], - [] - ); - + $I->createEntity("datakey", "test", "simpleData", [], []); // stepKey: datakey $I->amOnPage("/page.html"); // stepKey: noParamPage $I->amOnPage("/StringLiteral/page.html"); // stepKey: oneParamPageString $I->amOnPage("/John/page.html"); // stepKey: oneParamPageData - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . "/page.html"); // stepKey: oneParamPagePersist + $I->amOnPage("/" . $I->retrieveEntityField('datakey', 'firstname', 'test') . "/page.html"); // stepKey: oneParamPagePersist $I->amOnPage("/StringLiteral1/StringLiteral2.html"); // stepKey: twoParamPageString $I->amOnPage("/John/StringLiteral2.html"); // stepKey: twoParamPageStringData - $I->amOnPage("/John/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . ".html"); // stepKey: twoParamPageDataPersist - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . "/StringLiteral2.html"); // stepKey: twoParamPagePersistString + $I->amOnPage("/John/" . $I->retrieveEntityField('datakey', 'firstname', 'test') . ".html"); // stepKey: twoParamPageDataPersist + $I->amOnPage("/" . $I->retrieveEntityField('datakey', 'firstname', 'test') . "/StringLiteral2.html"); // stepKey: twoParamPagePersistString $I->amOnPage("/" . getenv("MAGENTO_BACKEND_NAME") . "/backend"); // stepKey: onAdminPage $I->amOnPage("/" . getenv("MAGENTO_BACKEND_NAME") . "/StringLiteral/page.html"); // stepKey: oneParamAdminPageString $I->amOnUrl("http://myFullUrl.com/"); // stepKey: onExternalPage diff --git a/dev/tests/verification/Resources/ParameterArrayTest.txt b/dev/tests/verification/Resources/ParameterArrayTest.txt index 52332217b..8918bb619 100644 --- a/dev/tests/verification/Resources/ParameterArrayTest.txt +++ b/dev/tests/verification/Resources/ParameterArrayTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ParameterArrayTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ParameterArrayTest.xml<br>") */ class ParameterArrayTestCest { @@ -28,21 +26,13 @@ class ParameterArrayTestCest */ public function ParameterArrayTest(AcceptanceTester $I) { - $I->comment("[simpleDataKey] create 'simpleParamData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "simpleDataKey", - "test", - "simpleParamData", - [], - [] - ); - + $I->createEntity("simpleDataKey", "test", "simpleParamData", [], []); // stepKey: simpleDataKey $I->searchAndMultiSelectOption("#selector", ["name"]); // stepKey: xmlSimpleReplace $I->searchAndMultiSelectOption("#selector", [msq("simpleParamData") . "prename"]); // stepKey: xmlPrefix $I->searchAndMultiSelectOption("#selector", ["postname" . msq("simpleParamData")]); // stepKey: xmlSuffix - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: persistSimple - $I->searchAndMultiSelectOption("#selector", ["name", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: persistXmlSimple - $I->searchAndMultiSelectOption("#selector", ['someKey' => PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: literalKeyToPersist + $I->searchAndMultiSelectOption("#selector", [$I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: persistSimple + $I->searchAndMultiSelectOption("#selector", ["name", $I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: persistXmlSimple + $I->searchAndMultiSelectOption("#selector", ['someKey' => $I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: literalKeyToPersist $I->searchAndMultiSelectOption("#selector", ['someKey' => "name"]); // stepKey: literalKeyToStatic $I->searchAndMultiSelectOption("#selector", ['someKey' => msq("simpleParamData") . "prename"]); // stepKey: literalKeyToPrefixUnique $I->searchAndMultiSelectOption("#selector", ['someKey' => "postname" . msq("simpleParamData")]); // stepKey: literalKeyToSuffixUnique @@ -51,13 +41,13 @@ class ParameterArrayTestCest $I->unselectOption("#selector", ["name"]); // stepKey: 002 $I->unselectOption("#selector", [msq("simpleParamData") . "prename"]); // stepKey: 003 $I->unselectOption("#selector", ["postname" . msq("simpleParamData")]); // stepKey: 004 - $I->unselectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: 005 - $I->unselectOption("#selector", ["name", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: 006 - $I->pressKey("#selector", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), ['ctrl', 'a'],\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey001 - $I->pressKey("#selector", ['ctrl', 'a'], 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey002 - $I->pressKey("#selector", ['ctrl', 'a'],'new', 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey003 - $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), 'a', "name"]); // stepKey: pressKey004 - $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], 0, [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: pressKey005 + $I->unselectOption("#selector", [$I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: 005 + $I->unselectOption("#selector", ["name", $I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: 006 + $I->pressKey("#selector", $I->retrieveEntityField('simpleDataKey', 'name', 'test'), ['ctrl', 'a'],\Facebook\WebDriver\WebDriverKeys::DELETE,$I->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey001 + $I->pressKey("#selector", ['ctrl', 'a'], 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,$I->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey002 + $I->pressKey("#selector", ['ctrl', 'a'],'new', 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,$I->retrieveEntityField('simpleDataKey', 'name', 'test')); // stepKey: pressKey003 + $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], [$I->retrieveEntityField('simpleDataKey', 'name', 'test'), 'a', "name"]); // stepKey: pressKey004 + $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], 0, [$I->retrieveEntityField('simpleDataKey', 'name', 'test'), $I->retrieveEntityField('simpleDataKey', 'name', 'test')]); // stepKey: pressKey005 $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], [msq("simpleParamData") . "prename", "postname" . msq("simpleParamData")]); // stepKey: pressKey006 } } diff --git a/dev/tests/verification/Resources/ParentExtendedTest.txt b/dev/tests/verification/Resources/ParentExtendedTest.txt index aeae567a2..8c756f010 100644 --- a/dev/tests/verification/Resources/ParentExtendedTest.txt +++ b/dev/tests/verification/Resources/ParentExtendedTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -17,7 +15,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: ParentExtendedTest") * @group Parent - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ExtendedFunctionalTest.xml<br>") */ class ParentExtendedTestCest { diff --git a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt index c6c09c9c7..f6956f5d9 100644 --- a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt +++ b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/ActionGroupFunctionalTest.xml<br>") */ class PersistedAndXmlEntityArgumentsCest { @@ -29,7 +27,7 @@ class PersistedAndXmlEntityArgumentsCest public function PersistedAndXmlEntityArguments(AcceptanceTester $I) { $I->comment("Entering Action Group [afterGroup] FunctionalActionGroupWithXmlAndPersistedData"); - $I->seeInCurrentUrl("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('persistedInTest', 'urlKey', 'test') . ".html?___store=" . msq("uniqueData") . "John"); // stepKey: checkUrlAfterGroup + $I->seeInCurrentUrl("/" . $I->retrieveEntityField('persistedInTest', 'urlKey', 'test') . ".html?___store=" . msq("uniqueData") . "John"); // stepKey: checkUrlAfterGroup $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroupWithXmlAndPersistedData"); } } diff --git a/dev/tests/verification/Resources/PersistedReplacementTest.txt b/dev/tests/verification/Resources/PersistedReplacementTest.txt index eb3642ed1..eb1c9995d 100644 --- a/dev/tests/verification/Resources/PersistedReplacementTest.txt +++ b/dev/tests/verification/Resources/PersistedReplacementTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/PersistedReplacementTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/PersistedReplacementTest.xml<br>") */ class PersistedReplacementTestCest { @@ -25,15 +23,7 @@ class PersistedReplacementTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("[createData1] create 'ReplacementPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData1", - "hook", - "ReplacementPerson", - [], - [] - ); - + $I->createEntity("createData1", "hook", "ReplacementPerson", [], []); // stepKey: createData1 } /** @@ -45,36 +35,28 @@ class PersistedReplacementTestCest */ public function PersistedReplacementTest(AcceptanceTester $I) { - $I->comment("[createdData] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdData", - "test", - "simpleData", - [], - [] - ); - - $I->fillField("#selector", "StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: inputReplace - $I->fillField("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace - $I->fillField("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace2 - $I->fillSecretField("#" . CredentialStore::getInstance()->getSecret("SECRET_PARAM") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace3 - $I->dragAndDrop("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test')); // stepKey: selector12Replace - $I->conditionalClick(PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test'), "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), true); // stepKey: dependentSelectorReplace - $I->amOnUrl(PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . ".html"); // stepKey: urlReplace - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test')]); // stepKey: parameterArrayReplacement - $I->fillField("#selector", "John " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " stringLiteral"); // stepKey: allTypesMixed - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "John", "stringLiteral"]); // stepKey: parameterArrayMixed - $I->seeInPageSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace1 - $I->seeInPageSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace2 - $I->seeInPageSource("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace3 - $I->dontSeeInPageSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace4 - $I->dontSeeInPageSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace5 - $I->dontSeeInPageSource("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace6 - $I->seeInSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace7 - $I->seeInSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace8 - $I->seeInSource("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace9 - $I->dontSeeInSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace10 - $I->dontSeeInSource("StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace11 - $I->dontSeeInSource("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace12 + $I->createEntity("createdData", "test", "simpleData", [], []); // stepKey: createdData + $I->fillField("#selector", "StringBefore " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: inputReplace + $I->fillField("#" . $I->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace + $I->fillField("#" . getenv("MAGENTO_BASE_URL") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace2 + $I->fillSecretField("#" . $I->getSecret("SECRET_PARAM") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test'), "input"); // stepKey: selectorReplace3 + $I->dragAndDrop("#" . $I->retrieveEntityField('createdData', 'firstname', 'test'), $I->retrieveEntityField('createdData', 'lastname', 'test')); // stepKey: selector12Replace + $I->conditionalClick($I->retrieveEntityField('createdData', 'lastname', 'test'), "#" . $I->retrieveEntityField('createdData', 'firstname', 'test'), true); // stepKey: dependentSelectorReplace + $I->amOnUrl($I->retrieveEntityField('createdData', 'firstname', 'test') . ".html"); // stepKey: urlReplace + $I->searchAndMultiSelectOption("#selector", [$I->retrieveEntityField('createdData', 'firstname', 'test'), $I->retrieveEntityField('createdData', 'lastname', 'test')]); // stepKey: parameterArrayReplacement + $I->fillField("#selector", "John " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " stringLiteral"); // stepKey: allTypesMixed + $I->searchAndMultiSelectOption("#selector", [$I->retrieveEntityField('createdData', 'firstname', 'test'), "John", "stringLiteral"]); // stepKey: parameterArrayMixed + $I->seeInPageSource("StringBefore " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace1 + $I->seeInPageSource("StringBefore " . $I->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace2 + $I->seeInPageSource("#" . getenv("MAGENTO_BASE_URL") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace3 + $I->dontSeeInPageSource("StringBefore " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace4 + $I->dontSeeInPageSource("StringBefore " . $I->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace5 + $I->dontSeeInPageSource("#" . getenv("MAGENTO_BASE_URL") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace6 + $I->seeInSource("StringBefore " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace7 + $I->seeInSource("StringBefore " . $I->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace8 + $I->seeInSource("#" . getenv("MAGENTO_BASE_URL") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace9 + $I->dontSeeInSource("StringBefore " . $I->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace10 + $I->dontSeeInSource("StringBefore " . $I->retrieveEntityField('createData1', 'firstname', 'test') . " StringAfter"); // stepKey: htmlReplace11 + $I->dontSeeInSource("#" . getenv("MAGENTO_BASE_URL") . "#" . $I->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: htmlReplace12 } } diff --git a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt index 95aab913f..426003bc2 100644 --- a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt +++ b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/PersistenceActionGroupAppendingTest.xml<br>") */ class PersistenceActionGroupAppendingTestCest { @@ -26,39 +24,11 @@ class PersistenceActionGroupAppendingTestCest public function _before(AcceptanceTester $I) { $I->comment("Entering Action Group [ACTIONGROUPBEFORE] DataPersistenceAppendingActionGroup"); - $I->comment("[createDataACTIONGROUPBEFORE] create 'entity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createDataACTIONGROUPBEFORE", - "hook", - "entity", - [], - [] - ); - - $I->comment("[updateDataACTIONGROUPBEFORE] update 'createDataACTIONGROUPBEFORE' entity to 'newEntity'"); - PersistedObjectHandler::getInstance()->updateEntity( - "createDataACTIONGROUPBEFORE", - "hook", - "newEntity", - [] - ); - - $I->comment("[deleteDataACTIONGROUPBEFORE] delete entity 'createDataACTIONGROUPBEFORE'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createDataACTIONGROUPBEFORE", - "hook" - ); - - $I->comment("[getDataACTIONGROUPBEFORE] get 'someEneity' entity"); - PersistedObjectHandler::getInstance()->getEntity( - "getDataACTIONGROUPBEFORE", - "hook", - "someEneity", - [], - null - ); - - $I->comment(PersistedObjectHandler::getInstance()->retrieveEntityField('createData', 'field', 'hook')); + $I->createEntity("createDataACTIONGROUPBEFORE", "hook", "entity", [], []); // stepKey: createDataACTIONGROUPBEFORE + $I->updateEntity("createDataACTIONGROUPBEFORE", "hook", "newEntity",[]); // stepKey: updateDataACTIONGROUPBEFORE + $I->deleteEntity("createDataACTIONGROUPBEFORE", "hook"); // stepKey: deleteDataACTIONGROUPBEFORE + $I->getEntity("getDataACTIONGROUPBEFORE", "hook", "someEneity", [], null); // stepKey: getDataACTIONGROUPBEFORE + $I->comment($I->retrieveEntityField('createData', 'field', 'hook')); $I->comment("Exiting Action Group [ACTIONGROUPBEFORE] DataPersistenceAppendingActionGroup"); } @@ -72,39 +42,11 @@ class PersistenceActionGroupAppendingTestCest public function PersistenceActionGroupAppendingTest(AcceptanceTester $I) { $I->comment("Entering Action Group [ACTIONGROUP] DataPersistenceAppendingActionGroup"); - $I->comment("[createDataACTIONGROUP] create 'entity' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createDataACTIONGROUP", - "test", - "entity", - [], - [] - ); - - $I->comment("[updateDataACTIONGROUP] update 'createDataACTIONGROUP' entity to 'newEntity'"); - PersistedObjectHandler::getInstance()->updateEntity( - "createDataACTIONGROUP", - "test", - "newEntity", - [] - ); - - $I->comment("[deleteDataACTIONGROUP] delete entity 'createDataACTIONGROUP'"); - PersistedObjectHandler::getInstance()->deleteEntity( - "createDataACTIONGROUP", - "test" - ); - - $I->comment("[getDataACTIONGROUP] get 'someEneity' entity"); - PersistedObjectHandler::getInstance()->getEntity( - "getDataACTIONGROUP", - "test", - "someEneity", - [], - null - ); - - $I->comment(PersistedObjectHandler::getInstance()->retrieveEntityField('createDataACTIONGROUP', 'field', 'test')); + $I->createEntity("createDataACTIONGROUP", "test", "entity", [], []); // stepKey: createDataACTIONGROUP + $I->updateEntity("createDataACTIONGROUP", "test", "newEntity",[]); // stepKey: updateDataACTIONGROUP + $I->deleteEntity("createDataACTIONGROUP", "test"); // stepKey: deleteDataACTIONGROUP + $I->getEntity("getDataACTIONGROUP", "test", "someEneity", [], null); // stepKey: getDataACTIONGROUP + $I->comment($I->retrieveEntityField('createDataACTIONGROUP', 'field', 'test')); $I->comment("Exiting Action Group [ACTIONGROUP] DataPersistenceAppendingActionGroup"); } } diff --git a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt index 0a6deaca8..41251d2fb 100644 --- a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt +++ b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/PersistenceCustomFieldsTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/PersistenceCustomFieldsTest.xml<br>") */ class PersistenceCustomFieldsTestCest { @@ -27,25 +25,9 @@ class PersistenceCustomFieldsTestCest { $createData1Fields['firstname'] = "Mac"; $createData1Fields['lastname'] = "Doe"; - $I->comment("[createData1] create 'DefaultPerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData1", - "hook", - "DefaultPerson", - [], - $createData1Fields - ); - - $createData2Fields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'hook'); - $I->comment("[createData2] create 'uniqueData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData2", - "hook", - "uniqueData", - ["createData1"], - $createData2Fields - ); - + $I->createEntity("createData1", "hook", "DefaultPerson", [], $createData1Fields); // stepKey: createData1 + $createData2Fields['firstname'] = $I->retrieveEntityField('createData1', 'firstname', 'hook'); + $I->createEntity("createData2", "hook", "uniqueData", ["createData1"], $createData2Fields); // stepKey: createData2 } /** @@ -59,88 +41,24 @@ class PersistenceCustomFieldsTestCest { $createdDataFields['favoriteIndex'] = "1"; $createdDataFields['middlename'] = "Kovacs"; - $I->comment("[createdData] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdData", - "test", - "simpleData", - [], - $createdDataFields - ); - + $I->createEntity("createdData", "test", "simpleData", [], $createdDataFields); // stepKey: createdData $createdData3Fields['firstname'] = "Takeshi"; $createdData3Fields['lastname'] = "Kovacs"; - $I->comment("[createdData3] create 'UniquePerson' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdData3", - "test", - "UniquePerson", - ["createdData"], - $createdData3Fields - ); - + $I->createEntity("createdData3", "test", "UniquePerson", ["createdData"], $createdData3Fields); // stepKey: createdData3 $I->comment("Entering Action Group [createdAG] PersistenceActionGroup"); $createDataAG1CreatedAGFields['firstname'] = "string1"; - $I->comment("[createDataAG1CreatedAG] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createDataAG1CreatedAG", - "test", - "simpleData", - [], - $createDataAG1CreatedAGFields - ); - + $I->createEntity("createDataAG1CreatedAG", "test", "simpleData", [], $createDataAG1CreatedAGFields); // stepKey: createDataAG1CreatedAG $createDataAG2CreatedAGFields['firstname'] = "Jane"; - $I->comment("[createDataAG2CreatedAG] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createDataAG2CreatedAG", - "test", - "simpleData", - [], - $createDataAG2CreatedAGFields - ); - - $createDataAG3CreatedAGFields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createdData3', 'firstname', 'test'); - $I->comment("[createDataAG3CreatedAG] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createDataAG3CreatedAG", - "test", - "simpleData", - [], - $createDataAG3CreatedAGFields - ); - + $I->createEntity("createDataAG2CreatedAG", "test", "simpleData", [], $createDataAG2CreatedAGFields); // stepKey: createDataAG2CreatedAG + $createDataAG3CreatedAGFields['firstname'] = $I->retrieveEntityField('createdData3', 'firstname', 'test'); + $I->createEntity("createDataAG3CreatedAG", "test", "simpleData", [], $createDataAG3CreatedAGFields); // stepKey: createDataAG3CreatedAG $I->comment("Exiting Action Group [createdAG] PersistenceActionGroup"); $I->comment("Entering Action Group [AGKEY] DataPersistenceSelfReferenceActionGroup"); - $I->comment("[createData1AGKEY] create 'entity1' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData1AGKEY", - "test", - "entity1", - [], - [] - ); - - $I->comment("[createData2AGKEY] create 'entity2' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData2AGKEY", - "test", - "entity2", - [], - [] - ); - - $createData3AGKEYFields['key1'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData1AGKEY', 'field', 'test'); - $createData3AGKEYFields['key2'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData2AGKEY', 'field', 'test'); - $I->comment("[createData3AGKEY] create 'entity3' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createData3AGKEY", - "test", - "entity3", - [], - $createData3AGKEYFields - ); - + $I->createEntity("createData1AGKEY", "test", "entity1", [], []); // stepKey: createData1AGKEY + $I->createEntity("createData2AGKEY", "test", "entity2", [], []); // stepKey: createData2AGKEY + $createData3AGKEYFields['key1'] = $I->retrieveEntityField('createData1AGKEY', 'field', 'test'); + $createData3AGKEYFields['key2'] = $I->retrieveEntityField('createData2AGKEY', 'field', 'test'); + $I->createEntity("createData3AGKEY", "test", "entity3", [], $createData3AGKEYFields); // stepKey: createData3AGKEY $I->comment("Exiting Action Group [AGKEY] DataPersistenceSelfReferenceActionGroup"); } } diff --git a/dev/tests/verification/Resources/SectionReplacementTest.txt b/dev/tests/verification/Resources/SectionReplacementTest.txt index 5089cfbfd..109c198eb 100644 --- a/dev/tests/verification/Resources/SectionReplacementTest.txt +++ b/dev/tests/verification/Resources/SectionReplacementTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -15,7 +13,7 @@ use Yandex\Allure\Adapter\Model\SeverityLevel; use Yandex\Allure\Adapter\Annotation\TestCaseId; /** - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/SectionReplacementTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/SectionReplacementTest.xml<br>") */ class SectionReplacementTestCest { @@ -47,27 +45,19 @@ class SectionReplacementTestCest $I->click("#Doe" . msq("uniqueData") . " .stringLiteral2"); // stepKey: selectorReplaceTwoParamDataRefMSQSuffix $I->click("#Doe" . msq("uniqueData") . "-stringLiteral2 .stringLiteral3"); // stepKey: selectorReplaceThreeParamDataRefMSQSuffix $I->click("#Doe" . msq("uniqueData") . "-stringLiteral2 .Doe" . msq("uniqueData") . " [stringLiteral3]"); // stepKey: selectorReplaceThreeParamOneDupeDataRefMSQSuffix - $I->comment("[createdData] create 'simpleData' entity"); - PersistedObjectHandler::getInstance()->createEntity( - "createdData", - "test", - "simpleData", - [], - [] - ); - - $I->click("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: selectorReplaceOneParamPersisted - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .stringLiteral2"); // stepKey: selectorReplaceTwoParamPersisted - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 .stringLiteral3"); // stepKey: selectorReplaceThreeParamPersisted - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " [stringLiteral3]"); // stepKey: selectorReplaceThreeParamOneDupePersisted + $I->createEntity("createdData", "test", "simpleData", [], []); // stepKey: createdData + $I->click("#element ." . $I->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: selectorReplaceOneParamPersisted + $I->click("#" . $I->retrieveEntityField('createdData', 'firstname', 'test') . " .stringLiteral2"); // stepKey: selectorReplaceTwoParamPersisted + $I->click("#" . $I->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 .stringLiteral3"); // stepKey: selectorReplaceThreeParamPersisted + $I->click("#" . $I->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 ." . $I->retrieveEntityField('createdData', 'firstname', 'test') . " [stringLiteral3]"); // stepKey: selectorReplaceThreeParamOneDupePersisted $I->click("#element .{$data}"); // stepKey: selectorReplaceOneParamVariable $I->click("#{$data1} .{$data2}"); // stepKey: selectorReplaceTwoParamVariable $I->click("#{$data1}-{$data2} .{$data3}"); // stepKey: selectorReplaceThreeParamVariable $I->click("#John-Doe .John [Tiberius]"); // stepKey: selectorReplaceThreeParamVariableOneDupe - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .John"); // stepKey: selectorReplaceThreeParamMixed1 - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .{$data}"); // stepKey: selectorReplaceThreeParamMixed2 - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " ." . msq("uniqueData") . "John"); // stepKey: selectorReplaceThreeParamMixedMSQPrefix - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .Doe" . msq("uniqueData")); // stepKey: selectorReplaceThreeParamMixedMSQSuffix + $I->click("#stringLiteral1-" . $I->retrieveEntityField('createdData', 'firstname', 'test') . " .John"); // stepKey: selectorReplaceThreeParamMixed1 + $I->click("#stringLiteral1-" . $I->retrieveEntityField('createdData', 'firstname', 'test') . " .{$data}"); // stepKey: selectorReplaceThreeParamMixed2 + $I->click("#stringLiteral1-" . $I->retrieveEntityField('createdData', 'firstname', 'test') . " ." . msq("uniqueData") . "John"); // stepKey: selectorReplaceThreeParamMixedMSQPrefix + $I->click("#stringLiteral1-" . $I->retrieveEntityField('createdData', 'firstname', 'test') . " .Doe" . msq("uniqueData")); // stepKey: selectorReplaceThreeParamMixedMSQSuffix $I->click("#element .1#element .2"); // stepKey: selectorReplaceTwoParamElements $I->click("#element .1#element .{$data}"); // stepKey: selectorReplaceTwoParamMixedTypes $I->click("(//div[@data-role='slide'])[1]/a[@data-element='link'][contains(@href,'')]"); // stepKey: selectorParamWithEmptyString diff --git a/dev/tests/verification/Resources/SkippedTest.txt b/dev/tests/verification/Resources/SkippedTest.txt index 08ff4fd43..95783ca66 100644 --- a/dev/tests/verification/Resources/SkippedTest.txt +++ b/dev/tests/verification/Resources/SkippedTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedTest") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/SkippedTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/SkippedTest.xml<br>") */ class SkippedTestCest { diff --git a/dev/tests/verification/Resources/SkippedTestNoIssues.txt b/dev/tests/verification/Resources/SkippedTestNoIssues.txt index 168077458..e8f4726d9 100644 --- a/dev/tests/verification/Resources/SkippedTestNoIssues.txt +++ b/dev/tests/verification/Resources/SkippedTestNoIssues.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedNoIssuesTest") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/SkippedTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/SkippedTest.xml<br>") * @group skip */ class SkippedTestNoIssuesCest diff --git a/dev/tests/verification/Resources/SkippedTestTwoIssues.txt b/dev/tests/verification/Resources/SkippedTestTwoIssues.txt index 3de81e02f..4a801856e 100644 --- a/dev/tests/verification/Resources/SkippedTestTwoIssues.txt +++ b/dev/tests/verification/Resources/SkippedTestTwoIssues.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedMultipleIssuesTest") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/SkippedTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/SkippedTest.xml<br>") */ class SkippedTestTwoIssuesCest { diff --git a/dev/tests/verification/Resources/SkippedTestWithHooks.txt b/dev/tests/verification/Resources/SkippedTestWithHooks.txt index a86924b94..ad59d48c3 100644 --- a/dev/tests/verification/Resources/SkippedTestWithHooks.txt +++ b/dev/tests/verification/Resources/SkippedTestWithHooks.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: skippedTestWithHooks") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/SkippedTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/SkippedTest.xml<br>") */ class SkippedTestWithHooksCest { diff --git a/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt b/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt index 7e43433a1..0eb546335 100644 --- a/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt +++ b/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Action Group With comment block in arguments and action group body") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/XmlCommentedActionGroupTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/XmlCommentedActionGroupTest.xml<br>") */ class XmlCommentedActionGroupTestCest { diff --git a/dev/tests/verification/Resources/XmlCommentedTest.txt b/dev/tests/verification/Resources/XmlCommentedTest.txt index f77aa5fe4..47d984d9e 100644 --- a/dev/tests/verification/Resources/XmlCommentedTest.txt +++ b/dev/tests/verification/Resources/XmlCommentedTest.txt @@ -2,8 +2,6 @@ namespace Magento\AcceptanceTest\_default\Backend; use Magento\FunctionalTestingFramework\AcceptanceTester; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use \Codeception\Util\Locator; use Yandex\Allure\Adapter\Annotation\Features; use Yandex\Allure\Adapter\Annotation\Stories; @@ -16,7 +14,7 @@ use Yandex\Allure\Adapter\Annotation\TestCaseId; /** * @Title("[NO TESTCASEID]: Test With comment blocks in root element 'tests', in annotations and in test body.") - * @Description("<br><br><b><font size=+0.9>Test files</font></b><br><br>verification/TestModule/Test/XmlCommentedTest.xml<br>") + * @Description("<h3>Test files</h3>verification/TestModule/Test/XmlCommentedTest.xml<br>") */ class XmlCommentedTestCest { diff --git a/dev/tests/verification/Resources/functionalSuiteHooks.txt b/dev/tests/verification/Resources/functionalSuiteHooks.txt index 05ada44f1..908cff8aa 100644 --- a/dev/tests/verification/Resources/functionalSuiteHooks.txt +++ b/dev/tests/verification/Resources/functionalSuiteHooks.txt @@ -122,7 +122,7 @@ class functionalSuiteHooks extends \Codeception\GroupObject // initialize the webdriver session $webDriver->_initializeSession(); $webDriver->amOnPage("some.url"); // stepKey: after - $webDriver->deleteEntityByUrl("deleteThis"); + $webDriver->deleteEntityByUrl("deleteThis"); // stepKey: delete print("Entering Action Group [AC] actionGroupWithTwoArguments"); $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC print("Exiting Action Group [AC] actionGroupWithTwoArguments"); diff --git a/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml new file mode 100644 index 000000000..8f0341c09 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/DeprecatedActionGroup.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd"> + <actionGroup name="DeprecatedActionGroup" deprecated="Deprecated action group"> + <see stepKey="deprecatedSee" userInput="{{DeprecatedData.field}}" selector="{{DeprecatedSection.deprecatedElement}}" /> + </actionGroup> +</actionGroups> diff --git a/dev/tests/verification/TestModule/Data/DeprecatedData.xml b/dev/tests/verification/TestModule/Data/DeprecatedData.xml new file mode 100644 index 000000000..060752419 --- /dev/null +++ b/dev/tests/verification/TestModule/Data/DeprecatedData.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd"> + <entity name="DeprecatedData" deprecated="Data entity deprecated"> + <data key="field">deprecated</data> + </entity> +</entities> diff --git a/dev/tests/verification/TestModule/Page/DeprecatedPage.xml b/dev/tests/verification/TestModule/Page/DeprecatedPage.xml new file mode 100644 index 000000000..316b8b1d7 --- /dev/null +++ b/dev/tests/verification/TestModule/Page/DeprecatedPage.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd"> + <page name="DeprecatedPage" url="/test.html" area="storefront" module="UnknownVendor_TestModule" deprecated="Deprecated page"> + <section name="SampleSection"/> + </page> +</pages> diff --git a/dev/tests/verification/TestModule/Section/DeprecatedSection.xml b/dev/tests/verification/TestModule/Section/DeprecatedSection.xml new file mode 100644 index 000000000..a9ed20d98 --- /dev/null +++ b/dev/tests/verification/TestModule/Section/DeprecatedSection.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<sections xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd"> + <section name="DeprecatedSection" deprecated="Deprecated section"> + <element name="deprecatedElement" type="button" selector="#element" deprecated="Deprecated element"/> + </section> +</sections> diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml index c23a3ce60..1ef25b43d 100644 --- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml @@ -79,6 +79,9 @@ <magentoCLI command="maintenance:enable" arguments=""stuffHere"" timeout="120" stepKey="magentoCli2"/> <magentoCLI command="config:set somePath {{_CREDS.someKey}}" stepKey="magentoCli3"/> <magentoCLI command="config:set somePath {{_CREDS.someKey}}" timeout="120" stepKey="magentoCli4"/> + <magentoCron stepKey="cronAllGroups"/> + <magentoCron groups="index" stepKey="cronSingleGroup"/> + <magentoCron groups="a b c" stepKey="cronMultipleGroups"/> <makeScreenshot userInput="screenShotInput" stepKey="makeScreenshotKey1"/> <maximizeWindow stepKey="maximizeWindowKey1"/> <moveBack stepKey="moveBackKey1"/> @@ -143,4 +146,4 @@ <fillField selector="#bar" userInput="bar" stepKey="fillField2"/> <fillField selector="#baz" userInput="baz" stepKey="fillField3"/> </test> -</tests> \ No newline at end of file +</tests> diff --git a/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml b/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.xml new file mode 100644 index 000000000..733a34e80 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/DeprecatedEntitiesTest.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="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="DeprecatedEntitiesTest"> + <actionGroup ref="DeprecatedActionGroup" stepKey="deprecatedActionGroup" /> + <amOnPage url="{{DeprecatedPage.url}}" stepKey="amOnPage" /> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/DeprecatedTest.xml b/dev/tests/verification/TestModule/Test/DeprecatedTest.xml new file mode 100644 index 000000000..cc5ae4994 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/DeprecatedTest.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="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="DeprecatedTest" deprecated="Test is deprecated"> + <actionGroup ref="DeprecatedActionGroup" stepKey="deprecatedActionGroup" /> + <amOnPage url="{{DeprecatedPage.url}}" stepKey="amOnPage" /> + </test> +</tests> diff --git a/dev/tests/verification/Tests/DeprecatedTest.php b/dev/tests/verification/Tests/DeprecatedTest.php new file mode 100644 index 000000000..78e3326b9 --- /dev/null +++ b/dev/tests/verification/Tests/DeprecatedTest.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace tests\verification\Tests; + +use tests\util\MftfTestCase; + +class DeprecatedTest extends MftfTestCase +{ + /** + * Tests flat generation of a deprecated test which uses deprecated entities. + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testDeprecatedTestEntitiesGeneration() + { + $this->generateAndCompareTest('DeprecatedTest'); + } + + /** + * Tests flat generation of a test which uses deprecated entities. + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testDeprecatedEntitiesOnlyGeneration() + { + $this->generateAndCompareTest('DeprecatedEntitiesTest'); + } +} diff --git a/dev/tests/verification/Tests/SecretCredentialDataTest.php b/dev/tests/verification/Tests/SecretCredentialDataTest.php index 46391feee..d1ef43745 100644 --- a/dev/tests/verification/Tests/SecretCredentialDataTest.php +++ b/dev/tests/verification/Tests/SecretCredentialDataTest.php @@ -37,7 +37,7 @@ public function secretCredentialDataTest(AcceptanceTester $I) $createProductWithFieldOverridesUsingHardcodedData1Fields['price'] = "12.34"; $I->comment("[createProductWithFieldOverridesUsingHardcodedData1] create '_defaultProduct' entity"); - PersistedObjectHandler::getInstance()->createEntity( + $I->createEntity( "createProductWithFieldOverridesUsingHardcodedData1", "test", "_defaultProduct", @@ -46,13 +46,13 @@ public function secretCredentialDataTest(AcceptanceTester $I) ); $createProductWithFieldOverridesUsingSecretCredData1Fields['qty'] = - CredentialStore::getInstance()->getSecret("payment_authorizenet_trans_key"); + $I->getSecret("payment_authorizenet_trans_key"); $createProductWithFieldOverridesUsingSecretCredData1Fields['price'] = - CredentialStore::getInstance()->getSecret("carriers_dhl_account_eu"); + $I->getSecret("carriers_dhl_account_eu"); $I->comment("[createProductWithFieldOverridesUsingSecretCredData1] create '_defaultProduct' entity"); - PersistedObjectHandler::getInstance()->createEntity( + $I->createEntity( "createProductWithFieldOverridesUsingSecretCredData1", "test", "_defaultProduct", @@ -61,14 +61,14 @@ public function secretCredentialDataTest(AcceptanceTester $I) ); $I->fillField("#username", "Hardcoded"); // stepKey: fillFieldUsingHardCodedData1 - $I->fillSecretField("#username", CredentialStore::getInstance()->getSecret("carriers_dhl_id_eu")); + $I->fillSecretField("#username", $I->getSecret("carriers_dhl_id_eu")); // stepKey: fillFieldUsingSecretCredData1 $magentoCliUsingHardcodedData1 = $I->magentoCLI("config:set cms/wysiwyg/enabled 0"); // stepKey: magentoCliUsingHardcodedData1 $I->comment($magentoCliUsingHardcodedData1); $magentoCliUsingSecretCredData1 = $I->magentoCLI("config:set cms/wysiwyg/enabled " . - CredentialStore::getInstance()->getSecret("payment_authorizenet_login")); + $I->getSecret("payment_authorizenet_login")); // stepKey: magentoCliUsingSecretCredData1 $I->comment($magentoCliUsingSecretCredData1); } diff --git a/docs/best-practices.md b/docs/best-practices.md index a3e5f2629..0b95b1c41 100644 --- a/docs/best-practices.md +++ b/docs/best-practices.md @@ -5,12 +5,12 @@ Check out our best practices below to ensure you are getting the absolute most o ## 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 comments if needed. + Add additional explanation in annotations if needed. 2. Provide default values for the arguments that apply to your most common case scenarios. ## `actionGroups` vs `extends` -Use an action group to wraps a set of actions to reuse them multiple times. +Use an action group to wrap a set of actions to reuse them multiple times. Use an [extension] when a test or action group needs to be repeated with the exception of a few steps. @@ -58,12 +58,20 @@ The following pattern is used when merging with `extends`: Name files according to the following patterns to make searching in future more easy: +<!-- {% raw %} --> + #### Test file name Format: {_Admin_ or _Storefront_}{Functionality}_Test.xml_, where Functionality briefly describes the testing functionality. Example: _StorefrontCreateCustomerTest.xml_. +#### Action Group file name + +Format: {_Admin_ or _Storefront_}{Action Group Summary}ActionGroup.xml`, where Action Group Summary describes with a few words what we can expect from it. + +Example: _AdminCreateStoreActionGroup.xml_ + #### Section file name Format: {_Admin_ or _Storefront_}{UI Description}_Section.xml_, where UI Description briefly describes the testing UI. @@ -74,6 +82,8 @@ Example: _AdminNavbarSection.xml_. Format: {Type}_Data.xml_, where Type represents the entity type. +<!-- {% endraw %} --> + Example: _ProductData.xml_. ### Object names @@ -85,18 +95,19 @@ Use the _Foo.camelCase_ naming convention, which is similar to _Classes_ and _cl Use an upper case first letter for: - File names. Example: _StorefrontCreateCustomerTest.xml_ -- Test name attributes. Example: `<test name="TestAllTheThingsTest">`. -- Data entity names. Example: `<entity name="OutOfStockProduct">`. -- Page name. Example: `<page name="AdminLoginPage">`. -- Section name. Example: `<section name="AdminCategorySidebarActionSection">`. -- Action group name. Example: `<actionGroup name="LoginToAdminActionGroup">`. +- Test name attributes. Example: `<test name="TestAllTheThingsTest">` +- Data entity names. Example: `<entity name="OutOfStockProduct">` +- Page name. Example: `<page name="AdminLoginPage">` +- Section name. Example: `<section name="AdminCategorySidebarActionSection">` +- Action group name. Example: `<actionGroup name="LoginToAdminActionGroup">` #### Lower case Use a lower case first letter for: -- Data keys. Example: `<data key="firstName">`. -- Element names. Examples: `<element name="confirmDeleteButton"/>`. +- Data keys. Example: `<data key="firstName">` +- Element names. Examples: `<element name="confirmDeleteButton"/>` +- Step keys. For example: `<click selector="..." stepKey="clickLogin"/>` ## Page object diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md index 2440428f9..b2c36dae4 100644 --- a/docs/commands/mftf.md +++ b/docs/commands/mftf.md @@ -42,6 +42,12 @@ vendor/bin/mftf generate:tests vendor/bin/mftf generate:tests AdminLoginTest StorefrontPersistedCustomerLoginTest ``` +### Generate test by test and suite name + +```bash +vendor/bin/mftf generate:tests LoginSuite:AdminLoginTest +``` + ### Generate and run the tests for a specified group ```bash @@ -58,6 +64,14 @@ vendor/bin/mftf run:test AdminLoginTest StorefrontPersistedCustomerLoginTest -r This command cleans up the previously generated tests; generates and runs the `LoginAsAdminTest` and `LoginAsCustomerTest` tests. +### Generate and run particular test in a specific suite's context + +```bash +vendor/bin/mftf run:test LoginSuite:AdminLoginTest -r +``` + +This command cleans up previously generated tests; generates and run `AdminLoginTest` within the context of the `LoginSuite`. + ### Generate and run a testManifest.txt file ```bash @@ -449,18 +463,46 @@ The example parameters are taken from the `etc/config/.env.example` file. ### `static-checks` -Runs all MFTF static-checks on the test codebase that MFTF is currently attached to. +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. -#### Existing static checks +#### Usage -* Test Dependency: Checks that test dependencies do not violate Magento module's composer dependencies. +```bash +vendor/bin/mftf static-checks [<names>]... +``` -#### Usage +#### Examples + +To check what existing static check scripts are available + +```bash +vendor/bin/mftf static-checks --help +``` + +To run all existing static check scripts ```bash vendor/bin/mftf static-checks ``` +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 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. + ### `upgrade:tests` Applies all the MFTF major version upgrade scripts to test components in the given path (`test.xml`, `data.xml`, etc). diff --git a/docs/configuration.md b/docs/configuration.md index 5140c01e7..9466f2bcc 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -277,6 +277,28 @@ Example: CREDENTIAL_VAULT_SECRET_BASE_PATH=secret ``` +### CREDENTIAL_AWS_SECRETS_MANAGER_REGION + +The region that AWS Secrets Manager is located. + +Example: + +```conf +# Region of AWS Secrets Manager +CREDENTIAL_AWS_SECRETS_MANAGER_REGION=us-east-1 +``` + +### CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE + +The profile used to connect to AWS Secrets Manager. + +Example: + +```conf +# Profile used to connect to AWS Secrets Manager. +CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE=default +``` + ### ENABLE_BROWSER_LOG Enables addition of browser logs to Allure steps diff --git a/docs/credentials.md b/docs/credentials.md index a2850cfe8..402030985 100644 --- a/docs/credentials.md +++ b/docs/credentials.md @@ -3,10 +3,11 @@ When you test functionality that involves external services such as UPS, FedEx, PayPal, or SignifyD, use the MFTF credentials feature to hide sensitive [data][] like integration tokens and API keys. -Currently the MFTF supports two types of credential storage: +Currently the MFTF supports three types of credential storage: - **.credentials file** -- **HashiCorp vault** +- **HashiCorp Vault** +- **AWS Secrets Manager** ## Configure File Storage @@ -135,11 +136,100 @@ CREDENTIAL_VAULT_ADDRESS=http://127.0.0.1:8200 CREDENTIAL_VAULT_SECRET_BASE_PATH=secret ``` -## Configure both File Storage and Vault Storage +## Configure AWS Secrets Manager -It is possible and sometimes useful to setup and use both `.credentials` file and vault for secret storage at the same time. -In this case, the MFTF tests are able to read secret data at runtime from both storage options, but the local `.credentials` file will take precedence. +AWS Secrets Manager offers secret management that supports: +- Secret rotation with built-in integration for Amazon RDS, Amazon Redshift, and Amazon DocumentDB +- Fine-grained policies and permissions +- Audit secret rotation centrally for resources in the AWS Cloud, third-party services, and on-premises +### Prerequisites + +#### Use AWS Secrets Manager from your own AWS account + +- An AWS account with Secrets Manager service +- An IAM user with AWS Secrets Manager access permission + +#### Use AWS Secrets Manager in CI/CD + +- AWS account ID where the AWS Secrets Manager service is hosted +- Authorized CI/CD EC2 instances with AWS Secrets Manager service access IAM role attached + +### Store secrets in AWS Secrets Manager + +#### Secrets format + +`Secret Name` and `Secret Value` are two key pieces of information for creating a secret. + +`Secret Value` can be either plaintext or key/value pairs in JSON format. + +`Secret Name` must use the following format: + +```conf +mftf/<VENDOR>/<YOUR/SECRET/KEY> +``` + +`Secret Value` can be stored in two different formats: plaintext or key/value pairs. + +For plaintext format, `Secret Value` can be any string you want to secure. + +For key/value pairs format, `Secret Value` is a key/value pair with `key` the same as `Secret Name` without `mftf/<VENDOR>/` prefix, which is `<YOUR/SECRET/KEY>`, and value can be any string you want to secure. + +##### Create Secrets using AWS CLI + +```bash +aws secretsmanager create-secret --name "mftf/magento/shipping/carriers_usps_userid" --description "Carriers USPS user id" --secret-string "1234567" +``` + +##### Create Secrets using AWS Console + +- Sign in to the AWS Secrets Manager console +- Choose Store a new secret +- In the Select secret type section, specify "Other type of secret" +- For `Secret Name`, `Secret Key` and `Secret Value` field, for example, to save the same secret in key/value JSON format, you should use + +```conf +# Secret Name +mftf/magento/shipping/carriers_usps_userid + +# Secret Key +shipping/carriers_usps_userid + +# Secret Value +1234567 +``` + +### Setup MFTF to use AWS Secrets Manager + +To use AWS Secrets Manager, the AWS region to connect to is required. You can set it through environment variable [`CREDENTIAL_AWS_SECRETS_MANAGER_REGION`][] in `.env`. + +MFTF uses the recommended [Default Credential Provider Chain][credential chain] to establish connection to AWS Secrets Manager service. +You can setup credentials according to [Default Credential Provider Chain][credential chain] and there is no MFTF specific setup required. +Optionally, however, you can explicitly set AWS profile through environment variable [`CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE`][] in `.env`. + +```conf +# Sample AWS Secrets Manager configuration +CREDENTIAL_AWS_SECRETS_MANAGER_REGION=us-east-1 +CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE=default +``` + +### Optionally set CREDENTIAL_AWS_ACCOUNT_ID environment variable + +In case AWS credentials cannot resolve to a valid AWS account, full AWS KMS ([Key Management Service][]) key ARN ([Amazon Resource Name][]) is required. +You will also need to set `CREDENTIAL_AWS_ACCOUNT_ID` environment variable so that MFTF can construct the full ARN. This is mostly used for CI/CD. + +```bash +export CREDENTIAL_AWS_ACCOUNT_ID=<Your_12_Digits_AWS_Account_ID> +``` + +## Configure multiple credential storage + +It is possible and sometimes useful to setup and use multiple credential storage at the same time. +In this case, the MFTF tests are able to read secret data at runtime from all storage options, in this case MFTF use the following precedence: + +``` +.credentials File > HashiCorp Vault > AWS Secrets Manager +``` <!-- {% raw %} --> ## Use credentials in a test @@ -150,7 +240,7 @@ Define the value as a reference to the corresponding key in the credentials file - `_CREDS` is an environment constant pointing to the `.credentials` file - `my_data_key` is a key in the the `.credentials` file or vault that contains the value to be used in a test step - - for File Storage, ensure your key contains the vendor prefix, i.e. `vendor/my_data_key` + - for File Storage, ensure your key contains the vendor prefix, which is `vendor/my_data_key` For example, to reference secret data in the [`fillField`][] action, use the `userInput` attribute using a typical File Storage: @@ -183,3 +273,8 @@ The MFTF tests delivered with Magento application do not use credentials and do [Vault KV2]: https://www.vaultproject.io/docs/secrets/kv/kv-v2.html [`CREDENTIAL_VAULT_ADDRESS`]: configuration.md#credential_vault_address [`CREDENTIAL_VAULT_SECRET_BASE_PATH`]: configuration.md#credential_vault_secret_base_path +[credential chain]: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html +[`CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE`]: configuration.md#credential_aws_secrets_manager_profile +[`CREDENTIAL_AWS_SECRETS_MANAGER_REGION`]: configuration.md#credential_aws_secrets_manager_region +[Key Management Service]: https://aws.amazon.com/kms/ +[Amazon Resource Name]: https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html \ No newline at end of file diff --git a/docs/extending.md b/docs/extending.md index 91dc97c5d..064ed3208 100644 --- a/docs/extending.md +++ b/docs/extending.md @@ -26,7 +26,7 @@ __Use case__: Create two similar tests with different `url` (`"{{AdminCategoryPa > Test with "extends": ```xml -<tests > +<tests> <test name="AdminCategoryTest"> <annotations> ... @@ -47,7 +47,7 @@ __Use case__: Create two similar tests with different `url` (`"{{AdminCategoryPa > Test without "extends": ```xml -<tests > +<tests> <test name="AdminCategoryTest"> <annotations> ... @@ -77,7 +77,7 @@ __Use case__: Create two similar tests where the second test contains two additi > Tests with "extends": ```xml -<tests > +<tests> <test name="LogInAsAdminTest"> <amOnPage url="{{AdminLoginPage}}" stepKey="navigateToAdmin"/> <fillField selector="{{AdminLoginFormSection.username}}" userInput="admin" stepKey="fillUsername"/> @@ -95,7 +95,7 @@ __Use case__: Create two similar tests where the second test contains two additi > Tests without "extends": ```xml -<tests > +<tests> <test name="LogInAsAdminTest"> <amOnPage url="{{AdminLoginPage}}" stepKey="navigateToAdmin"/> <fillField selector="{{AdminLoginFormSection.username}}" userInput="admin" stepKey="fillUsername"/> @@ -125,7 +125,7 @@ __Use case__: Create two similar tests where the second one contains two additio > Tests with "extends": ```xml -<tests > +<tests> <test name="LogInAsAdminTest"> <before> <amOnPage url="{{AdminLoginPage}}" stepKey="navigateToAdmin"/> @@ -147,7 +147,7 @@ __Use case__: Create two similar tests where the second one contains two additio > Tests without "extends": ```xml -<tests > +<tests> <test name="LogInAsAdminTest"> <before> <amOnPage url="{{AdminLoginPage}}" stepKey="navigateToAdmin"/> @@ -295,7 +295,7 @@ __Use case__: Create an entity named `DivPanelGreen`, which is similar to the `D > Entities with "extends": ```xml -<entities > +<entities> <entity name="DivPanel"> <data key="divColor">Red</data> <data key="divSize">80px</data> @@ -310,7 +310,7 @@ __Use case__: Create an entity named `DivPanelGreen`, which is similar to the `D > Entities without "extends": ```xml -<entities > +<entities> <entity name="DivPanel"> <data key="divColor">Red</data> <data key="divSize">80px</data> @@ -331,7 +331,7 @@ __Use case__: Create an entity named `DivPanelGreen`, which is similar to the `D > Entities with "extends": ```xml -<entities > +<entities> <entity name="DivPanel"> <data key="divColor">Red</data> <data key="divSize">80px</data> @@ -347,7 +347,7 @@ __Use case__: Create an entity named `DivPanelGreen`, which is similar to the `D > Entities without "extends": ```xml -<entities > +<entities> <entity name="DivPanel"> <data key="divColor">Red</data> <data key="divSize">80px</data> diff --git a/docs/mftf-tests.md b/docs/mftf-tests.md index 08d1c59a1..4505975a9 100644 --- a/docs/mftf-tests.md +++ b/docs/mftf-tests.md @@ -12,11 +12,11 @@ dl dt{ The Magento Functional Testing Framework runs tests on every Module within Magento. These files are stored within each Module folder in the Magento repo. This page lists all those tests so that developers can have a good sense of what is covered. -{% include mftf/functional_data.md %} +{% include mftf/mftf_data.md %} {% for item in mftf %} -### {{ item.name }} +### {{ item.name }} {% for file in item.items %} #### [{{ file.filename }}]({{file.repo}}) {: .mftf-test-link} diff --git a/docs/test/action-groups.md b/docs/test/action-groups.md index 0743481f6..5fdfbb522 100644 --- a/docs/test/action-groups.md +++ b/docs/test/action-groups.md @@ -10,8 +10,10 @@ The following diagram shows the structure of an MFTF action group: The following conventions apply to MFTF action groups: -- All action groups are declared in XML files and stored in the `<module>/ActionGroup/` directory. -- Every file name ends with `ActionGroup`, such as `LoginToAdminActionGroup`. +- 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 The XML format for the `actionGroups` declaration is: @@ -34,32 +36,31 @@ The XML format for the `actionGroups` declaration is: These examples build a declaration for a group of actions that grant authorization to the Admin area, and use the declaration in a test. -The _Backend/ActionGroup/LoginToAdminActionGroup.xml_ `<actionGroup>` relates to the functionality of the _Backend_ module. -In [test][], the name and identifier of the `<actionGroup>` is used as a reference in the `ref` parameter, such as `ref="LoginToAdminActionGroup"`. +The _Magento/Backend/Test/Mftf/ActionGroup/LoginAsAdminActionGroup.xml_ `<actionGroup>` relates to the functionality of the _Magento_Backend_ module. + +In [test][], the name and identifier of the `<actionGroup>` is used as a reference in the `ref` parameter, such as `ref="LoginAsAdminActionGroup"`. ### Create an action group declaration To create the `<actionGroup>` declaration: -1. Begin with a _Backend/ActionGroup/LoginToAdminActionGroup.xml_ template for the `<actionGroup>`: +1. Begin with a template for the `<actionGroup>`: ```xml <?xml version="1.0" encoding="UTF-8"?> <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="LoginToAdminActionGroup"> - ... + <actionGroup name="{Action Group Name}"> + </actionGroup> </actionGroups> ``` -<!-- {% raw %} --> - 1. Add actions to the `actionGroup` arguments: ```xml - <actionGroup name="LoginToAdminActionGroup"> + <actionGroup name="LoginAsAdminActionGroup"> <fillField stepKey="fillUsername" selector="#username" userInput="{{adminUser.username}}" /> <fillField stepKey="fillPassword" selector="#password" userInput="{{adminUser.password}}" /> <click stepKey="click" selector="#login" /> @@ -81,14 +82,20 @@ To create the `<actionGroup>` declaration: <actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - <actionGroup name="LoginToAdminActionGroup"> - <arguments> - <argument name="adminUser" defaultValue="_defaultAdmin"/> - </arguments> - <fillField stepKey="fillUsername" selector="#username" userInput="{{adminUser.username}}" /> - <fillField stepKey="fillPassword" selector="#password" userInput="{{adminUser.password}}" /> - <click stepKey="click" selector="#login" /> - </actionGroup> + <actionGroup name="LoginAsAdmin"> + <annotations> + <description>Login to Backend Admin using provided User Data. PLEASE NOTE: This Action Group does NOT validate that you are Logged In.</description> + </annotations> + <arguments> + <argument name="adminUser" type="entity" defaultValue="DefaultAdminUser"/> + </arguments> + + <amOnPage url="{{AdminLoginPage.url}}" stepKey="navigateToAdmin"/> + <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.username}}" stepKey="fillUsername"/> + <fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.password}}" stepKey="fillPassword"/> + <click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/> + <closeAdminNotification stepKey="closeAdminNotification"/> + </actionGroup> </actionGroups> ``` @@ -97,23 +104,23 @@ To create the `<actionGroup>` declaration: In this test example, we want to add the following set of actions: ```xml -<fillField stepKey="fillUsername" selector="#username" userInput="{{CustomAdminUser.username}}" /> -<fillField stepKey="fillPassword" selector="#password" userInput="{{CustomAdminUser.password}}" /> -<click stepKey="click" selector="#login" /> +<fillField selector="{{AdminLoginFormSection.username}}" userInput="{{adminUser.username}}" stepKey="fillUsername"/> +<fillField selector="{{AdminLoginFormSection.password}}" userInput="{{adminUser.password}}" stepKey="fillPassword"/> +<click selector="{{AdminLoginFormSection.signIn}}" stepKey="clickLogin"/> ``` -Instead of adding this set of actions, use the _LoginToAdminActionGroup_ `<actionGroup>` declaration in tests: +Instead of adding this set of actions, use the _LoginAsAdminActionGroup_ `<actionGroup>` declaration in tests: -1. Reference the `LoginToAdminActionGroup` action group: +1. Reference the `LoginAsAdminActionGroup` action group: ```xml - <actionGroup stepKey="loginToAdminPanel" ref="LoginToAdminActionGroup"/> + <actionGroup stepKey="loginToAdminPanel" ref="LoginAsAdminActionGroup"/> ``` 1. Update the argument name/value pair to `adminUser` and `CustomAdminUser`: ```xml - <actionGroup stepKey="loginToAdminPanel" ref="LoginToAdminActionGroup"> + <actionGroup stepKey="loginToAdminPanel" ref="LoginAsAdminActionGroup"> <argument name="adminUser" value="CustomAdminUser"/> </actionGroup> ``` @@ -196,30 +203,34 @@ Starting with an action group such as: ``` It can be reworked into more manageable pieces, as below. These smaller steps are easier to read, update, and reuse. - -```xml -<actionGroup name="GoToCategoryGridAndAddNewCategory"> - <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> - <click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategory"/> - <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Category" stepKey="seeCategoryPageTitle"/> -</actionGroup> - -<actionGroup name="FillInBasicCategoryFields"> - <arguments> - <argument name="categoryEntity" defaultValue="_defaultCategory"/> - </arguments> - <fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{categoryEntity.name}}" stepKey="enterCategoryName"/> - <click selector="{{AdminCategorySEOSection.SectionHeader}}" stepKey="openSEO"/> - <fillField selector="{{AdminCategorySEOSection.UrlKeyInput}}" userInput="{{categoryEntity.name_lwr}}" stepKey="enterURLKey"/> -</actionGroup> - -<actionGroup name="SaveAndVerifyCategoryCreation"> - <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/> - <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/> - <seeInTitle userInput="{{categoryEntity.name}}" stepKey="seeNewCategoryPageTitle"/> - <seeElement selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryEntity.name)}}" stepKey="seeCategoryInTree"/> -</actionGroup> -``` +* GoToCategoryGridAndAddNewCategory + ```xml + <actionGroup name="GoToCategoryGridAndAddNewCategory"> + <seeInCurrentUrl url="{{AdminCategoryPage.url}}" stepKey="seeOnCategoryPage"/> + <click selector="{{AdminCategorySidebarActionSection.AddSubcategoryButton}}" stepKey="clickOnAddSubCategory"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Category" stepKey="seeCategoryPageTitle"/> + </actionGroup> + ``` +* FillInBasicCategoryFields + ```xml + <actionGroup name="FillInBasicCategoryFields"> + <arguments> + <argument name="categoryEntity" defaultValue="_defaultCategory"/> + </arguments> + <fillField selector="{{AdminCategoryBasicFieldSection.CategoryNameInput}}" userInput="{{categoryEntity.name}}" stepKey="enterCategoryName"/> + <click selector="{{AdminCategorySEOSection.SectionHeader}}" stepKey="openSEO"/> + <fillField selector="{{AdminCategorySEOSection.UrlKeyInput}}" userInput="{{categoryEntity.name_lwr}}" stepKey="enterURLKey"/> + </actionGroup> + ``` +* SaveAndVerifyCategoryCreation + ```xml + <actionGroup name="SaveAndVerifyCategoryCreation"> + <click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveCategory"/> + <seeElement selector="{{AdminCategoryMessagesSection.SuccessMessage}}" stepKey="assertSuccess"/> + <seeInTitle userInput="{{categoryEntity.name}}" stepKey="seeNewCategoryPageTitle"/> + <seeElement selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryEntity.name)}}" stepKey="seeCategoryInTree"/> + </actionGroup> + ``` <!-- {% endraw %} --> @@ -261,4 +272,4 @@ Attribute|Type|Use|Description [actions]: ./actions.md [test]: ../test.md [`argument`]: #argument-tag -[created]: ../data.md#persist-data \ No newline at end of file +[created]: ../data.md#persist-data diff --git a/docs/test/actions.md b/docs/test/actions.md index c5dc83fdb..59fd12aa2 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -1274,6 +1274,29 @@ Attribute|Type|Use|Description <magentoCLI command="indexer:reindex" stepKey="reindex"/> ``` +### magentoCron + +Used to execute Magento Cron jobs. Groups may be provided optionally. Internal mechanism of `<magentoCron>` ensures that Cron Job of single group is ran with 60 seconds interval. + +Attribute|Type|Use|Description +---|---|---|--- +`groups`|string |optional| Run only specified groups of Cron Jobs +`arguments`|string |optional| Unescaped arguments to be passed in with the CLI command. +`timeout`|string|optional| Number of seconds CLI command can run without outputting anything. +`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 +<magentoCron stepKey="runStagingCronJobs" groups="staging"/> +<!-- No interval here --> +<magentoCron stepKey="runIndexCronJobs" groups="index"/> +<!-- 60 seconds interval takes place here --> +<magentoCron stepKey="runAllCronJobs"/> +``` + ### makeScreenshot See [makeScreenshot docs on codeception.com](http://codeception.com/docs/modules/WebDriver#makeScreenshot). diff --git a/docs/tips-tricks.md b/docs/tips-tricks.md index 4f7539c6d..a2300c3bf 100644 --- a/docs/tips-tricks.md +++ b/docs/tips-tricks.md @@ -419,5 +419,5 @@ BAD: <!--{% endraw %}--> <!-- Link Definitions --> -[This test]: https://github.com/magento/magento2/blob/2.3-develop/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml#L24 -[Data file]: https://github.com/magento/magento2/blob/2.3-develop/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml +[This test]: https://github.com/magento/magento2/blob/2.3/app/code/Magento/Captcha/Test/Mftf/Test/StorefrontCaptchaRegisterNewCustomerTest.xml#L24 +[Data file]: https://github.com/magento/magento2/blob/2.3/app/code/Magento/Captcha/Test/Mftf/Data/CaptchaConfigData.xml diff --git a/etc/config/.env.example b/etc/config/.env.example index 7320d8b8b..f5b6ef40e 100644 --- a/etc/config/.env.example +++ b/etc/config/.env.example @@ -30,10 +30,14 @@ BROWSER=chrome #MAGENTO_RESTAPI_SERVER_PORT=8080 #MAGENTO_RESTAPI_SERVER_PROTOCOL=https -#*** Uncomment and set vault address and secret base path if you want to use vault to manage _CREDS secrets ***# +#*** To use HashiCorp Vault to manage _CREDS secrets, uncomment and set vault address and secret base path ***# #CREDENTIAL_VAULT_ADDRESS=http://127.0.0.1:8200 #CREDENTIAL_VAULT_SECRET_BASE_PATH=secret +#*** To use AWS Secrets Manager to manage _CREDS secrets, uncomment and set region, profile is optional, when omitted, AWS default credential provider chain will be used ***# +#CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE=default +#CREDENTIAL_AWS_SECRETS_MANAGER_REGION=us-east-1 + #*** Uncomment these properties to set up a dev environment with symlinked projects ***# #TESTS_BP= #FW_BP= diff --git a/etc/config/functional.suite.dist.yml b/etc/config/functional.suite.dist.yml index 5487a3c99..319804d7a 100644 --- a/etc/config/functional.suite.dist.yml +++ b/etc/config/functional.suite.dist.yml @@ -16,6 +16,7 @@ modules: - \Magento\FunctionalTestingFramework\Helper\MagentoFakerData - \Magento\FunctionalTestingFramework\Module\MagentoSequence - \Magento\FunctionalTestingFramework\Module\MagentoAssert + - \Magento\FunctionalTestingFramework\Module\MagentoActionProxies - Asserts config: \Magento\FunctionalTestingFramework\Module\MagentoWebDriver: diff --git a/etc/di.xml b/etc/di.xml index 3e6313bf3..e5e31cf87 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|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|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"> ]> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../src/Magento/FunctionalTestingFramework/ObjectManager/etc/config.xsd"> diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 4bce08d9f..e9e1c344c 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -8,7 +8,8 @@ use Codeception\Step\Comment; use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; -use \Magento\FunctionalTestingFramework\Util\TestGenerator; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; +use Magento\FunctionalTestingFramework\Util\TestGenerator; use Yandex\Allure\Adapter\Model\Status; use Yandex\Allure\Adapter\Model\Step; use Yandex\Allure\Codeception\AllureCodeception; @@ -41,6 +42,13 @@ class MagentoAllureAdapter extends AllureCodeception */ private $testFiles = []; + /** + * Boolean value to indicate if steps are invisible steps + * + * @var boolean + */ + private $atInvisibleSteps = false; + /** * Array of group values passed to test runner command * @@ -125,6 +133,19 @@ private function sanitizeGroupName($group) */ public function stepBefore(StepEvent $stepEvent) { + $stepAction = $stepEvent->getStep()->getAction(); + + // Set atInvisibleSteps flag and return if step is in INVISIBLE_STEP_ACTIONS + if (in_array($stepAction, ActionObject::INVISIBLE_STEP_ACTIONS)) { + $this->atInvisibleSteps = true; + return; + } + + // Set back atInvisibleSteps flag + if ($this->atInvisibleSteps && !in_array($stepAction, ActionObject::INVISIBLE_STEP_ACTIONS)) { + $this->atInvisibleSteps = false; + } + //Hard set to 200; we don't expose this config in MFTF $argumentsLength = 200; $stepKey = null; @@ -134,11 +155,9 @@ public function stepBefore(StepEvent $stepEvent) } // DO NOT alter action if actionGroup is starting, need the exact actionGroup name for good logging - if (strpos($stepEvent->getStep()->getAction(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false - || $stepEvent->getStep() instanceof Comment + if (strpos($stepAction, ActionGroupObject::ACTION_GROUP_CONTEXT_START) === false + && !($stepEvent->getStep() instanceof Comment) ) { - $stepAction = $stepEvent->getStep()->getAction(); - } else { $stepAction = $stepEvent->getStep()->getHumanizedActionWithoutArguments(); } $stepArgs = $stepEvent->getStep()->getArgumentsAsString($argumentsLength); @@ -169,9 +188,18 @@ public function stepBefore(StepEvent $stepEvent) */ public function stepAfter(StepEvent $stepEvent = null) { + // Simply return if step is INVISIBLE_STEP_ACTIONS + if ($this->atInvisibleSteps) { + if ($stepEvent->getStep()->hasFailed()) { + $this->atInvisibleSteps = false; + } + return; + } + if ($stepEvent->getStep()->hasFailed()) { $this->getLifecycle()->fire(new StepFailedEvent()); } + $this->getLifecycle()->fire(new StepFinishedEvent()); } diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 0ba1a3b2f..90f04abae 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -7,16 +7,27 @@ namespace Magento\FunctionalTestingFramework\Codeception\Subscriber; use Codeception\Event\StepEvent; +use Codeception\Event\TestEvent; use Codeception\Lib\Console\Message; use Codeception\Step; use Codeception\Step\Comment; use Codeception\Test\Interfaces\ScenarioDriven; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\Util\TestGenerator; use Symfony\Component\Console\Formatter\OutputFormatter; +/** + * @SuppressWarnings(PHPMD) + */ class Console extends \Codeception\Subscriber\Console { + /** + * Regular expresion to find deprecated notices. + */ + const DEPRECATED_NOTICE = '/<li>(?<deprecatedMessage>.*?)<\/li>/m'; + /** * Test files cache. * @@ -31,6 +42,13 @@ class Console extends \Codeception\Subscriber\Console */ private $actionGroupStepKey = null; + /** + * Boolean value to indicate if steps are invisible steps + * + * @var boolean + */ + private $atInvisibleSteps = false; + /** * Console constructor. Parent constructor requires codeception CLI options, and does not have its own configs. * Constructor is only different than parent due to the way Codeception instantiates Extensions. @@ -45,6 +63,36 @@ public function __construct($extensionOptions = [], $options = []) parent::__construct($options); } + /** + * Triggered event before each test. + * + * @param TestEvent $e + * @return void + * @throws \Exception + */ + public function startTest(TestEvent $e) + { + $test = $e->getTest()->getTestClass(); + try { + $testReflection = new \ReflectionClass($test); + $isDeprecated = preg_match_all(self::DEPRECATED_NOTICE, $testReflection->getDocComment(), $match); + if ($isDeprecated) { + $this->message('DEPRECATION NOTICE(S): ') + ->style('debug') + ->writeln(); + foreach ($match['deprecatedMessage'] as $deprecatedMessage) { + $this->message(' - ' . $deprecatedMessage) + ->style('debug') + ->writeln(); + } + } + } catch (\ReflectionException $e) { + LoggingUtil::getInstance()->getLogger(self::class)->error($e->getMessage(), $e->getTrace()); + } + + parent::startTest($e); + } + /** * Printing stepKey in before step action. * @@ -57,6 +105,19 @@ public function beforeStep(StepEvent $e) return; } + $stepAction = $e->getStep()->getAction(); + + // Set atInvisibleSteps flag and return if step is in INVISIBLE_STEP_ACTIONS + if (in_array($stepAction, ActionObject::INVISIBLE_STEP_ACTIONS)) { + $this->atInvisibleSteps = true; + return; + } + + // Set back atInvisibleSteps flag + if ($this->atInvisibleSteps && !in_array($stepAction, ActionObject::INVISIBLE_STEP_ACTIONS)) { + $this->atInvisibleSteps = false; + } + $metaStep = $e->getStep()->getMetaStep(); if ($metaStep and $this->metaStep != $metaStep) { $this->message(' ' . $metaStep->getPrefix()) @@ -77,9 +138,14 @@ public function beforeStep(StepEvent $e) */ public function afterStep(StepEvent $e) { - parent::afterStep($e); + // Do usual after step if step is not INVISIBLE_STEP_ACTIONS + if (!$this->atInvisibleSteps) { + parent::afterStep($e); + } + if ($e->getStep()->hasFailed()) { $this->actionGroupStepKey = null; + $this->atInvisibleSteps = false; } } diff --git a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php index 2f2cb8ad3..db96b010c 100644 --- a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php +++ b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php @@ -235,7 +235,8 @@ protected function validateSchema($configMerger, $filename = null) $error = str_replace(PHP_EOL, "", $error); LoggingUtil::getInstance()->getLogger(Filesystem::class)->criticalFailure( "Schema validation error ", - ($filename ? [ "file"=> $filename, "error" => $error]: ["error" => $error]) + ($filename ? [ "file"=> $filename, "error" => $error]: ["error" => $error]), + true ); } throw new \Exception("Schema validation errors found in xml file(s)" . $filename); diff --git a/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php b/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php index 0953e9d68..a0d94b16e 100644 --- a/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/BaseGenerateCommand.php @@ -87,6 +87,10 @@ protected function getTestAndSuiteConfiguration(array $tests) $suiteToTestPair = []; foreach($tests as $test) { + if (strpos($test, ':') !== false) { + $suiteToTestPair[] = $test; + continue; + } if (array_key_exists($test, $testsReferencedInSuites)) { $suites = $testsReferencedInSuites[$test]; foreach ($suites as $suite) { diff --git a/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php b/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php index 98d121d40..6ea37785d 100644 --- a/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php @@ -94,21 +94,31 @@ protected function execute(InputInterface $input, OutputInterface $output): int $command->run(new ArrayInput($args), $output); } - $codeceptionCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional --verbose --steps'; + $commandString = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' run functional --verbose --steps'; + $exitCode = -1; + $returnCodes = []; foreach ($groups as $group) { - $codeceptionCommand .= " -g {$group}"; - } + $codeceptionCommandString = $commandString . " -g {$group}"; + + $process = new Process($codeceptionCommandString); + $process->setWorkingDirectory(TESTS_BP); + $process->setIdleTimeout(600); + $process->setTimeout(0); - $process = new Process($codeceptionCommand); - $process->setWorkingDirectory(TESTS_BP); - $process->setIdleTimeout(600); - $process->setTimeout(0); + $returnCodes[] = $process->run( + function ($type, $buffer) use ($output) { + $output->write($buffer); + } + ); + } - return $process->run( - function ($type, $buffer) use ($output) { - $output->write($buffer); + foreach ($returnCodes as $returnCode) { + if ($returnCode != 0) { + return $returnCode; } - ); + $exitCode = 0; + } + return $exitCode; } } diff --git a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php index 9757f494e..30c9cd600 100644 --- a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php @@ -8,10 +8,12 @@ namespace Magento\FunctionalTestingFramework\Console; +use Magento\FunctionalTestingFramework\StaticCheck\StaticCheckInterface; use Magento\FunctionalTestingFramework\StaticCheck\StaticChecksList; -use Magento\FunctionalTestingFramework\StaticCheck\StaticCheckListInterface; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Exception; @@ -19,11 +21,18 @@ class StaticChecksCommand extends Command { /** - * Pool of static check scripts to run + * Pool of all existing static check objects * - * @var StaticCheckListInterface + * @var StaticCheckInterface[] */ - private $staticChecksList; + private $allStaticCheckObjects; + + /** + * Static checks to run + * + * @var StaticCheckInterface[] + */ + private $staticCheckObjects; /** * Configures the current command. @@ -32,13 +41,22 @@ class StaticChecksCommand extends Command */ 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}"; $this->setName('static-checks') - ->setDescription('This command will run all static checks on xml test materials.'); - $this->staticChecksList = new StaticChecksList(); + ->setDescription($description) + ->addArgument( + 'names', + InputArgument::OPTIONAL | InputArgument::IS_ARRAY, + 'name(s) of specific static check script(s) to run' + ); } /** - * + * Run required static check scripts * * @param InputInterface $input * @param OutputInterface $output @@ -47,11 +65,23 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $staticCheckObjects = $this->staticChecksList->getStaticChecks(); + try { + $this->validateInputArguments($input, $output); + } catch (InvalidArgumentException $e) { + LoggingUtil::getInstance()->getLogger(StaticChecksCommand::class)->error($e->getMessage()); + $output->writeln($e->getMessage() . " Please fix input arguments and rerun."); + return 1; + } $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 + ); - foreach ($staticCheckObjects as $staticCheck) { $staticCheck->execute($input); $staticOutput = $staticCheck->getOutput(); @@ -66,4 +96,38 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } } + + /** + * Validate input arguments + * + * @param InputInterface $input + * @return void + * @throws InvalidArgumentException + */ + private function validateInputArguments(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 + 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]; + } + } + } + + if (!empty($invalidCheckNames)) { + throw new InvalidArgumentException( + "Invalid static check script(s): " . implode(', ', $invalidCheckNames) . "." + ); + } + } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index 94ff40069..d6e6b9a69 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -6,23 +6,37 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers; +use Magento\FunctionalTestingFramework\Exceptions\Collector\ExceptionCollector; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\BaseStorage; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\VaultStorage; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\AwsSecretsManagerStorage; use Magento\FunctionalTestingFramework\Util\Path\UrlFormatter; class CredentialStore { const ARRAY_KEY_FOR_VAULT = 'vault'; const ARRAY_KEY_FOR_FILE = 'file'; + const ARRAY_KEY_FOR_AWS_SECRETS_MANAGER = 'aws'; + + const CREDENTIAL_STORAGE_INFO = 'You need to configure at least one of these options: ' + . '.credentials file, HashiCorp Vault or AWS Secrets Manager correctly'; /** * Credential storage array * - * @var array + * @var BaseStorage[] */ private $credStorage = []; + /** + * Boolean to indicate if credential storage have been initialized + * + * @var boolean + */ + private $initialized; + /** * Singleton instance * @@ -30,11 +44,17 @@ class CredentialStore */ private static $INSTANCE = null; + /** + * Exception contexts + * + * @var ExceptionCollector + */ + private $exceptionContexts; + /** * Static singleton getter for CredentialStore Instance * * @return CredentialStore - * @throws TestFrameworkException */ public static function getInstance() { @@ -47,35 +67,11 @@ public static function getInstance() /** * CredentialStore constructor - * - * @throws TestFrameworkException */ private function __construct() { - // Initialize file storage - try { - $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); - } catch (TestFrameworkException $e) { - } - - // Initialize vault storage - $cvAddress = getenv('CREDENTIAL_VAULT_ADDRESS'); - $cvSecretPath = getenv('CREDENTIAL_VAULT_SECRET_BASE_PATH'); - if ($cvAddress !== false && $cvSecretPath !== false) { - try { - $this->credStorage[self::ARRAY_KEY_FOR_VAULT] = new VaultStorage( - UrlFormatter::format($cvAddress, false), - '/' . trim($cvSecretPath, '/') - ); - } catch (TestFrameworkException $e) { - } - } - - if (empty($this->credStorage)) { - throw new TestFrameworkException( - "No credential storage is properly configured. Please configure vault or .credentials file." - ); - } + $this->initialized = false; + $this->exceptionContexts = new ExceptionCollector(); } /** @@ -87,8 +83,11 @@ private function __construct() */ public function getSecret($key) { - // Get secret data from storage according to the order they are stored - // File storage is preferred over vault storage to allow local secret value overriding remote secret value + // Initialize credential storage if it's not been done + $this->initializeCredentialStorage(); + + // Get secret data from storage according to the order they are stored which follows this precedence: + // FileStorage > VaultStorage > AwsSecretsManagerStorage foreach ($this->credStorage as $storage) { $value = $storage->getEncryptedValue($key); if (null !== $value) { @@ -96,9 +95,12 @@ public function getSecret($key) } } + $exceptionContexts = $this->getExceptionContexts(); + $this->resetExceptionContext(); throw new TestFrameworkException( - "\"{$key}\" not defined in vault or .credentials file, " - . "please provide a value in order to use this secret in a test." + "{$key} not found. " . self::CREDENTIAL_STORAGE_INFO + . " and ensure key, value exists to use _CREDS in tests." + . $exceptionContexts ); } @@ -106,27 +108,187 @@ public function getSecret($key) * Return decrypted input value * * @param string $value - * @return string + * @return string|false The decrypted string on success or false on failure + * @throws TestFrameworkException */ public function decryptSecretValue($value) { - // Loop through storage to decrypt value - foreach ($this->credStorage as $storage) { - return $storage->getDecryptedValue($value); - } + // Initialize credential storage if it's not been done + $this->initializeCredentialStorage(); + + // Decrypt secret value + return BaseStorage::getDecryptedValue($value); } /** * Return decrypted values for all occurrences from input string * * @param string $string - * @return mixed + * @return string|false The decrypted string on success or false on failure + * @throws TestFrameworkException */ public function decryptAllSecretsInString($string) { - // Loop through storage to decrypt all occurrences from input string - foreach ($this->credStorage as $storage) { - return $storage->getAllDecryptedValuesInString($string); + // Initialize credential storage if it's not been done + $this->initializeCredentialStorage(); + + // Decrypt all secret values in string + return BaseStorage::getAllDecryptedValuesInString($string); + } + + /** + * Setter for exception contexts + * + * @param string $type + * @param string $context + * @return void + */ + public function setExceptionContexts($type, $context) + { + $typeArray = [self::ARRAY_KEY_FOR_FILE, self::ARRAY_KEY_FOR_VAULT, self::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER]; + if (in_array($type, $typeArray) && !empty($context)) { + $this->exceptionContexts->addError($type, $context); + } + } + + /** + * Return collected exception contexts + * + * @return string + */ + private function getExceptionContexts() + { + // Gather all exceptions collected + $exceptionMessage = "\n"; + foreach ($this->exceptionContexts->getErrors() as $type => $exceptions) { + $exceptionMessage .= "\nException from "; + if ($type == self::ARRAY_KEY_FOR_FILE) { + $exceptionMessage .= "File Storage: \n"; + } + if ($type == self::ARRAY_KEY_FOR_VAULT) { + $exceptionMessage .= "Vault Storage: \n"; + } + if ($type == self::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER) { + $exceptionMessage .= "AWS Secrets Manager Storage: \n"; + } + + if (is_array($exceptions)) { + $exceptionMessage .= implode("\n", $exceptions) . "\n"; + } else { + $exceptionMessage .= $exceptions . "\n"; + } + } + return $exceptionMessage; + } + + /** + * Reset exception contexts to empty array + * + * @return void + */ + private function resetExceptionContext() + { + $this->exceptionContexts->reset(); + } + + /** + * Initialize all available credential storage + * + * @return void + * @throws TestFrameworkException + */ + private function initializeCredentialStorage() + { + if (!$this->initialized) { + // Initialize credential storage by defined order of precedence as the following + $this->initializeFileStorage(); + $this->initializeVaultStorage(); + $this->initializeAwsSecretsManagerStorage(); + $this->initialized = true; + } + + if (empty($this->credStorage)) { + throw new TestFrameworkException( + 'Invalid Credential Storage. ' . self::CREDENTIAL_STORAGE_INFO + . '.' . $this->getExceptionContexts() + ); + } + $this->resetExceptionContext(); + } + + /** + * Initialize file storage + * + * @return void + */ + private function initializeFileStorage() + { + // Initialize file storage + try { + $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); + } catch (TestFrameworkException $e) { + // Print error message in console + print_r($e->getMessage()); + // Save to exception context for Allure report + $this->setExceptionContexts(self::ARRAY_KEY_FOR_FILE, $e->getMessage()); + } + } + + /** + * Initialize Vault storage + * + * @return void + */ + private function initializeVaultStorage() + { + // Initialize vault storage + $cvAddress = getenv('CREDENTIAL_VAULT_ADDRESS'); + $cvSecretPath = getenv('CREDENTIAL_VAULT_SECRET_BASE_PATH'); + if ($cvAddress !== false && $cvSecretPath !== false) { + try { + $this->credStorage[self::ARRAY_KEY_FOR_VAULT] = new VaultStorage( + UrlFormatter::format($cvAddress, false), + '/' . trim($cvSecretPath, '/') + ); + } catch (TestFrameworkException $e) { + // Print error message in console + print_r($e->getMessage()); + // Save to exception context for Allure report + $this->setExceptionContexts(self::ARRAY_KEY_FOR_VAULT, $e->getMessage()); + } + } + } + + /** + * Initialize AWS Secrets Manager storage + * + * @return void + */ + private function initializeAwsSecretsManagerStorage() + { + // Initialize AWS Secrets Manager storage + $awsRegion = getenv('CREDENTIAL_AWS_SECRETS_MANAGER_REGION'); + $awsProfile = getenv('CREDENTIAL_AWS_SECRETS_MANAGER_PROFILE'); + $awsId = getenv('CREDENTIAL_AWS_ACCOUNT_ID'); + if (!empty($awsRegion)) { + if (empty($awsProfile)) { + $awsProfile = null; + } + if (empty($awsId)) { + $awsId = null; + } + try { + $this->credStorage[self::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER] = new AwsSecretsManagerStorage( + $awsRegion, + $awsProfile, + $awsId + ); + } catch (TestFrameworkException $e) { + // Print error message in console + print_r($e->getMessage()); + // Save to exception context for Allure report + $this->setExceptionContexts(self::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER, $e->getMessage()); + } } } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php index 95a2b8b93..a210710db 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/DataObjectHandler.php @@ -13,6 +13,7 @@ use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\DataGenerator\Util\DataExtensionUtil; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; class DataObjectHandler implements ObjectHandlerInterface { @@ -119,6 +120,7 @@ public function getAllObjects() * @param string[] $parserOutput Primitive array output from the Magento parser. * @return EntityDataObject[] * @throws XmlException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function processParserOutput($parserOutput) { @@ -132,6 +134,7 @@ private function processParserOutput($parserOutput) $type = $rawEntity[self::_TYPE] ?? null; $data = []; + $deprecated = null; $linkedEntities = []; $uniquenessData = []; $vars = []; @@ -163,6 +166,14 @@ private function processParserOutput($parserOutput) $parentEntity = $rawEntity[self::_EXTENDS]; } + if (array_key_exists(self::OBJ_DEPRECATED, $rawEntity)) { + $deprecated = $rawEntity[self::OBJ_DEPRECATED]; + LoggingUtil::getInstance()->getLogger(self::class)->deprecation( + $deprecated, + ["dataName" => $filename, "deprecatedEntity" => $deprecated] + ); + } + $entityDataObject = new EntityDataObject( $name, $type, @@ -171,7 +182,8 @@ private function processParserOutput($parserOutput) $uniquenessData, $vars, $parentEntity, - $filename + $filename, + $deprecated ); $entityDataObjects[$entityDataObject->getName()] = $entityDataObject; diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php index b768d9bd8..8c2ec7b0a 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/OperationDefinitionObjectHandler.php @@ -11,6 +11,7 @@ use Magento\FunctionalTestingFramework\DataGenerator\Util\OperationElementExtractor; use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; class OperationDefinitionObjectHandler implements ObjectHandlerInterface { @@ -128,9 +129,7 @@ public function getOperationDefinition($operation, $dataType) * @return void * @throws \Exception * - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.UnusedPrivateMethod) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD) */ private function initialize() { @@ -145,6 +144,7 @@ private function initialize() $auth = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_AUTH] ?? null; $successRegex = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_SUCCESS_REGEX] ?? null; $returnRegex = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_RETURN_REGEX] ?? null; + $deprecated = $opDefArray[ObjectHandlerInterface::OBJ_DEPRECATED] ?? null; $returnIndex = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_RETURN_INDEX] ?? 0; $contentType = $opDefArray[OperationDefinitionObjectHandler::ENTITY_OPERATION_CONTENT_TYPE][0]['value'] ?? null; @@ -205,6 +205,13 @@ private function initialize() } } + if ($deprecated !== null) { + LoggingUtil::getInstance()->getLogger(self::class)->deprecation( + $deprecated, + ["operationName" => $dataDefName, "deprecatedOperation" => $deprecated] + ); + } + $this->operationDefinitionObjects[$operation . $dataType] = new OperationDefinitionObject( $dataDefName, $operation, @@ -219,7 +226,8 @@ private function initialize() $removeBackend, $successRegex, $returnRegex, - $returnIndex + $returnIndex, + $deprecated ); } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php index 42286564f..927c0ab4e 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php @@ -55,7 +55,6 @@ private function __construct() * Return the singleton instance of this class. Initialize it if needed. * * @return PersistedObjectHandler - * @throws \Exception */ public static function getInstance() { @@ -90,14 +89,24 @@ public function createEntity( foreach ($overrideFields as $index => $field) { try { - $overrideFields[$index] = CredentialStore::getInstance()->decryptAllSecretsInString($field); + $decrptedField = CredentialStore::getInstance()->decryptAllSecretsInString($field); + if ($decrptedField !== false) { + $overrideFields[$index] = $decrptedField; + } } catch (TestFrameworkException $e) { - //do not rethrow if Credentials are not defined - $overrideFields[$index] = $field; + //catch exception if Credentials are not defined } } $retrievedEntity = DataObjectHandler::getInstance()->getObject($entity); + + if ($retrievedEntity === null) { + throw new TestReferenceException( + "Entity \"" . $entity . "\" does not exist." . + "\nException occurred executing action at StepKey \"" . $key . "\"" + ); + } + $persistedObject = new DataPersistenceHandler( $retrievedEntity, $retrievedDependentObjects, diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorage.php new file mode 100644 index 000000000..6bd1ff144 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/AwsSecretsManagerStorage.php @@ -0,0 +1,212 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; + +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Aws\SecretsManager\SecretsManagerClient; +use Aws\Exception\AwsException; +use Aws\Result; +use InvalidArgumentException; +use Exception; + +class AwsSecretsManagerStorage extends BaseStorage +{ + /** + * Mftf project path + */ + const MFTF_PATH = 'mftf'; + + /** + * AWS Secrets Manager partial ARN + */ + const AWS_SM_PARTIAL_ARN = 'arn:aws:secretsmanager:'; + + /** + * AWS Secrets Manager version + * + * Last tested version '2017-10-17' + */ + const LATEST_VERSION = 'latest'; + + /** + * SecretsManagerClient client + * + * @var SecretsManagerClient + */ + private $client = null; + + /** + * AWS account id + * + * @var string + */ + private $awsAccountId; + + /** + * AWS account region + * + * @var string + */ + private $region; + + /** + * AwsSecretsManagerStorage constructor + * + * @param string $region + * @param string $profile + * @param string $accountId + * @throws TestFrameworkException + * @throws InvalidArgumentException + */ + public function __construct($region, $profile = null, $accountId = null) + { + parent::__construct(); + $this->createAwsSecretsManagerClient($region, $profile); + $this->region = $region; + $this->awsAccountId = $accountId; + } + + /** + * Returns the value of a secret based on corresponding key + * + * @param string $key + * @return string|null + * @throws Exception + */ + public function getEncryptedValue($key) + { + // Check if secret is in cached array + if (null !== ($value = parent::getEncryptedValue($key))) { + return $value; + } + + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(AwsSecretsManagerStorage::class)->debug( + "Retrieving value for key name {$key} from AWS Secrets Manager" + ); + } + + $reValue = null; + try { + // Split vendor/key to construct secret id + list($vendor, $key) = explode('/', trim($key, '/'), 2); + // If AWS account id is specified, create and use full ARN, otherwise use partial ARN as secret id + $secretId = ''; + if (!empty($this->awsAccountId)) { + $secretId = self::AWS_SM_PARTIAL_ARN . $this->region . ':' . $this->awsAccountId . ':secret:'; + } + $secretId .= self::MFTF_PATH + . '/' + . $vendor + . '/' + . $key; + // Read value by id from AWS Secrets Manager, and parse the result + $value = $this->parseAwsSecretResult( + $this->client->getSecretValue(['SecretId' => $secretId]), + $key + ); + // Encrypt value for return + $reValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); + parent::$cachedSecretData[$key] = $reValue; + } catch (AwsException $e) { + $errMessage = "\nAWS Exception:\n" . $e->getAwsErrorMessage() + . "\nUnable to read value for key {$key} from AWS Secrets Manager\n"; + // Print error message in console + print_r($errMessage); + // Add error message in mftf log if verbose is enable + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(AwsSecretsManagerStorage::class)->debug($errMessage); + } + // Save to exception context for Allure report + CredentialStore::getInstance()->setExceptionContexts( + CredentialStore::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER, + $errMessage + ); + } catch (\Exception $e) { + $errMessage = "\nException:\n" . $e->getMessage() + . "\nUnable to read value for key {$key} from AWS Secrets Manager\n"; + // Print error message in console + print_r($errMessage); + // Add error message in mftf log if verbose is enable + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(AwsSecretsManagerStorage::class)->debug($errMessage); + } + // Save to exception context for Allure report + CredentialStore::getInstance()->setExceptionContexts( + CredentialStore::ARRAY_KEY_FOR_AWS_SECRETS_MANAGER, + $errMessage + ); + } + return $reValue; + } + + /** + * Parse AWS result object and return secret for key + * + * @param Result $awsResult + * @param string $key + * @return string + * @throws TestFrameworkException + */ + private function parseAwsSecretResult($awsResult, $key) + { + // Return secret from the associated KMS CMK + if (isset($awsResult['SecretString'])) { + $rawSecret = $awsResult['SecretString']; + } else { + throw new TestFrameworkException( + "'SecretString' field is not set in AWS Result. Error parsing result from AWS Secrets Manager" + ); + } + + // Secrets are saved as JSON structures of key/value pairs if using AWS Secrets Manager console, and + // Secrets are saved as plain text if using AWS CLI. We need to handle both cases. + $secret = json_decode($rawSecret, true); + if (isset($secret[$key])) { + return $secret[$key]; + } elseif (is_string($rawSecret)) { + return $rawSecret; + } + throw new TestFrameworkException( + "$key not found or value is not string . Error parsing result from AWS Secrets Manager" + ); + } + + /** + * Create Aws Secrets Manager client + * + * @param string $region + * @param string $profile + * @return void + * @throws TestFrameworkException + * @throws InvalidArgumentException + */ + private function createAwsSecretsManagerClient($region, $profile) + { + if (null !== $this->client) { + return; + } + + $options = [ + 'region' => $region, + 'version' => self::LATEST_VERSION, + ]; + + if (!empty($profile)) { + $options['profile'] = $profile; + } + + // Create AWS Secrets Manager client + $this->client = new SecretsManagerClient($options); + if ($this->client === null) { + throw new TestFrameworkException("Unable to create AWS Secrets Manager client"); + } + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php index cb892a545..6eb7fa7e8 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php @@ -58,30 +58,38 @@ public function getEncryptedValue($key) /** * Takes a value encrypted at runtime and decrypts it using the object's initial vector + * return the decrypted string on success or false on failure * * @param string $value - * @return string + * @return string|false The decrypted string on success or false on failure */ - public function getDecryptedValue($value) + public static function getDecryptedValue($value) { return openssl_decrypt($value, self::ENCRYPTION_ALGO, self::$encodedKey, 0, self::$iv); } /** * Takes a string that contains encrypted data at runtime and decrypts each value + * return false if no decryption happens or a failure occurs * * @param string $string - * @return mixed + * @return string|false The decrypted string on success or false on failure */ - public function getAllDecryptedValuesInString($string) + public static function getAllDecryptedValuesInString($string) { - $newString = $string; + $decrypted = false; foreach (self::$cachedSecretData as $key => $secretValue) { - if (strpos($newString, $secretValue) !== false) { + if (strpos($string, $secretValue) !== false) { $decryptedValue = self::getDecryptedValue($secretValue); - $newString = str_replace($secretValue, $decryptedValue, $newString); + if ($decryptedValue === false) { + return false; + } + if (!$decrypted) { + $decrypted = true; + } + $string = str_replace($secretValue, $decryptedValue, $string); } } - return $newString; + return $decrypted ? $string : false; } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php index 6a9e9f0cf..39839e8f9 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php @@ -7,6 +7,7 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Vault\Client; @@ -67,7 +68,7 @@ class VaultStorage extends BaseStorage private $secretBasePath; /** - * CredentialVault constructor + * VaultStorage constructor * * @param string $baseUrl * @param string $secretBasePath @@ -123,10 +124,14 @@ public function getEncryptedValue($key) $reValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); parent::$cachedSecretData[$key] = $reValue; } catch (\Exception $e) { + $errMessage = "\nUnable to read secret for key name {$key} from vault." . $e->getMessage(); + // Print error message in console + print_r($errMessage); + // Save to exception context for Allure report + CredentialStore::getInstance()->setExceptionContexts('vault', $errMessage); + // Add error message in mftf log if verbose is enable if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug( - "Unable to read secret for key name {$key} from vault" - ); + LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug($errMessage); } } return $reValue; @@ -149,6 +154,13 @@ private function authenticated() return true; } } catch (\Exception $e) { + // Print error message in console + print_r($e->getMessage()); + // Save to exception context for Allure report + CredentialStore::getInstance()->setExceptionContexts( + CredentialStore::ARRAY_KEY_FOR_VAULT, + $e->getMessage() + ); } return false; } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/EntityDataObject.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/EntityDataObject.php index 47a966f84..2204364f5 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/EntityDataObject.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/EntityDataObject.php @@ -80,17 +80,25 @@ class EntityDataObject */ private $filename; + /** + * Deprecated message. + * + * @var string + */ + private $deprecated; + /** * Constructor * - * @param string $name - * @param string $type - * @param string[] $data - * @param string[] $linkedEntities - * @param string[] $uniquenessData - * @param string[] $vars - * @param string $parentEntity - * @param string $filename + * @param string $name + * @param string $type + * @param string[] $data + * @param string[] $linkedEntities + * @param string[] $uniquenessData + * @param string[] $vars + * @param string $parentEntity + * @param string $filename + * @param string|null $deprecated */ public function __construct( $name, @@ -100,7 +108,8 @@ public function __construct( $uniquenessData, $vars = [], $parentEntity = null, - $filename = null + $filename = null, + $deprecated = null ) { $this->name = $name; $this->type = $type; @@ -113,6 +122,17 @@ public function __construct( $this->vars = $vars; $this->parentEntity = $parentEntity; $this->filename = $filename; + $this->deprecated = $deprecated; + } + + /** + * Getter for the deprecated attr of the section. + * + * @return string + */ + public function getDeprecated() + { + return $this->deprecated; } /** diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/OperationDefinitionObject.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/OperationDefinitionObject.php index 721a9dcc9..67fe48300 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/OperationDefinitionObject.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Objects/OperationDefinitionObject.php @@ -8,6 +8,7 @@ /** * Class OperationDefinitionObject + * @SuppressWarnings(PHPMD) */ class OperationDefinitionObject { @@ -117,22 +118,30 @@ class OperationDefinitionObject */ private $removeBackend; + /** + * Deprecated message. + * + * @var string + */ + private $deprecated; + /** * OperationDefinitionObject constructor. - * @param string $name - * @param string $operation - * @param string $dataType - * @param string $apiMethod - * @param string $apiUri - * @param string $auth - * @param array $headers - * @param array $params - * @param array $metaData - * @param string $contentType - * @param boolean $removeBackend - * @param string $successRegex - * @param string $returnRegex - * @param string $returnIndex + * @param string $name + * @param string $operation + * @param string $dataType + * @param string $apiMethod + * @param string $apiUri + * @param string $auth + * @param array $headers + * @param array $params + * @param array $metaData + * @param string $contentType + * @param boolean $removeBackend + * @param string $successRegex + * @param string $returnRegex + * @param string $returnIndex + * @param string|null $deprecated * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -149,7 +158,8 @@ public function __construct( $removeBackend, $successRegex = null, $returnRegex = null, - $returnIndex = null + $returnIndex = null, + $deprecated = null ) { $this->name = $name; $this->operation = $operation; @@ -164,6 +174,7 @@ public function __construct( $this->returnRegex = $returnRegex; $this->returnIndex = $returnIndex; $this->removeBackend = $removeBackend; + $this->deprecated = $deprecated; $this->apiUrl = null; if (!empty($contentType)) { @@ -176,6 +187,16 @@ public function __construct( $this->headers[] = self::HTTP_CONTENT_TYPE_HEADER . ': ' . $this->contentType; } + /** + * Getter for the deprecated attr of the section + * + * @return string + */ + public function getDeprecated() + { + return $this->deprecated; + } + /** * Getter for data's data type * diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php index 16584e7a3..05178c915 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/CurlHandler.php @@ -123,8 +123,8 @@ public function executeRequest($dependentEntities) $returnRegex = $this->operationDefinition->getReturnRegex(); $returnIndex = $this->operationDefinition->getReturnIndex(); $method = $this->operationDefinition->getApiMethod(); - AllureHelper::addAttachmentToLastStep($apiUrl, 'API Endpoint'); - AllureHelper::addAttachmentToLastStep(json_encode($headers, JSON_PRETTY_PRINT), 'Request Headers'); + AllureHelper::addAttachmentToCurrentStep($apiUrl, 'API Endpoint'); + AllureHelper::addAttachmentToCurrentStep(json_encode($headers, JSON_PRETTY_PRINT), 'Request Headers'); $operationDataResolver = new OperationDataArrayResolver($dependentEntities); $this->requestData = $operationDataResolver->resolveOperationDataArray( @@ -169,8 +169,8 @@ public function executeRequest($dependentEntities) $response = $executor->read($successRegex, $returnRegex, $returnIndex); $executor->close(); - AllureHelper::addAttachmentToLastStep(json_encode($this->requestData, JSON_PRETTY_PRINT), 'Request Body'); - AllureHelper::addAttachmentToLastStep( + 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' ); diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/DataPersistenceHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/DataPersistenceHandler.php index dcb9d158a..73ee2be19 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/DataPersistenceHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/DataPersistenceHandler.php @@ -59,7 +59,10 @@ public function __construct($entityObject, $dependentObjects = [], $customFields array_merge($entityObject->getAllData(), $customFields), $entityObject->getLinkedEntities(), $this->stripCustomFieldsFromUniquenessData($entityObject->getUniquenessData(), $customFields), - $entityObject->getVarReferences() + $entityObject->getVarReferences(), + $entityObject->getParentName(), + $entityObject->getFilename(), + $entityObject->getDeprecated() ); } else { $this->entityObject = clone $entityObject; diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php index 2766b39a0..3a12bdce1 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/DataExtensionUtil.php @@ -93,7 +93,8 @@ public function extendEntity($entityObject) $newUniqueReferences, $newVarReferences, $entityObject->getParentName(), - $entityObject->getFilename() + $entityObject->getFilename(), + $entityObject->getDeprecated() ); return $extendedEntity; } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/RuntimeDataReferenceResolver.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/RuntimeDataReferenceResolver.php index a09afd01a..220d4ab7f 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/RuntimeDataReferenceResolver.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/RuntimeDataReferenceResolver.php @@ -9,6 +9,7 @@ use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; /** @@ -23,7 +24,7 @@ class RuntimeDataReferenceResolver implements DataReferenceResolverInterface * @param string $originalDataEntity * @return array|false|string|null * @throws TestReferenceException - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException + * @throws TestFrameworkException */ public function getDataReference(string $data, string $originalDataEntity) { @@ -43,6 +44,9 @@ public function getDataReference(string $data, string $originalDataEntity) case ActionObject::__CREDS: $value = CredentialStore::getInstance()->getSecret($var); $result = CredentialStore::getInstance()->decryptSecretValue($value); + if ($result === false) { + throw new TestFrameworkException("\nFailed to decrypt value {$value}\n"); + } $result = str_replace($matches['reference'], $result, $data); break; default: diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd index 8b59ccae0..58fad8d8b 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataOperation.xsd @@ -22,6 +22,13 @@ </xs:choice> <xs:attribute type="xs:string" name="name"/> <xs:attribute type="xs:string" name="dataType" use="required"/> + <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="operationEnum" name="type" use="required"/> <xs:attribute type="xs:string" name="url"/> <xs:attribute type="authEnum" name="auth"/> diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd index aec157309..9d0d8bb35 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd @@ -69,6 +69,14 @@ </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="xs:string" name="type"> <xs:annotation> <xs:documentation> diff --git a/src/Magento/FunctionalTestingFramework/Exceptions/Collector/ExceptionCollector.php b/src/Magento/FunctionalTestingFramework/Exceptions/Collector/ExceptionCollector.php index c1e023ef4..f64b35446 100644 --- a/src/Magento/FunctionalTestingFramework/Exceptions/Collector/ExceptionCollector.php +++ b/src/Magento/FunctionalTestingFramework/Exceptions/Collector/ExceptionCollector.php @@ -43,6 +43,26 @@ public function throwException() throw new \Exception("\n" . $errorMsg); } + /** + * Return all errors + * + * @return array + */ + public function getErrors() + { + return $this->errors ?? []; + } + + /** + * Reset error to empty array + * + * @return void + */ + public function reset() + { + $this->errors = []; + } + /** * If there are multiple exceptions for a single file, the function flattens the array so they can be printed * as separate messages. diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoActionProxies.php b/src/Magento/FunctionalTestingFramework/Module/MagentoActionProxies.php new file mode 100644 index 000000000..5a3b2360b --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoActionProxies.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\Module; + +use Codeception\Module as CodeceptionModule; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; + +/** + * Class MagentoActionProxies + * + * Contains all proxy functions whose corresponding MFTF actions need to be accessible for AcceptanceTester $I + * + * @package Magento\FunctionalTestingFramework\Module + */ +class MagentoActionProxies extends CodeceptionModule +{ + // TODO: placeholder for proxy functions currently in MagentoWebDriver (MQE-1904) +} diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index ff0c621dd..cd2768a06 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -26,6 +26,7 @@ use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver\Exception\WebDriverCurlException; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; /** * MagentoWebDriver module provides common Magento web actions through Selenium WebDriver. @@ -46,11 +47,15 @@ * ``` * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.ExcessivePublicCount) */ class MagentoWebDriver extends WebDriver { use AttachmentSupport; + const MAGENTO_CRON_INTERVAL = 60; + const MAGENTO_CRON_COMMAND = 'cron:run'; + /** * List of known magento loading masks by selector * @@ -119,6 +124,13 @@ class MagentoWebDriver extends WebDriver */ private $jsErrors = []; + /** + * Contains last execution times for Cron + * + * @var int[] + */ + private $cronExecution = []; + /** * Sanitizes config, then initializes using parent. * @@ -550,6 +562,75 @@ public function magentoCLI($command, $timeout = null, $arguments = null) return $response; } + /** + * Executes Magento Cron keeping the interval (> 60 seconds between each run) + * + * @param string|null $cronGroups + * @param integer|null $timeout + * @param string|null $arguments + * @return string + */ + public function magentoCron($cronGroups = null, $timeout = null, $arguments = null) + { + $cronGroups = explode(' ', $cronGroups); + return $this->executeCronjobs($cronGroups, $timeout, $arguments); + } + + /** + * Updates last execution time for Cron + * + * @param array $cronGroups + * @return void + */ + private function notifyCronFinished(array $cronGroups = []) + { + if (empty($cronGroups)) { + $this->cronExecution['*'] = time(); + } + + foreach ($cronGroups as $group) { + $this->cronExecution[$group] = time(); + } + } + + /** + * Returns last Cron execution time for specific cron or all crons + * + * @param array $cronGroups + * @return integer + */ + private function getLastCronExecution(array $cronGroups = []) + { + if (empty($cronGroups)) { + return (int)max($this->cronExecution); + } + + $cronGroups = array_merge($cronGroups, ['*']); + + return array_reduce($cronGroups, function ($lastExecution, $group) { + if (isset($this->cronExecution[$group]) && $this->cronExecution[$group] > $lastExecution) { + $lastExecution = $this->cronExecution[$group]; + } + + return (int)$lastExecution; + }, 0); + } + + /** + * Returns time to wait for next run + * + * @param array $cronGroups + * @param integer $cronInterval + * @return integer + */ + private function getCronWait(array $cronGroups = [], int $cronInterval = self::MAGENTO_CRON_INTERVAL) + { + $nextRun = $this->getLastCronExecution($cronGroups) + $cronInterval; + $toNextRun = $nextRun - time(); + + return max(0, $toNextRun); + } + /** * Runs DELETE request to delete a Magento entity against the url given. * @@ -688,6 +769,9 @@ public function fillSecretField($field, $value) // decrypted value $decryptedValue = CredentialStore::getInstance()->decryptSecretValue($value); + if ($decryptedValue === false) { + throw new TestFrameworkException("\nFailed to decrypt value {$value} for field {$field}\n"); + } $this->fillField($field, $decryptedValue); } @@ -707,6 +791,9 @@ public function magentoCLISecret($command, $timeout = null, $arguments = null) // decrypted value $decryptedCommand = CredentialStore::getInstance()->decryptAllSecretsInString($command); + if ($decryptedCommand === false) { + throw new TestFrameworkException("\nFailed to decrypt magentoCLI command {$command}\n"); + } return $this->magentoCLI($decryptedCommand, $timeout, $arguments); } @@ -855,4 +942,150 @@ public function makeScreenshot($name = null) $this->debug("Screenshot saved to $screenName"); AllureHelper::addAttachmentToCurrentStep($screenName, 'Screenshot'); } + + /** + * Create an entity + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $key StepKey of the createData action. + * @param string $scope + * @param string $entity Name of xml entity to create. + * @param array $dependentObjectKeys StepKeys of other createData actions that are required. + * @param array $overrideFields Array of FieldName => Value of override fields. + * @param string $storeCode + * @return void + */ + public function createEntity( + $key, + $scope, + $entity, + $dependentObjectKeys = [], + $overrideFields = [], + $storeCode = '' + ) { + PersistedObjectHandler::getInstance()->createEntity( + $key, + $scope, + $entity, + $dependentObjectKeys, + $overrideFields, + $storeCode + ); + } + + /** + * Retrieves and updates a previously created entity + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $key StepKey of the createData action. + * @param string $scope + * @param string $updateEntity Name of the static XML data to update the entity with. + * @param array $dependentObjectKeys StepKeys of other createData actions that are required. + * @return void + */ + public function updateEntity($key, $scope, $updateEntity, $dependentObjectKeys = []) + { + PersistedObjectHandler::getInstance()->updateEntity( + $key, + $scope, + $updateEntity, + $dependentObjectKeys + ); + } + + /** + * Performs GET on given entity and stores entity for use + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $key StepKey of getData action. + * @param string $scope + * @param string $entity Name of XML static data to use. + * @param array $dependentObjectKeys StepKeys of other createData actions that are required. + * @param string $storeCode + * @param integer $index + * @return void + */ + public function getEntity($key, $scope, $entity, $dependentObjectKeys = [], $storeCode = '', $index = null) + { + PersistedObjectHandler::getInstance()->getEntity( + $key, + $scope, + $entity, + $dependentObjectKeys, + $storeCode, + $index + ); + } + + /** + * Retrieves and deletes a previously created entity + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $key StepKey of the createData action. + * @param string $scope + * @return void + */ + public function deleteEntity($key, $scope) + { + PersistedObjectHandler::getInstance()->deleteEntity($key, $scope); + } + + /** + * Retrieves a field from an entity, according to key and scope given + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $stepKey + * @param string $field + * @param string $scope + * @return string + */ + public function retrieveEntityField($stepKey, $field, $scope) + { + return PersistedObjectHandler::getInstance()->retrieveEntityField($stepKey, $field, $scope); + } + + /** + * Get encrypted value by key + * TODO: move this function to MagentoActionProxies after MQE-1904 + * + * @param string $key + * @return string|null + * @throws TestFrameworkException + */ + public function getSecret($key) + { + return CredentialStore::getInstance()->getSecret($key); + } + + /** + * Waits proper amount of time to perform Cron execution + * + * @param string $cronGroups + * @param integer $timeout + * @param string $arguments + * @return string + * @throws TestFrameworkException + */ + private function executeCronjobs($cronGroups, $timeout, $arguments): string + { + $cronGroups = array_filter($cronGroups); + + $waitFor = $this->getCronWait($cronGroups); + + if ($waitFor) { + $this->wait($waitFor); + } + + $command = array_reduce($cronGroups, function ($command, $cronGroup) { + $command .= ' --group=' . $cronGroup; + return $command; + }, self::MAGENTO_CRON_COMMAND); + $timeStart = microtime(true); + $cronResult = $this->magentoCLI($command, $timeout, $arguments); + $timeEnd = microtime(true); + + $this->notifyCronFinished($cronGroups); + + return sprintf('%s (wait: %ss, execution: %ss)', $cronResult, $waitFor, round($timeEnd - $timeStart, 2)); + } } diff --git a/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php b/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php index 1bc79cbbb..94147dc08 100644 --- a/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php +++ b/src/Magento/FunctionalTestingFramework/ObjectManager/ObjectHandlerInterface.php @@ -11,6 +11,8 @@ */ interface ObjectHandlerInterface { + const OBJ_DEPRECATED = 'deprecated'; + /** * Function to enforce singleton design pattern * diff --git a/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php b/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php index d9eec1af1..c310b9bef 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Page/Handlers/PageObjectHandler.php @@ -9,6 +9,7 @@ use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; use Magento\FunctionalTestingFramework\Page\Objects\PageObject; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\XmlParser\PageParser; use Magento\FunctionalTestingFramework\Exceptions\XmlException; @@ -68,9 +69,17 @@ private function __construct() $sectionNames = array_keys($pageData[self::SECTION] ?? []); $parameterized = $pageData[self::PARAMETERIZED] ?? false; $filename = $pageData[self::FILENAME] ?? null; + $deprecated = $pageData[self::OBJ_DEPRECATED] ?? null; + + if ($deprecated !== null) { + LoggingUtil::getInstance()->getLogger(self::class)->deprecation( + $deprecated, + ["pageName" => $filename, "deprecatedPage" => $deprecated] + ); + } $this->pageObjects[$pageName] = - new PageObject($pageName, $url, $module, $sectionNames, $parameterized, $area, $filename); + new PageObject($pageName, $url, $module, $sectionNames, $parameterized, $area, $filename, $deprecated); } } diff --git a/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php b/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php index e77e4c502..2736100fd 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Page/Handlers/SectionObjectHandler.php @@ -10,6 +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\XmlParser\SectionParser; use Magento\FunctionalTestingFramework\Exceptions\XmlException; @@ -73,14 +75,21 @@ private function __construct() $elementLocatorFunc = $elementData[SectionObjectHandler::LOCATOR_FUNCTION] ?? null; $elementTimeout = $elementData[SectionObjectHandler::TIMEOUT] ?? null; $elementParameterized = $elementData[SectionObjectHandler::PARAMETERIZED] ?? false; - + $elementDeprecated = $elementData[self::OBJ_DEPRECATED] ?? null; + if ($elementDeprecated !== null) { + LoggingUtil::getInstance()->getLogger(ElementObject::class)->deprecation( + $elementDeprecated, + ["elementName" => $elementName, "deprecatedElement" => $elementDeprecated] + ); + } $elements[$elementName] = new ElementObject( $elementName, $elementType, $elementSelector, $elementLocatorFunc, $elementTimeout, - $elementParameterized + $elementParameterized, + $elementDeprecated ); } } catch (XmlException $exception) { @@ -88,7 +97,21 @@ private function __construct() } $filename = $sectionData[self::FILENAME] ?? null; - $this->sectionObjects[$sectionName] = new SectionObject($sectionName, $elements, $filename); + $sectionDeprecated = $sectionData[self::OBJ_DEPRECATED] ?? null; + + if ($sectionDeprecated !== null) { + LoggingUtil::getInstance()->getLogger(SectionObject::class)->deprecation( + $sectionDeprecated, + ["sectionName" => $filename, "deprecatedSection" => $sectionDeprecated] + ); + } + + $this->sectionObjects[$sectionName] = new SectionObject( + $sectionName, + $elements, + $filename, + $sectionDeprecated + ); } } diff --git a/src/Magento/FunctionalTestingFramework/Page/Objects/ElementObject.php b/src/Magento/FunctionalTestingFramework/Page/Objects/ElementObject.php index 6b0626f10..567872fc7 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Objects/ElementObject.php +++ b/src/Magento/FunctionalTestingFramework/Page/Objects/ElementObject.php @@ -56,6 +56,13 @@ class ElementObject */ private $parameterized; + /** + * Deprecated message. + * + * @var string + */ + private $deprecated; + /** * ElementObject constructor. * @param string $name @@ -66,7 +73,7 @@ class ElementObject * @param boolean $parameterized * @throws XmlException */ - public function __construct($name, $type, $selector, $locatorFunction, $timeout, $parameterized) + public function __construct($name, $type, $selector, $locatorFunction, $timeout, $parameterized, $deprecated = null) { if ($selector != null && $locatorFunction != null) { throw new XmlException("Element '{$name}' cannot have both a selector and a locatorFunction."); @@ -83,6 +90,17 @@ public function __construct($name, $type, $selector, $locatorFunction, $timeout, } $this->timeout = $timeout; $this->parameterized = $parameterized; + $this->deprecated = $deprecated; + } + + /** + * Getter for the deprecated attr + * + * @return string + */ + public function getDeprecated() + { + return $this->deprecated; } /** diff --git a/src/Magento/FunctionalTestingFramework/Page/Objects/PageObject.php b/src/Magento/FunctionalTestingFramework/Page/Objects/PageObject.php index d99c40240..e4a1acdc0 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Objects/PageObject.php +++ b/src/Magento/FunctionalTestingFramework/Page/Objects/PageObject.php @@ -65,18 +65,34 @@ class PageObject */ private $filename; + /** + * Deprecated message. + * + * @var string + */ + private $deprecated; + /** * PageObject constructor. - * @param string $name - * @param string $url - * @param string $module - * @param array $sections - * @param boolean $parameterized - * @param string $area - * @param string $filename - */ - public function __construct($name, $url, $module, $sections, $parameterized, $area, $filename = null) - { + * @param string $name + * @param string $url + * @param string $module + * @param array $sections + * @param boolean $parameterized + * @param string $area + * @param string|null $filename + * @param string|null $deprecated + */ + public function __construct( + $name, + $url, + $module, + $sections, + $parameterized, + $area, + $filename = null, + $deprecated = null + ) { $this->name = $name; $this->url = $url; $this->module = $module; @@ -84,6 +100,17 @@ public function __construct($name, $url, $module, $sections, $parameterized, $ar $this->parameterized = $parameterized; $this->area = $area; $this->filename = $filename; + $this->deprecated = $deprecated; + } + + /** + * Getter for the deprecated attr of the section + * + * @return string + */ + public function getDeprecated() + { + return $this->deprecated; } /** diff --git a/src/Magento/FunctionalTestingFramework/Page/Objects/SectionObject.php b/src/Magento/FunctionalTestingFramework/Page/Objects/SectionObject.php index 8c1cac326..3674eea16 100644 --- a/src/Magento/FunctionalTestingFramework/Page/Objects/SectionObject.php +++ b/src/Magento/FunctionalTestingFramework/Page/Objects/SectionObject.php @@ -32,17 +32,26 @@ class SectionObject */ private $filename; + /** + * Deprecated message. + * + * @var string + */ + private $deprecated; + /** * SectionObject constructor. - * @param string $name - * @param array $elements - * @param string $filename + * @param string $name + * @param array $elements + * @param string|null $filename + * @param string|null $deprecated */ - public function __construct($name, $elements, $filename = null) + public function __construct($name, $elements, $filename = null, $deprecated = null) { $this->name = $name; $this->elements = $elements; $this->filename = $filename; + $this->deprecated = $deprecated; } /** @@ -55,6 +64,16 @@ public function getName() return $this->name; } + /** + * Getter for the deprecated attr of the section + * + * @return string + */ + public function getDeprecated() + { + return $this->deprecated; + } + /** * Getter for the Section Filename * diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd index c6f399a67..65ac8290d 100644 --- a/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd +++ b/src/Magento/FunctionalTestingFramework/Page/etc/PageObject.xsd @@ -48,6 +48,14 @@ </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> diff --git a/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd b/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd index 44e057369..1b5b44ddd 100644 --- a/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd +++ b/src/Magento/FunctionalTestingFramework/Page/etc/SectionObject.xsd @@ -44,6 +44,13 @@ </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> @@ -58,6 +65,13 @@ </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> diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php new file mode 100644 index 000000000..32c7661fe --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/ActionGroupArgumentsCheck.php @@ -0,0 +1,211 @@ +<?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\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; + +/** + * Class ActionGroupArgumentsCheck + * @package Magento\FunctionalTestingFramework\StaticCheck + */ +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'; + + /** + * 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; + + /** + * Checks unused arguments in action groups and prints out error to file. + * + * @param InputInterface $input + * @return void + * @throws Exception + */ + public function execute(InputInterface $input) + { + MftfApplicationConfig::create( + true, + MftfApplicationConfig::UNIT_TEST_PHASE, + false, + MftfApplicationConfig::LEVEL_NONE, + true + ); + + $allModules = ModuleResolver::getInstance()->getModulesPath(); + + $actionGroupXmlFiles = StaticCheckHelper::buildFileList( + $allModules, + DIRECTORY_SEPARATOR . 'ActionGroup' . DIRECTORY_SEPARATOR + ); + + $this->errors = $this->findErrorsInFileSet($actionGroupXmlFiles); + + $this->output = StaticCheckHelper::printErrorsToFile( + $this->errors, + self::ERROR_LOG_FILENAME, + 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 unused arguments found." + * @return string + */ + public function getOutput() + { + return $this->output; + } + + /** + * Finds all unused arguments in given set of actionGroup files + * @param Finder $files + * @return array $testErrors + */ + private function findErrorsInFileSet($files) + { + $actionGroupErrors = []; + 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); + } + return $actionGroupErrors; + } + + /** + * Builds array of action group => unused arguments + * @param array $actionGroups + * @return array $actionGroupToArguments + */ + private function buildUnusedArgumentList($actionGroups) + { + $actionGroupToArguments = []; + + foreach ($actionGroups as $actionGroupXml) { + preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); + $unusedArguments = $this->findUnusedArguments($actionGroupXml); + if (!empty($unusedArguments)) { + $actionGroupToArguments[$actionGroupName[1]] = $unusedArguments; + } + } + return $actionGroupToArguments; + } + + /** + * Returns unused arguments in an action group + * @param string $actionGroupXml + * @return array + */ + private function findUnusedArguments($actionGroupXml) + { + $unusedArguments = []; + + preg_match_all(self::ACTIONGROUP_ARGUMENT_REGEX_PATTERN, $actionGroupXml, $arguments); + preg_match(self::ACTIONGROUP_NAME_REGEX_PATTERN, $actionGroupXml, $actionGroupName); + try { + $actionGroup = ActionGroupObjectHandler::getInstance()->getObject($actionGroupName[1]); + } catch (XmlException $e) { + } + foreach ($arguments[1] 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)) { + continue; + } + //matches parametrized references + if (preg_match($patterns[1], $actionGroupXml)) { + continue; + } + //for extending action groups, exclude arguments that are also defined in parent action group + if ($this->isParentActionGroupArgument($argument, $actionGroup)) { + continue; + } + $unusedArguments[] = $argument; + } + return $unusedArguments; + } + + /** + * Checks if the argument is also defined in the parent for extending action groups. + * @param string $argument + * @param ActionGroupObject $actionGroup + * @return boolean + */ + private function isParentActionGroupArgument($argument, $actionGroup) + { + $parentActionGroupName = $actionGroup->getParentName(); + if ($parentActionGroupName !== null) { + $parentActionGroup = ActionGroupObjectHandler::getInstance()->getObject($parentActionGroupName); + $parentArguments = $parentActionGroup->getArguments(); + foreach ($parentArguments as $parentArgument) { + if ($argument === $parentArgument->getName()) { + return true; + } + } + } + return false; + } + + /** + * Builds and returns error output for violating references + * + * @param array $actionGroupToArguments + * @param string $path + * @return mixed + */ + private function setErrorOutput($actionGroupToArguments, $path) + { + $actionGroupErrors = []; + if (!empty($actionGroupToArguments)) { + // Build error output + $errorOutput = "\nFile \"{$path->getRealPath()}\""; + $errorOutput .= "\ncontains action group(s) with unused arguments.\n\t\t"; + foreach ($actionGroupToArguments as $actionGroup => $arguments) { + $errorOutput .= "\n\t {$actionGroup} has unused argument(s): " . implode(", ", $arguments); + } + $actionGroupErrors[$path->getRealPath()][] = $errorOutput; + } + return $actionGroupErrors; + } +} diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php new file mode 100644 index 000000000..f534544fc --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckHelper.php @@ -0,0 +1,56 @@ +<?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 f3cf20739..ffa63389d 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php @@ -29,6 +29,7 @@ public function __construct(array $checks = []) { $this->checks = [ 'testDependencies' => new TestDependencyCheck(), + 'actionGroupArguments' => new ActionGroupArgumentsCheck(), ] + $checks; } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php index 19725dc18..3c3ed6a37 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php @@ -32,6 +32,9 @@ class TestDependencyCheck implements StaticCheckInterface 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'; + /** * Array of FullModuleName => [dependencies] * @var array @@ -113,9 +116,9 @@ public function execute(InputInterface $input) DIRECTORY_SEPARATOR . 'Data' . DIRECTORY_SEPARATOR, ]; // These files can contain references to other modules. - $testXmlFiles = $this->buildFileList($allModules, $filePaths[0]); - $actionGroupXmlFiles = $this->buildFileList($allModules, $filePaths[1]); - $dataXmlFiles= $this->buildFileList($allModules, $filePaths[2]); + $testXmlFiles = StaticCheckHelper::buildFileList($allModules, $filePaths[0]); + $actionGroupXmlFiles = StaticCheckHelper::buildFileList($allModules, $filePaths[1]); + $dataXmlFiles= StaticCheckHelper::buildFileList($allModules, $filePaths[2]); $this->errors = []; $this->errors += $this->findErrorsInFileSet($testXmlFiles); @@ -123,7 +126,11 @@ public function execute(InputInterface $input) $this->errors += $this->findErrorsInFileSet($dataXmlFiles); // hold on to the output and print any errors to a file - $this->output = $this->printErrorsToFile(); + $this->output = StaticCheckHelper::printErrorsToFile( + $this->errors, + self::ERROR_LOG_FILENAME, + self::ERROR_LOG_MESSAGE + ); } /** @@ -413,24 +420,6 @@ private function getModuleDependenciesFromReferences($array) return $filenames; } - /** - * Builds list of all XML files in given modulePaths + path given - * @param string $modulePaths - * @param string $path - * @return Finder - */ - private 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(); - } - /** * Attempts to find any MFTF entity by its name. Returns null if none are found. * @param string $name @@ -461,32 +450,4 @@ private function findEntity($name) } return null; } - - /** - * Prints out given errors to file, and returns summary result string - * @return string - */ - private function printErrorsToFile() - { - $errors = $this->getErrors(); - - if (empty($errors)) { - return "No Dependency errors found."; - } - - $outputPath = getcwd() . DIRECTORY_SEPARATOR . "mftf-dependency-checks.txt"; - $fileResource = fopen($outputPath, 'w'); - $header = "MFTF File Dependency Check:\n"; - fwrite($fileResource, $header); - - foreach ($errors as $test => $error) { - fwrite($fileResource, $error[0] . PHP_EOL); - } - - fclose($fileResource); - $errorCount = count($errors); - $output = "Dependency errors found across {$errorCount} file(s). Error details output to {$outputPath}"; - - return $output; - } } diff --git a/src/Magento/FunctionalTestingFramework/Suite/Handlers/SuiteObjectHandler.php b/src/Magento/FunctionalTestingFramework/Suite/Handlers/SuiteObjectHandler.php index 30a67c31d..bbaaf4379 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/Handlers/SuiteObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Suite/Handlers/SuiteObjectHandler.php @@ -5,6 +5,7 @@ */ namespace Magento\FunctionalTestingFramework\Suite\Handlers; +use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\ObjectManager\ObjectHandlerInterface; use Magento\FunctionalTestingFramework\ObjectManagerFactory; @@ -73,7 +74,7 @@ public static function getInstance(): ObjectHandlerInterface public function getObject($objectName): SuiteObject { if (!array_key_exists($objectName, $this->suiteObjects)) { - trigger_error("Suite ${objectName} is not defined.", E_USER_ERROR); + throw new TestReferenceException("Suite ${objectName} is not defined in xml."); } return $this->suiteObjects[$objectName]; } diff --git a/src/Magento/FunctionalTestingFramework/Suite/SuiteGenerator.php b/src/Magento/FunctionalTestingFramework/Suite/SuiteGenerator.php index 4df7daa75..e3da10497 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/SuiteGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Suite/SuiteGenerator.php @@ -178,12 +178,14 @@ private function validateTestsReferencedInSuite($suiteName, $testsReferenced, $o { $suiteRef = $originalSuiteName ?? $suiteName; $possibleTestRef = SuiteObjectHandler::getInstance()->getObject($suiteRef)->getTests(); - $errorMsg = "Cannot reference tests whcih are not declared as part of suite."; + $errorMsg = "Cannot reference tests which are not declared as part of suite"; $invalidTestRef = array_diff($testsReferenced, array_keys($possibleTestRef)); if (!empty($invalidTestRef)) { - throw new TestReferenceException($errorMsg, ['suite' => $suiteRef, 'test' => $invalidTestRef]); + $testList = implode("\", \"", $invalidTestRef); + $fullError = $errorMsg . " (Suite: \"{$suiteRef}\" Tests: \"{$testList}\")"; + throw new TestReferenceException($fullError, ['suite' => $suiteRef, 'test' => $invalidTestRef]); } } diff --git a/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd b/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd index 34ef37594..b36e35517 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Suite/etc/suiteSchema.xsd @@ -61,6 +61,13 @@ <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"> diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index fc38a7fce..dc1b158e1 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -94,6 +94,13 @@ class ActionGroupObject */ private $cachedStepKeys = null; + /** + * Deprecation message. + * + * @var string|null + */ + private $deprecated; + /** * ActionGroupObject constructor. * @@ -103,9 +110,17 @@ class ActionGroupObject * @param array $actions * @param string $parentActionGroup * @param string $filename + * @param string|null $deprecated */ - public function __construct($name, $annotations, $arguments, $actions, $parentActionGroup, $filename = null) - { + public function __construct( + $name, + $annotations, + $arguments, + $actions, + $parentActionGroup, + $filename = null, + $deprecated = null + ) { $this->varAttributes = array_merge( ActionObject::SELECTOR_ENABLED_ATTRIBUTES, ActionObject::DATA_ENABLED_ATTRIBUTES @@ -117,6 +132,17 @@ public function __construct($name, $annotations, $arguments, $actions, $parentAc $this->parsedActions = $actions; $this->parentActionGroup = $parentActionGroup; $this->filename = $filename; + $this->deprecated = $deprecated; + } + + /** + * Returns deprecated messages. + * + * @return string|null + */ + public function getDeprecated() + { + return $this->deprecated; } /** @@ -213,7 +239,8 @@ private function getResolvedActionsWithArgs($arguments, $actionReferenceKey) $action->getLinkedAction() == null ? null : $action->getLinkedAction() . ucfirst($actionReferenceKey), $orderOffset, [self::ACTION_GROUP_ORIGIN_NAME => $this->name, - self::ACTION_GROUP_ORIGIN_TEST_REF => $actionReferenceKey] + self::ACTION_GROUP_ORIGIN_TEST_REF => $actionReferenceKey], + $action->getDeprecatedUsages() ); } @@ -543,10 +570,20 @@ private function addContextCommentsToActionList($actionList, $actionReferenceKey { $actionStartComment = self::ACTION_GROUP_CONTEXT_START . "[" . $actionReferenceKey . "] " . $this->name; $actionEndComment = self::ACTION_GROUP_CONTEXT_END . "[" . $actionReferenceKey . "] " . $this->name; + + $deprecationNotices = []; + if ($this->getDeprecated() !== null) { + $deprecationNotices[] = "DEPRECATED ACTION GROUP in Test: " . $this->name . ' ' . $this->getDeprecated(); + } + $startAction = new ActionObject( $actionStartComment, ActionObject::ACTION_TYPE_COMMENT, - [ActionObject::ACTION_ATTRIBUTE_USERINPUT => $actionStartComment] + [ActionObject::ACTION_ATTRIBUTE_USERINPUT => $actionStartComment], + null, + ActionObject::MERGE_ACTION_ORDER_BEFORE, + null, + $deprecationNotices ); $endAction = new ActionObject( $actionEndComment, diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index ad5ca0c33..45b5db69d 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -75,6 +75,7 @@ class ActionObject const DEFAULT_COMMAND_WAIT_TIMEOUT = 60; const ACTION_ATTRIBUTE_USERINPUT = 'userInput'; const ACTION_TYPE_COMMENT = 'comment'; + const INVISIBLE_STEP_ACTIONS = ['retrieveEntityField', 'getSecret']; /** * The unique identifier for the action @@ -83,6 +84,13 @@ class ActionObject */ private $stepKey; + /** + * Array of deprecated entities used in action. + * + * @var array + */ + private $deprecatedUsage = []; + /** * The type of action (e.g. fillField, createData, etc) * @@ -141,6 +149,7 @@ class ActionObject * @param string|null $linkedAction * @param string $order * @param array $actionOrigin + * @param array $deprecatedUsage */ public function __construct( $stepKey, @@ -148,13 +157,15 @@ public function __construct( $actionAttributes, $linkedAction = null, $order = ActionObject::MERGE_ACTION_ORDER_BEFORE, - $actionOrigin = null + $actionOrigin = null, + $deprecatedUsage = [] ) { $this->stepKey = $stepKey; $this->type = $type === self::COMMENT_ACTION ? self::ACTION_TYPE_COMMENT : $type; $this->actionAttributes = $actionAttributes; $this->linkedAction = $linkedAction; $this->actionOrigin = $actionOrigin; + $this->deprecatedUsage = $deprecatedUsage; if ($order === ActionObject::MERGE_ACTION_ORDER_AFTER) { $this->orderOffset = 1; @@ -194,7 +205,7 @@ public function getType() /** * Getter for actionOrigin * - * @return string + * @return array */ public function getActionOrigin() { @@ -303,7 +314,8 @@ public function trimAssertionAttributes() 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] + ["action" => $this->type, "stepKey" => $this->stepKey], + true ); } return; @@ -533,11 +545,18 @@ private function findAndReplaceReferences($objectHandler, $inputString) $replacement = null; $parameterized = false; } elseif (get_class($obj) == PageObject::class) { + if ($obj->getDeprecated() !== null) { + $this->deprecatedUsage[] = "DEPRECATED PAGE in Test: " . $match . ' ' . $obj->getDeprecated(); + } $this->validateUrlAreaAgainstActionType($obj); $replacement = $obj->getUrl(); $parameterized = $obj->isParameterized(); } elseif (get_class($obj) == SectionObject::class) { + if ($obj->getDeprecated() !== null) { + $this->deprecatedUsage[] = "DEPRECATED SECTION in Test: " . $match . ' ' . $obj->getDeprecated(); + } list(,$objField) = $this->stripAndSplitReference($match); + if ($obj->getElement($objField) == null) { throw new TestReferenceException( "Could not resolve entity reference \"{$inputString}\" " @@ -548,7 +567,15 @@ private function findAndReplaceReferences($objectHandler, $inputString) $parameterized = $obj->getElement($objField)->isParameterized(); $replacement = $obj->getElement($objField)->getPrioritizedSelector(); $this->setTimeout($obj->getElement($objField)->getTimeout()); + if ($obj->getElement($objField)->getDeprecated() !== null) { + $this->deprecatedUsage[] = "DEPRECATED ELEMENT in Test: " . $match . ' ' + . $obj->getElement($objField)->getDeprecated(); + } } elseif (get_class($obj) == EntityDataObject::class) { + if ($obj->getDeprecated() !== null) { + $this->deprecatedUsage[] = "DEPRECATED DATA ENTITY in Test: " + . $match . ' ' . $obj->getDeprecated(); + } $replacement = $this->resolveEntityDataObjectReference($obj, $match); if (is_array($replacement)) { @@ -765,4 +792,14 @@ private function checkParameterCount($matches, $parameters, $reference) ); } } + + /** + * Returns array of deprecated usages in Action. + * + * @return array + */ + public function getDeprecatedUsages() + { + return $this->deprecatedUsage; + } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php index 44b004105..9d3a9877e 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php @@ -64,7 +64,8 @@ private function validateMissingAnnotations($annotationObjects, $filename) $message = "Action Group File {$filename} is missing required annotations."; LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation( $message, - ["actionGroup" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)] + ["actionGroup" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)], + true ); } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php index e41329cb3..618cddc09 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php @@ -11,6 +11,8 @@ use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Objects\ArgumentObject; +use Magento\FunctionalTestingFramework\Test\Objects\TestObject; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; /** * Class ActionGroupObjectExtractor @@ -58,7 +60,15 @@ public function __construct() public function extractActionGroup($actionGroupData) { $arguments = []; + $deprecated = null; + if (array_key_exists(self::OBJ_DEPRECATED, $actionGroupData)) { + $deprecated = $actionGroupData[self::OBJ_DEPRECATED]; + LoggingUtil::getInstance()->getLogger(ActionGroupObject::class)->deprecation( + $deprecated, + ["actionGroupName" => $actionGroupData[self::FILENAME], "deprecatedActionGroup" => $deprecated] + ); + } $actionGroupReference = $actionGroupData[self::EXTENDS_ACTION_GROUP] ?? null; $actionData = $this->stripDescriptorTags( $actionGroupData, @@ -69,7 +79,8 @@ public function extractActionGroup($actionGroupData) self::FILENAME, self::ACTION_GROUP_INSERT_BEFORE, self::ACTION_GROUP_INSERT_AFTER, - self::EXTENDS_ACTION_GROUP + self::EXTENDS_ACTION_GROUP, + 'deprecated' ); // TODO filename is now available to the ActionGroupObject, integrate this into debug and error statements @@ -99,7 +110,8 @@ public function extractActionGroup($actionGroupData) $arguments, $actions, $actionGroupReference, - $actionGroupData[self::FILENAME] + $actionGroupData[self::FILENAME], + $deprecated ); } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index cd81ade24..159822db1 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -128,7 +128,8 @@ private function resolveSecretFieldAccess($resolvedActions) $action->getCustomActionAttributes(), $action->getLinkedAction(), $action->getOrderOffset(), - $action->getActionOrigin() + $action->getActionOrigin(), + $action->getDeprecatedUsages() ); $actions[$action->getStepKey()] = $action; diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php index d30ed351e..1859f3195 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php @@ -164,7 +164,8 @@ private function validateMissingAnnotations($annotationObjects, $filename) $message = "Test {$filename} is missing required annotations."; LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation( $message, - ["testName" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)] + ["testName" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)], + true ); } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/BaseObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/BaseObjectExtractor.php index 26644937d..516f79d14 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/BaseObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/BaseObjectExtractor.php @@ -13,6 +13,7 @@ class BaseObjectExtractor { const NODE_NAME = 'nodeName'; const NAME = 'name'; + const OBJ_DEPRECATED = 'deprecated'; /** * BaseObjectExtractor constructor. diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php index d5420e355..a25db0935 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/TestObjectExtractor.php @@ -8,13 +8,16 @@ use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use Magento\FunctionalTestingFramework\Exceptions\XmlException; +use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\Util\ModulePathExtractor; use Magento\FunctionalTestingFramework\Util\Validation\NameValidationUtil; /** * Class TestObjectExtractor + * @SuppressWarnings(PHPMD) */ class TestObjectExtractor extends BaseObjectExtractor { @@ -95,7 +98,8 @@ public function extractTestData($testData) $fileNames = explode(",", $filename); $baseFileName = $fileNames[0]; $module = $this->modulePathExtractor->extractModuleName($baseFileName); - $testReference = $testData['extends'] ?? null; + $testReference = $testData['extends'] ?? null; + $deprecated = isset($testData[self::OBJ_DEPRECATED]) ? $testData[self::OBJ_DEPRECATED] : null; $testActions = $this->stripDescriptorTags( $testData, self::NODE_NAME, @@ -107,6 +111,7 @@ public function extractTestData($testData) self::TEST_INSERT_BEFORE, self::TEST_INSERT_AFTER, self::TEST_FILENAME, + self::OBJ_DEPRECATED, 'extends' ); @@ -122,12 +127,20 @@ public function extractTestData($testData) // when $fileNames is not available if (!isset($testAnnotations["description"])) { $testAnnotations["description"] = []; + } else { + $testAnnotations["description"]['main'] = $testAnnotations["description"][0]; + unset($testAnnotations["description"][0]); + } + $testAnnotations["description"]['test_files'] = $this->appendFileNamesInDescriptionAnnotation($fileNames); + + $testAnnotations["description"][self::OBJ_DEPRECATED] = []; + if ($deprecated !== null) { + $testAnnotations["description"][self::OBJ_DEPRECATED][] = $deprecated; + LoggingUtil::getInstance()->getLogger(TestObject::class)->deprecation( + $deprecated, + ["testName" => $filename, "deprecatedTest" => $deprecated] + ); } - $description = $testAnnotations["description"][0] ?? ''; - $testAnnotations["description"][0] = $this->appendFileNamesInDescriptionAnnotation( - $description, - $fileNames - ); // extract before if (array_key_exists(self::TEST_BEFORE_HOOK, $testData) && is_array($testData[self::TEST_BEFORE_HOOK])) { @@ -152,6 +165,10 @@ public function extractTestData($testData) ); } + if (!empty($testData[self::OBJ_DEPRECATED])) { + $testAnnotations[self::OBJ_DEPRECATED] = $testData[self::OBJ_DEPRECATED]; + } + // TODO extract filename info and store try { return new TestObject( @@ -170,14 +187,13 @@ public function extractTestData($testData) /** * Append names of test files, including merge files, in description annotation * - * @param string $description - * @param array $fileNames + * @param array $fileNames * * @return string */ - private function appendFileNamesInDescriptionAnnotation($description, $fileNames) + private function appendFileNamesInDescriptionAnnotation(array $fileNames) { - $description .= '<br><br><b><font size=+0.9>Test files</font></b><br><br>'; + $filePaths = '<h3>Test files</h3>'; foreach ($fileNames as $fileName) { if (!empty($fileName) && realpath($fileName) !== false) { @@ -187,11 +203,11 @@ private function appendFileNamesInDescriptionAnnotation($description, $fileNames DIRECTORY_SEPARATOR ); if (!empty($relativeFileName)) { - $description .= $relativeFileName . '<br>'; + $filePaths .= $relativeFileName . '<br>'; } } } - return $description; + return $filePaths; } } diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd index 2424d0d31..8670d9885 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd @@ -12,6 +12,7 @@ <xs:group name="customTags"> <xs:choice> <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"/> @@ -62,6 +63,40 @@ </xs:simpleContent> </xs:complexType> + <xs:complexType name="magentoCronType"> + <xs:annotation> + <xs:documentation> + Executes Magento Cron Jobs (selected groups) + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="groups"> + <xs:annotation> + <xs:documentation> + Cron groups to be executed (separated by space) + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="arguments"> + <xs:annotation> + <xs:documentation> + Arguments for Magento CLI command, will not be escaped. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="timeout"> + <xs:annotation> + <xs:documentation> + Idle timeout in seconds, defaulted to 60s when not specified. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attributeGroup ref="commonActionAttributes"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="closeAdminNotificationType"> <xs:annotation> <xs:documentation> @@ -285,4 +320,4 @@ <xs:enumeration value="desc"/> </xs:restriction> </xs:simpleType> -</xs:schema> \ No newline at end of file +</xs:schema> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd index 6e9e798f1..bd32ba879 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd @@ -43,6 +43,13 @@ <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"> diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd index fe45945ee..6ded366bb 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/mergedTestSchema.xsd @@ -86,6 +86,13 @@ <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:group name="testTypeTags"> <xs:choice> diff --git a/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php b/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php index 0a52f6b6b..3983a755a 100644 --- a/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php +++ b/src/Magento/FunctionalTestingFramework/Util/Logger/MftfLogger.php @@ -15,15 +15,17 @@ class MftfLogger extends Logger /** * Prints a deprecation warning, as well as adds a log at the WARNING level. * - * @param string $message The log message. - * @param array $context The log context. + * @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 = []) + public function deprecation($message, array $context = [], $verbose = false) { $message = "DEPRECATION: " . $message; // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE) { + if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { print ($message . json_encode($context) . "\n"); } parent::warning($message, $context); @@ -32,15 +34,17 @@ public function deprecation($message, array $context = []) /** * Prints a critical failure, as well as adds a log at the CRITICAL level. * - * @param string $message The log message. - * @param array $context The log context. + * @param string $message The log message. + * @param array $context The log context. + * @param boolean $verbose * @return void + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException */ - public function criticalFailure($message, array $context = []) + public function criticalFailure($message, array $context = [], $verbose = false) { $message = "FAILURE: " . $message; // Suppress print during unit testing - if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE) { + if (MftfApplicationConfig::getConfig()->getPhase() !== MftfApplicationConfig::UNIT_TEST_PHASE && $verbose) { print ($message . implode("\n", $context) . "\n"); } parent::critical($message, $context); diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index fcbb49ac9..e40f60dcf 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -7,7 +7,6 @@ namespace Magento\FunctionalTestingFramework\Util; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; @@ -17,14 +16,11 @@ use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\TestHookObject; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\Test\Util\BaseObjectExtractor; use Magento\FunctionalTestingFramework\Util\Manifest\BaseTestManifest; -use Magento\FunctionalTestingFramework\Util\Manifest\TestManifestFactory; use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; -use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; use Magento\FunctionalTestingFramework\Util\Path\FilePathFormatter; @@ -40,22 +36,35 @@ class TestGenerator const REQUIRED_ENTITY_REFERENCE = 'createDataKey'; const GENERATED_DIR = '_generated'; const DEFAULT_DIR = 'default'; + const TEST_SCOPE = 'test'; const HOOK_SCOPE = 'hook'; const SUITE_SCOPE = 'suite'; + const PRESSKEY_ARRAY_ANCHOR_KEY = '987654321098765432109876543210'; const PERSISTED_OBJECT_NOTATION_REGEX = '/\${1,2}[\w.\[\]]+\${1,2}/'; const NO_STEPKEY_ACTIONS = [ 'comment', - 'createData', - 'deleteData', - 'updateData', - 'getData', + 'retrieveEntityField', + 'getSecret', 'magentoCLI', + 'magentoCron', 'generateDate', 'field' ]; + const RULE_ERROR = 'On step with stepKey "%s", only one of the attributes: "%s" can be use for action "%s"'; + const STEP_KEY_ANNOTATION = " // stepKey: %s"; + const CRON_INTERVAL = 60; + const ARRAY_WRAP_OPEN = '['; + const ARRAY_WRAP_CLOSE = ']'; + + /** + * Actor name for AcceptanceTest + * + * @var string + */ + private $actor = 'I'; /** * Path to the export dir. @@ -97,10 +106,17 @@ class TestGenerator * * @var string */ - private $currentGenerationScope; + private $currentGenerationScope = TestGenerator::TEST_SCOPE; + + /** + * Test deprecation messages. + * + * @var array + */ + private $deprecationMessages = []; /** - * TestGenerator constructor. + * Private constructor for Factory * * @param string $exportDir * @param array $tests @@ -109,13 +125,11 @@ class TestGenerator */ private function __construct($exportDir, $tests, $debug = false) { - // private constructor for factory $this->exportDirName = $exportDir ?? self::DEFAULT_DIR; - $exportDir = $exportDir ?? self::DEFAULT_DIR; $this->exportDirectory = FilePathFormatter::format(TESTS_MODULE_PATH) . self::GENERATED_DIR . DIRECTORY_SEPARATOR - . $exportDir; + . $this->exportDirName; $this->tests = $tests; $this->consoleOutput = new \Symfony\Component\Console\Output\ConsoleOutput(); $this->debug = $debug; @@ -180,13 +194,13 @@ private function loadAllTestObjects($testsToIgnore) * @return void * @throws \Exception */ - private function createCestFile($testPhp, $filename) + private function createCestFile(string $testPhp, string $filename) { $exportFilePath = $this->exportDirectory . DIRECTORY_SEPARATOR . $filename . ".php"; $file = fopen($exportFilePath, 'w'); if (!$file) { - throw new \Exception("Could not open the file."); + throw new \Exception(sprintf('Could not open test file: "%s"', $exportFilePath)); } fwrite($file, $testPhp); @@ -233,11 +247,10 @@ public function createAllTestFiles($testManifest = null, $testsToIgnore = null) public function assembleTestPhp($testObject) { $usePhp = $this->generateUseStatementsPhp(); - $classAnnotationsPhp = $this->generateAnnotationsPhp($testObject->getAnnotations()); $className = $testObject->getCodeceptionName(); try { - if (!$testObject->isSkipped() && !MftfApplicationConfig::getConfig()->allowSkipped()) { + if (!$testObject->isSkipped() || MftfApplicationConfig::getConfig()->allowSkipped()) { $hookPhp = $this->generateHooksPhp($testObject->getHooks()); } else { $hookPhp = null; @@ -246,6 +259,7 @@ public function assembleTestPhp($testObject) } catch (TestReferenceException $e) { throw new TestReferenceException($e->getMessage() . "\n" . $testObject->getFilename()); } + $classAnnotationsPhp = $this->generateAnnotationsPhp($testObject->getAnnotations()); $cestPhp = "<?php\n"; $cestPhp .= "namespace Magento\AcceptanceTest\\_" . $this->exportDirName . "\Backend;\n\n"; @@ -326,8 +340,6 @@ private function debug($messages) private function generateUseStatementsPhp() { $useStatementsPhp = "use Magento\FunctionalTestingFramework\AcceptanceTester;\n"; - $useStatementsPhp .= "use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;\n"; - $useStatementsPhp .= "use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler;\n"; $useStatementsPhp .= "use \Codeception\Util\Locator;\n"; $allureStatements = [ @@ -447,7 +459,7 @@ private function generateMethodAnnotations($annotationType = null, $annotationNa * Method which return formatted class level annotations based on type and name(s). * * @param string $annotationType - * @param string $annotationName + * @param array $annotationName * @return null|string * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -461,7 +473,8 @@ private function generateClassAnnotations($annotationType, $annotationName) break; case "description": - $annotationToAppend = sprintf(" * @Description(\"%s\")\n", $annotationName[0]); + $template = " * @Description(\"%s\")\n"; + $annotationToAppend = sprintf($template, $this->generateDescriptionAnnotation($annotationName)); break; case "testCaseId": @@ -482,6 +495,36 @@ private function generateClassAnnotations($annotationType, $annotationName) return $annotationToAppend; } + /** + * Generates Description + * + * @param array $descriptions + * @return string + */ + private function generateDescriptionAnnotation(array $descriptions) + { + $descriptionText = ""; + + $descriptionText .= $descriptions["main"] ?? ''; + if (!empty($descriptions[BaseObjectExtractor::OBJ_DEPRECATED]) || !empty($this->deprecationMessages)) { + $deprecatedMessages = array_merge( + $descriptions[BaseObjectExtractor::OBJ_DEPRECATED], + $this->deprecationMessages + ); + + $descriptionText .= "<h3 class='y-label y-label_status_broken'>Deprecated Notice(s):</h3>"; + $descriptionText .= "<ul>"; + + foreach ($deprecatedMessages as $deprecatedMessage) { + $descriptionText .= "<li>" . $deprecatedMessage . "</li>"; + } + $descriptionText .= "</ul>"; + } + $descriptionText .= $descriptions["test_files"]; + + return $descriptionText; + } + /** * Creates a PHP string for the actions contained withing a <test> block. * Since nearly half of all Codeception methods don't share the same signature I had to setup a massive Case @@ -499,10 +542,13 @@ private function generateClassAnnotations($annotationType, $annotationName) public function generateStepsPhp($actionObjects, $generationScope = TestGenerator::TEST_SCOPE, $actor = "I") { //TODO: Refactor Method according to PHPMD warnings, remove @SuppressWarnings accordingly. - $testSteps = ""; + $testSteps = ''; + $this->actor = $actor; $this->currentGenerationScope = $generationScope; + $this->deprecationMessages = []; foreach ($actionObjects as $actionObject) { + $this->deprecationMessages = array_merge($this->deprecationMessages, $actionObject->getDeprecatedUsages()); $stepKey = $actionObject->getStepKey(); $customActionAttributes = $actionObject->getCustomActionAttributes(); $attribute = null; @@ -530,6 +576,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $dependentSelector = null; $visible = null; $command = null; + $cronGroups = ''; $arguments = null; $sortOrder = null; $storeCode = null; @@ -547,6 +594,9 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato if (isset($customActionAttributes['command'])) { $command = $this->addUniquenessFunctionCall($customActionAttributes['command']); } + if (isset($customActionAttributes['groups'])) { + $cronGroups = $this->addUniquenessFunctionCall($customActionAttributes['groups']); + } if (isset($customActionAttributes['arguments'])) { $arguments = $this->addUniquenessFunctionCall($customActionAttributes['arguments']); } @@ -624,9 +674,9 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato // validate the param array is in the correct format $this->validateParameterArray($customActionAttributes['parameterArray']); - $parameterArray = "["; - $parameterArray .= $this->addUniquenessToParamArray($customActionAttributes['parameterArray']); - $parameterArray .= "]"; + $parameterArray = $this->wrapParameterArray( + $this->addUniquenessToParamArray($customActionAttributes['parameterArray']) + ); } if (isset($customActionAttributes['requiredAction'])) { @@ -726,13 +776,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato switch ($actionObject->getType()) { case "createData": $entity = $customActionAttributes['entity']; - //Add an informative statement to help the user debug test runs - $testSteps .= sprintf( - "\t\t$%s->comment(\"[%s] create '%s' entity\");\n", - $actor, - $stepKey, - $entity - ); //TODO refactor entity field override to not be individual actionObjects $customEntityFields = @@ -751,28 +794,23 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato if (!empty($requiredEntityKeys)) { $requiredEntityKeysArray = '"' . implode('", "', $requiredEntityKeys) . '"'; } - //Determine Scope - $scope = PersistedObjectHandler::TEST_SCOPE; - if ($generationScope == TestGenerator::HOOK_SCOPE) { - $scope = PersistedObjectHandler::HOOK_SCOPE; - } elseif ($generationScope == TestGenerator::SUITE_SCOPE) { - $scope = PersistedObjectHandler::SUITE_SCOPE; - } - $createEntityFunctionCall = "\t\tPersistedObjectHandler::getInstance()->createEntity("; - $createEntityFunctionCall .= "\n\t\t\t\"{$stepKey}\","; - $createEntityFunctionCall .= "\n\t\t\t\"{$scope}\","; - $createEntityFunctionCall .= "\n\t\t\t\"{$entity}\""; - $createEntityFunctionCall .= ",\n\t\t\t[{$requiredEntityKeysArray}]"; + $scope = $this->getObjectScope($generationScope); + + $createEntityFunctionCall = "\t\t\${$actor}->createEntity("; + $createEntityFunctionCall .= "\"{$stepKey}\","; + $createEntityFunctionCall .= " \"{$scope}\","; + $createEntityFunctionCall .= " \"{$entity}\","; + $createEntityFunctionCall .= " [{$requiredEntityKeysArray}],"; if (count($customEntityFields) > 1) { - $createEntityFunctionCall .= ",\n\t\t\t\${$stepKey}Fields"; + $createEntityFunctionCall .= " \${$stepKey}Fields"; } else { - $createEntityFunctionCall .= ",\n\t\t\t[]"; + $createEntityFunctionCall .= " []"; } if ($storeCode !== null) { - $createEntityFunctionCall .= ",\n\t\t\t\"{$storeCode}\""; + $createEntityFunctionCall .= ", \"{$storeCode}\""; } - $createEntityFunctionCall .= "\n\t\t);\n"; + $createEntityFunctionCall .= ");"; $testSteps .= $createEntityFunctionCall; break; case "deleteData": @@ -784,34 +822,20 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato ); $actionGroup = $actionObject->getCustomActionAttributes()['actionGroup'] ?? null; $key .= $actionGroup; - //Add an informative statement to help the user debug test runs - $contextSetter = sprintf( - "\t\t$%s->comment(\"[%s] delete entity '%s'\");\n", - $actor, - $stepKey, - $key - ); - //Determine Scope - $scope = PersistedObjectHandler::TEST_SCOPE; - if ($generationScope == TestGenerator::HOOK_SCOPE) { - $scope = PersistedObjectHandler::HOOK_SCOPE; - } elseif ($generationScope == TestGenerator::SUITE_SCOPE) { - $scope = PersistedObjectHandler::SUITE_SCOPE; - } + $scope = $this->getObjectScope($generationScope); - $deleteEntityFunctionCall = "\t\tPersistedObjectHandler::getInstance()->deleteEntity("; - $deleteEntityFunctionCall .= "\n\t\t\t\"{$key}\","; - $deleteEntityFunctionCall .= "\n\t\t\t\"{$scope}\""; - $deleteEntityFunctionCall .= "\n\t\t);\n"; + $deleteEntityFunctionCall = "\t\t\${$actor}->deleteEntity("; + $deleteEntityFunctionCall .= "\"{$key}\","; + $deleteEntityFunctionCall .= " \"{$scope}\""; + $deleteEntityFunctionCall .= ");"; - $testSteps .= $contextSetter; $testSteps .= $deleteEntityFunctionCall; } else { $url = $this->resolveAllRuntimeReferences([$url])[0]; $url = $this->resolveTestVariable([$url], null)[0]; $output = sprintf( - "\t\t$%s->deleteEntityByUrl(%s);\n", + "\t\t$%s->deleteEntityByUrl(%s);", $actor, $url ); @@ -828,15 +852,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $actionGroup = $actionObject->getCustomActionAttributes()['actionGroup'] ?? null; $key .= $actionGroup; - //Add an informative statement to help the user debug test runs - $testSteps .= sprintf( - "\t\t$%s->comment(\"[%s] update '%s' entity to '%s'\");\n", - $actor, - $stepKey, - $key, - $updateEntity - ); - // Build array of requiredEntities $requiredEntityKeys = []; foreach ($actionObject->getCustomActionAttributes() as $actionAttribute) { @@ -851,22 +866,17 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $requiredEntityKeysArray = '"' . implode('", "', $requiredEntityKeys) . '"'; } - $scope = PersistedObjectHandler::TEST_SCOPE; - if ($generationScope == TestGenerator::HOOK_SCOPE) { - $scope = PersistedObjectHandler::HOOK_SCOPE; - } elseif ($generationScope == TestGenerator::SUITE_SCOPE) { - $scope = PersistedObjectHandler::SUITE_SCOPE; - } + $scope = $this->getObjectScope($generationScope); - $updateEntityFunctionCall = "\t\tPersistedObjectHandler::getInstance()->updateEntity("; - $updateEntityFunctionCall .= "\n\t\t\t\"{$key}\","; - $updateEntityFunctionCall .= "\n\t\t\t\"{$scope}\","; - $updateEntityFunctionCall .= "\n\t\t\t\"{$updateEntity}\""; - $updateEntityFunctionCall .= ",\n\t\t\t[{$requiredEntityKeysArray}]"; + $updateEntityFunctionCall = "\t\t\${$actor}->updateEntity("; + $updateEntityFunctionCall .= "\"{$key}\","; + $updateEntityFunctionCall .= " \"{$scope}\","; + $updateEntityFunctionCall .= " \"{$updateEntity}\","; + $updateEntityFunctionCall .= "[{$requiredEntityKeysArray}]"; if ($storeCode !== null) { - $updateEntityFunctionCall .= ",\n\t\t\t\"{$storeCode}\""; + $updateEntityFunctionCall .= ", \"{$storeCode}\""; } - $updateEntityFunctionCall .= "\n\t\t);\n"; + $updateEntityFunctionCall .= ");"; $testSteps .= $updateEntityFunctionCall; break; @@ -876,13 +886,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato if (isset($customActionAttributes['index'])) { $index = (int)$customActionAttributes['index']; } - //Add an informative statement to help the user debug test runs - $testSteps .= sprintf( - "\t\t$%s->comment(\"[%s] get '%s' entity\");\n", - $actor, - $stepKey, - $entity - ); // Build array of requiredEntities $requiredEntityKeys = []; @@ -897,29 +900,23 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $requiredEntityKeysArray = '"' . implode('", "', $requiredEntityKeys) . '"'; } - //Determine Scope - $scope = PersistedObjectHandler::TEST_SCOPE; - if ($generationScope == TestGenerator::HOOK_SCOPE) { - $scope = PersistedObjectHandler::HOOK_SCOPE; - } elseif ($generationScope == TestGenerator::SUITE_SCOPE) { - $scope = PersistedObjectHandler::SUITE_SCOPE; - } + $scope = $this->getObjectScope($generationScope); //Create Function - $getEntityFunctionCall = "\t\tPersistedObjectHandler::getInstance()->getEntity("; - $getEntityFunctionCall .= "\n\t\t\t\"{$stepKey}\","; - $getEntityFunctionCall .= "\n\t\t\t\"{$scope}\","; - $getEntityFunctionCall .= "\n\t\t\t\"{$entity}\""; - $getEntityFunctionCall .= ",\n\t\t\t[{$requiredEntityKeysArray}]"; + $getEntityFunctionCall = "\t\t\${$actor}->getEntity("; + $getEntityFunctionCall .= "\"{$stepKey}\","; + $getEntityFunctionCall .= " \"{$scope}\","; + $getEntityFunctionCall .= " \"{$entity}\","; + $getEntityFunctionCall .= " [{$requiredEntityKeysArray}],"; if ($storeCode !== null) { - $getEntityFunctionCall .= ",\n\t\t\t\"{$storeCode}\""; + $getEntityFunctionCall .= " \"{$storeCode}\""; } else { - $getEntityFunctionCall .= ",\n\t\t\tnull"; + $getEntityFunctionCall .= " null"; } if ($index !== null) { - $getEntityFunctionCall .= ",\n\t\t\t{$index}"; + $getEntityFunctionCall .= ", {$index}"; } - $getEntityFunctionCall .= "\n\t\t);\n"; + $getEntityFunctionCall .= ");"; $testSteps .= $getEntityFunctionCall; break; @@ -1297,6 +1294,22 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $stepKey ); break; + case 'magentoCron': + $testSteps .= $this->wrapFunctionCallWithReturnValue( + $stepKey, + $actor, + $actionObject, + $cronGroups, + self::CRON_INTERVAL + $time, + $arguments + ); + $testSteps .= sprintf(self::STEP_KEY_ANNOTATION, $stepKey) . PHP_EOL; + $testSteps .= sprintf( + "\t\t$%s->comment(\$%s);", + $actor, + $stepKey + ); + break; case "field": $fieldKey = $actionObject->getCustomActionAttributes()['key']; $input = $this->resolveStepKeyReferences($input, $actionObject->getActionOrigin()); @@ -1330,7 +1343,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato break; case "comment": $input = $input === null ? strtr($value, ['$' => '\$', '{' => '\{', '}' => '\}']) : $input; - // Combining userInput from native XML comment and <comment/> action to fall-through 'default' case + // Combining userInput from native XML comment and <comment/> action to fall-through 'default' case default: $testSteps .= $this->wrapFunctionCall( $actor, @@ -1407,9 +1420,9 @@ private function trimVariableIfNeeded($input) preg_match('/"{\$[a-z][a-zA-Z\d]+}"/', $input, $match); if (isset($match[0])) { return trim($input, '{}"'); - } else { - return $input; } + + return $input; } /** @@ -1430,12 +1443,16 @@ private function replaceMatchesIntoArg($matches, &$outputArg) $variable = $this->stripAndSplitReference($match, $delimiter); if (count($variable) != 2) { throw new \Exception( - "Invalid Persisted Entity Reference: {$match}. + "Invalid Persisted Entity Reference: {$match}. Test persisted entity references must follow {$delimiter}entityStepKey.field{$delimiter} format." ); } - $replacement = "PersistedObjectHandler::getInstance()->retrieveEntityField"; + $actor = "\$" . $this->actor; + if ($this->currentGenerationScope === TestGenerator::SUITE_SCOPE) { + $actor = 'PersistedObjectHandler::getInstance()'; + } + $replacement = "{$actor}->retrieveEntityField"; $replacement .= "('{$variable[0]}', '$variable[1]', '{$this->currentGenerationScope}')"; //Determine if quoteBreak check is necessary. Assume replacement is surrounded in quotes, then override @@ -1490,15 +1507,20 @@ private function resolveStepKeyReferences($input, $actionGroupOrigin, $matchAll foreach ($stepKeys as $stepKey) { // MQE-1011 $stepKeyVarRef = "$" . $stepKey; - $persistedVarRef = "PersistedObjectHandler::getInstance()->retrieveEntityField('{$stepKey}'" + + $actor = "\$" . $this->actor; + if ($this->currentGenerationScope === TestGenerator::SUITE_SCOPE) { + $actor = 'PersistedObjectHandler::getInstance()'; + } + $persistedVarRef = "{$actor}->retrieveEntityField('{$stepKey}'" . ", 'field', 'test')"; - $persistedVarRefInvoked = "PersistedObjectHandler::getInstance()->retrieveEntityField('" + $persistedVarRefInvoked = "{$actor}->retrieveEntityField('" . $stepKey . $testInvocationKey . "', 'field', 'test')"; // only replace when whole word matches exactly // e.g. testVar => $testVar but not $testVar2 if (strpos($output, $stepKeyVarRef) !== false) { - $output = preg_replace('/\B\\' .$stepKeyVarRef. '\b/', $stepKeyVarRef . $testInvocationKey, $output); + $output = preg_replace('/\B\\' . $stepKeyVarRef . '\b/', $stepKeyVarRef . $testInvocationKey, $output); } if (strpos($output, $persistedVarRef) !== false) { @@ -1533,8 +1555,8 @@ private function wrapFunctionArgsWithQuotes($functionRegex, $input) foreach ($allArguments as $argument) { $argument = trim($argument); - if ($argument[0] == "[") { - $replacement = "[" . $this->addUniquenessToParamArray($argument) . "]"; + if ($argument[0] == self::ARRAY_WRAP_OPEN) { + $replacement = $this->wrapParameterArray($this->addUniquenessToParamArray($argument)); } elseif (is_numeric($argument)) { $replacement = $argument; } else { @@ -1619,7 +1641,13 @@ private function generateTestPhp($test) $testName = str_replace(' ', '', $testName); $testAnnotations = $this->generateAnnotationsPhp($test->getAnnotations(), true); $dependencies = 'AcceptanceTester $I'; - if ($test->isSkipped() && !MftfApplicationConfig::getConfig()->allowSkipped()) { + if (!$test->isSkipped() || MftfApplicationConfig::getConfig()->allowSkipped()) { + try { + $steps = $this->generateStepsPhp($test->getOrderedActions()); + } catch (\Exception $e) { + throw new TestReferenceException($e->getMessage() . " in Test \"" . $test->getName() . "\""); + } + } else { $skipString = "This test is skipped due to the following issues:\\n"; $issues = $test->getAnnotations()['skip'] ?? null; if (isset($issues)) { @@ -1629,12 +1657,6 @@ private function generateTestPhp($test) } $steps = "\t\t" . '$scenario->skip("' . $skipString . '");' . "\n"; $dependencies .= ', \Codeception\Scenario $scenario'; - } else { - try { - $steps = $this->generateStepsPhp($test->getOrderedActions()); - } catch (\Exception $e) { - throw new TestReferenceException($e->getMessage() . " in Test \"" . $test->getName() . "\""); - } } $testPhp .= $testAnnotations; @@ -1703,8 +1725,9 @@ private function processPressKey($input) preg_match_all('/[\[][^\]]*?[\]]/', $input, $paramInput); if (!empty($paramInput)) { foreach ($paramInput[0] as $param) { - $arrayResult[self::PRESSKEY_ARRAY_ANCHOR_KEY . $count] = - '[' . trim($this->addUniquenessToParamArray($param)) . ']'; + $arrayResult[self::PRESSKEY_ARRAY_ANCHOR_KEY . $count] = $this->wrapParameterArray( + trim($this->addUniquenessToParamArray($param)) + ); $input = str_replace($param, self::PRESSKEY_ARRAY_ANCHOR_KEY . $count, $input); $count++; } @@ -1798,13 +1821,8 @@ private function stripWrappedQuotes($input) if (empty($input)) { return ''; } - if (substr($input, 0, 1) === '"') { - $input = substr($input, 1); - } - if (substr($input, -1, 1) === '"') { - $input = substr($input, 0, -1); - } - return $input; + + return trim($input, '"'); } /** @@ -1818,15 +1836,12 @@ private function addDollarSign($input) return sprintf("$%s", ltrim($this->stripQuotes($input), '$')); } - // @codingStandardsIgnoreStart - /** * Wrap parameters into a function call. * - * @param string $actor + * @param string $actor * @param actionObject $action - * @param string $scope - * @param array ...$args + * @param array ...$args * @return string * @throws \Exception */ @@ -1839,7 +1854,7 @@ private function wrapFunctionCall($actor, $action, ...$args) continue; } if ($args[$i] === "") { - $args[$i] = '"' . $args[$i] . '"'; + $args[$i] = '""'; } } if (!is_array($args)) { @@ -1847,7 +1862,7 @@ private function wrapFunctionCall($actor, $action, ...$args) } $args = $this->resolveAllRuntimeReferences($args); $args = $this->resolveTestVariable($args, $action->getActionOrigin()); - $output .= implode(", ", array_filter($args, function($value) { return $value !== null; })) . ");"; + $output .= implode(", ", array_filter($args, $this->filterNullCallback())) . ");"; return $output; } @@ -1857,8 +1872,7 @@ private function wrapFunctionCall($actor, $action, ...$args) * @param string $returnVariable * @param string $actor * @param string $action - * @param string $scope - * @param array ...$args + * @param array ...$args * @return string * @throws \Exception */ @@ -1871,7 +1885,7 @@ private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $actio continue; } if ($args[$i] === "") { - $args[$i] = '"' . $args[$i] . '"'; + $args[$i] = '""'; } } if (!is_array($args)) { @@ -1879,13 +1893,25 @@ private function wrapFunctionCallWithReturnValue($returnVariable, $actor, $actio } $args = $this->resolveAllRuntimeReferences($args); $args = $this->resolveTestVariable($args, $action->getActionOrigin()); - $output .= implode(", ", array_filter($args, function($value) { return $value !== null; })) . ");"; + $output .= implode(", ", array_filter($args, $this->filterNullCallback())) . ");"; return $output; } - // @codingStandardsIgnoreEnd + + /** + * Closure returned is used as a callable for array_filter to remove null values from array + * + * @return callable + */ + private function filterNullCallback() + { + return function ($value) { + return $value !== null; + }; + } /** * Resolves {{_ENV.variable}} into getenv("variable") for test-runtime ENV referencing. + * * @param array $args * @param string $regex * @param string $func @@ -1925,7 +1951,7 @@ private function resolveAllRuntimeReferences($args) { $runtimeReferenceRegex = [ "/{{_ENV\.([\w]+)}}/" => 'getenv', - ActionMergeUtil::CREDS_REGEX => 'CredentialStore::getInstance()->getSecret' + ActionMergeUtil::CREDS_REGEX => "\${$this->actor}->getSecret" ]; $argResult = $args; @@ -1945,43 +1971,79 @@ private function resolveAllRuntimeReferences($args) */ private function validateParameterArray($paramArray) { - if (substr($paramArray, 0, 1) != "[" || substr($paramArray, strlen($paramArray) - 1, 1) != "]") { - throw new TestReferenceException("parameterArray must begin with `[` and end with `]"); + if (!$this->isWrappedArray($paramArray)) { + throw new TestReferenceException(sprintf( + "parameterArray must begin with `%s` and end with `%s`", + self::ARRAY_WRAP_OPEN, + self::ARRAY_WRAP_CLOSE + )); } } + /** + * Verifies whether we have correctly wrapped array syntax + * + * @param string $paramArray + * @return boolean + */ + private function isWrappedArray(string $paramArray) + { + return 0 === strpos($paramArray, self::ARRAY_WRAP_OPEN) + && substr($paramArray, -1) === self::ARRAY_WRAP_CLOSE; + } + /** * Resolve value based on type. * - * @param string $value - * @param string $type - * @return string + * @param string|null $value + * @param string|null $type + * @return string|null * @throws TestReferenceException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function resolveValueByType($value, $type) + private function resolveValueByType($value = null, $type = null) { - //TODO: Refactor to deal with PHPMD.CyclomaticComplexity, and remove @SuppressWarnings if (null === $value) { return null; } + if (null === $type) { $type = 'const'; } - if ($type == "string") { - return $this->addUniquenessFunctionCall($value); - } elseif ($type == "bool") { - return $this->toBoolean($value) ? "true" : "false"; - } elseif ($type == "int" || $type == "float") { - return $this->toNumber($value); - } elseif ($type == "array") { - $this->validateParameterArray($value); - return "[" . $this->addUniquenessToParamArray($value) . "]"; - } elseif ($type == "variable") { - return $this->addDollarSign($value); - } else { - return $value; + + switch ($type) { + case 'string': + return $this->addUniquenessFunctionCall($value); + case 'bool': + return $this->toBoolean($value) ? "true" : "false"; + case 'int': + case 'float': + return $this->toNumber($value); + case 'array': + $this->validateParameterArray($value); + return $this->wrapParameterArray($this->addUniquenessToParamArray($value)); + case 'variable': + return $this->addDollarSign($value); } + + return $value; + } + + /** + * Determines correct scope based on parameter + * + * @param string $generationScope + * @return string + */ + private function getObjectScope(string $generationScope): string + { + switch ($generationScope) { + case TestGenerator::SUITE_SCOPE: + return PersistedObjectHandler::SUITE_SCOPE; + case TestGenerator::HOOK_SCOPE: + return PersistedObjectHandler::HOOK_SCOPE; + } + + return PersistedObjectHandler::TEST_SCOPE; } /** @@ -2004,11 +2066,11 @@ private function toBoolean($inStr) private function toNumber($inStr) { $outStr = $this->stripQuotes($inStr); - if (strpos($outStr, localeconv()['decimal_point']) === false) { - return intval($outStr); - } else { + if ($this->hasDecimalPoint($outStr)) { return floatval($outStr); } + + return intval($outStr); } /** @@ -2095,9 +2157,29 @@ private function printRuleErrorToConsole($key, $tagName, $attributes) if (empty($tagName) || empty($attributes)) { return; } - $message = 'On step with stepKey "' . $key . '", only one of the attributes: "'; - $message .= implode('", "', $attributes); - $message .= '" can be use for action "' . $tagName . "\".\n"; - print $message; + + printf(self::RULE_ERROR, $key, implode('", "', $attributes), $tagName); + } + + /** + * Wraps parameters array with opening and closing symbol. + * + * @param string $value + * @return string + */ + private function wrapParameterArray(string $value): string + { + return sprintf('%s%s%s', self::ARRAY_WRAP_OPEN, $value, self::ARRAY_WRAP_CLOSE); + } + + /** + * Determines whether string provided contains decimal point characteristic for current locale + * + * @param string $outStr + * @return boolean + */ + private function hasDecimalPoint(string $outStr) + { + return strpos($outStr, localeconv()['decimal_point']) === false; } }