From 6363af9b9d9db406acc22e69890768aa34787e15 Mon Sep 17 00:00:00 2001 From: John S Date: Fri, 31 May 2019 13:57:56 -0500 Subject: [PATCH 01/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Removed the "page" attribute from the annotations block. --- .../FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd index 616995531..6e9e798f1 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd @@ -34,7 +34,6 @@ - From 6a528c5e5ca9124397c515370efe47c5cd9ac8d8 Mon Sep 17 00:00:00 2001 From: John S Date: Mon, 3 Jun 2019 14:25:54 -0500 Subject: [PATCH 02/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Removed the "page" from the Required Annotations XML Scheme test. --- .../Test/Util/ActionGroupAnnotationExtractor.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php index b6e89fd44..44b004105 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php @@ -14,8 +14,7 @@ class ActionGroupAnnotationExtractor extends AnnotationExtractor { const ACTION_GROUP_REQUIRED_ANNOTATIONS = [ - "description", - "page", + "description" ]; const GENERATE_DOCS_COMMAND = 'generate:docs'; From 9bdfa62cdd40952b3a798fb4ccbad07483b44539 Mon Sep 17 00:00:00 2001 From: John S Date: Tue, 4 Jun 2019 14:03:58 -0500 Subject: [PATCH 03/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Removing the remaining Action Group "Page" references from the code base. --- .../ActionGroupAnnotationExtractorTest.php | 12 +++-------- .../Util/DocGeneratorTest.php | 4 ---- .../unit/Resources/alteredDocumentation.txt | 8 +------ .../unit/Resources/basicDocumentation.txt | 8 +------ .../Util/DocGenerator.php | 21 +++++++------------ 5 files changed, 13 insertions(+), 40 deletions(-) diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php index d56608894..af39298b1 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php @@ -34,10 +34,6 @@ public function testActionGroupExtractAnnotations() "description" => [ "nodeName" => "description", "value" => "someDescription" - ], - "page" => [ - "nodeName" => "page", - "value" => "somePage" ] ]; // Perform Test @@ -45,8 +41,6 @@ public function testActionGroupExtractAnnotations() $returnedAnnotations = $extractor->extractAnnotations($actionGroupAnnotations, "fileName"); // Asserts - - $this->assertEquals("somePage", $returnedAnnotations['page']); $this->assertEquals("someDescription", $returnedAnnotations['description']); } @@ -57,7 +51,7 @@ public function testActionGroupExtractAnnotations() */ public function testActionGroupMissingAnnotations() { - // Action Group Data, missing page and description + // Action Group Data, missing description $testAnnotations = []; // Perform Test $extractor = new ActionGroupAnnotationExtractor(); @@ -70,7 +64,7 @@ public function testActionGroupMissingAnnotations() 'DEPRECATION: Action Group File fileName is missing required annotations.', [ 'actionGroup' => 'fileName', - 'missingAnnotations' => "description, page" + 'missingAnnotations' => "description" ] ); } @@ -83,7 +77,7 @@ public function testActionGroupMissingAnnotations() */ public function testActionGroupMissingAnnotationsNoWarning() { - // Action Group Data, missing page and description + // Action Group Data, missing description $testAnnotations = []; // Perform Test $extractor = new ActionGroupAnnotationExtractor(); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php index ae61f37af..0fb73e53f 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php @@ -23,7 +23,6 @@ class DocGeneratorTest extends MagentoTestCase public function testBasicCreateDocumentation() { $annotations = [ - "page" => "somePage", "description" => "someDescription" ]; $actionGroupUnderTest = (new ActionGroupObjectBuilder()) @@ -55,7 +54,6 @@ public function testBasicCreateDocumentation() public function testCreateDocumentationWithOverwrite() { $annotations = [ - "page" => "somePage", "description" => "someDescription" ]; $actionGroupUnderTest = (new ActionGroupObjectBuilder()) @@ -70,7 +68,6 @@ public function testCreateDocumentationWithOverwrite() ); $annotations = [ - "page" => "alteredPage", "description" => "alteredDescription" ]; $actionGroupUnderTest = (new ActionGroupObjectBuilder()) @@ -102,7 +99,6 @@ public function testCreateDocumentationWithOverwrite() public function testCreateDocumentationNotCleanException() { $annotations = [ - "page" => "somePage", "description" => "someDescription" ]; $actionGroupUnderTest = (new ActionGroupObjectBuilder()) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index b55c30d6b..c9e39cd4e 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -1,11 +1,5 @@ #Action Group Information -This documentation contains a list of all action groups on the pages on which they start - -##List of Pages -- [ alteredPage ](#alteredPage) ---- - -##alteredPage +This documentation contains a list of all action groups ###testActionGroupObject alteredDescription diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 26a7fe719..1dce4de21 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -1,11 +1,5 @@ #Action Group Information -This documentation contains a list of all action groups on the pages on which they start - -##List of Pages -- [ somePage ](#somePage) ---- - -##somePage +This documentation contains a list of all action groups ###testActionGroupObject someDescription diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php index 9846cded5..2642a715f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -76,7 +76,8 @@ public function createDocumentation($annotatedObjects, $outputDir, $clean) ?? 'NO_DESCRIPTION_SPECIFIED', self::FILENAMES => $filenames, ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS => $arguments - ]; + ]; + $pageGroups = array_merge_recursive( $pageGroups, [$annotations[ActionGroupObject::ACTION_GROUP_PAGE] ?? 'NO_PAGE_SPECIFIED' => [$name => $info]] @@ -103,26 +104,20 @@ public function createDocumentation($annotatedObjects, $outputDir, $clean) private function transformToMarkdown($annotationList) { $markdown = "#Action Group Information" . PHP_EOL; - $markdown .= "This documentation contains a list of all" . - " action groups on the pages on which they start" . + $markdown .= "This documentation contains a list of all Action Groups." . PHP_EOL . PHP_EOL; - $markdown .= "##List of Pages" . PHP_EOL; - foreach ($annotationList as $group => $objects) { - $markdown .= "- [ $group ](#$group)" . PHP_EOL; - } $markdown .= "---" . PHP_EOL; foreach ($annotationList as $group => $objects) { - $markdown .= "" . PHP_EOL; - $markdown .= "##$group" . PHP_EOL . PHP_EOL; foreach ($objects as $name => $annotations) { $markdown .= "###$name" . PHP_EOL; - $markdown .= $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] . PHP_EOL . PHP_EOL; + $markdown .= "**Description**:" . PHP_EOL; + $markdown .= "- " . $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] . PHP_EOL . PHP_EOL; if (!empty($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS])) { - $markdown .= "Action Group Arguments:" . PHP_EOL . PHP_EOL; + $markdown .= "**Action Group Arguments**:" . PHP_EOL . PHP_EOL; $markdown .= "| Name | Type |" . PHP_EOL; - $markdown .= "| --- | --- |" . PHP_EOL; + $markdown .= "| ---- | ---- |" . PHP_EOL; foreach ($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS] as $argument) { $argumentName = $argument->getName(); $argumentType = $argument->getDataType(); @@ -130,7 +125,7 @@ private function transformToMarkdown($annotationList) } $markdown .= PHP_EOL; } - $markdown .= "Located in:" . PHP_EOL; + $markdown .= "**Located In**:" . PHP_EOL; foreach ($annotations[self::FILENAMES] as $filename) { $relativeFilename = str_replace(MAGENTO_BP . DIRECTORY_SEPARATOR, "", $filename); $markdown .= PHP_EOL . "- $relativeFilename"; From d3556aca320c2268e27c9e82b73ab26b1945ff24 Mon Sep 17 00:00:00 2001 From: John S Date: Wed, 5 Jun 2019 10:26:54 -0500 Subject: [PATCH 04/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Test. --- dev/tests/unit/Resources/alteredDocumentation.txt | 8 ++++---- dev/tests/unit/Resources/basicDocumentation.txt | 8 ++++---- .../FunctionalTestingFramework/Util/DocGenerator.php | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index c9e39cd4e..bc4bddd17 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -1,10 +1,10 @@ #Action Group Information -This documentation contains a list of all action groups +This documentation contains a list of all Action Groups. ###testActionGroupObject -alteredDescription - -Located in: +**Description**: +- alteredDescription +**Located in**: - filename *** diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 1dce4de21..129499e22 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -1,10 +1,10 @@ #Action Group Information -This documentation contains a list of all action groups +This documentation contains a list of all Action Groups. ###testActionGroupObject -someDescription - -Located in: +**Description**: +- someDescription +**Located in**: - filename *** diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php index 2642a715f..0eacf46e2 100644 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -128,7 +128,7 @@ private function transformToMarkdown($annotationList) $markdown .= "**Located In**:" . PHP_EOL; foreach ($annotations[self::FILENAMES] as $filename) { $relativeFilename = str_replace(MAGENTO_BP . DIRECTORY_SEPARATOR, "", $filename); - $markdown .= PHP_EOL . "- $relativeFilename"; + $markdown .= "- $relativeFilename"; } $markdown .= PHP_EOL . "***" . PHP_EOL; } From 0d0f789321c20bbe2693811480591dadefe09e13 Mon Sep 17 00:00:00 2001 From: John S Date: Wed, 5 Jun 2019 11:16:17 -0500 Subject: [PATCH 05/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Test. --- dev/tests/unit/Resources/alteredDocumentation.txt | 2 +- dev/tests/unit/Resources/basicDocumentation.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index bc4bddd17..5e4d70774 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -5,6 +5,6 @@ This documentation contains a list of all Action Groups. **Description**: - alteredDescription -**Located in**: +**Located In**: - filename *** diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 129499e22..43f1c9521 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -5,6 +5,6 @@ This documentation contains a list of all Action Groups. **Description**: - someDescription -**Located in**: +**Located In**: - filename *** From c5b651bac9a033fc645f002d3bc9d323a2a51ca5 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk Date: Wed, 5 Jun 2019 14:15:10 -0500 Subject: [PATCH 06/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report --- etc/config/codeception.dist.yml | 2 + .../Allure/Adapter/MagentoAllureAdapter.php | 31 +++++- .../Codeception/Subscriber/Console.php | 97 +++++++++++++++++++ .../Util/TestGenerator.php | 24 +++-- 4 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php diff --git a/etc/config/codeception.dist.yml b/etc/config/codeception.dist.yml index e6b03fab8..30697dc8f 100755 --- a/etc/config/codeception.dist.yml +++ b/etc/config/codeception.dist.yml @@ -8,10 +8,12 @@ paths: support: src/Magento/FunctionalTestingFramework envs: etc/_envs settings: + silent: true colors: true memory_limit: 1024M extensions: enabled: + - Magento\FunctionalTestingFramework\Codeception\Subscriber\Console - Magento\FunctionalTestingFramework\Extension\TestContextExtension - Magento\FunctionalTestingFramework\Allure\Adapter\MagentoAllureAdapter config: diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 65be8ea84..2784555af 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -5,8 +5,10 @@ */ namespace Magento\FunctionalTestingFramework\Allure\Adapter; +use Codeception\Step\Comment; use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; +use \Magento\FunctionalTestingFramework\Util\TestGenerator; use Yandex\Allure\Adapter\Model\Step; use Yandex\Allure\Codeception\AllureCodeception; use Yandex\Allure\Adapter\Event\StepStartedEvent; @@ -31,6 +33,8 @@ class MagentoAllureAdapter extends AllureCodeception { const STEP_PASSED = "passed"; + private $testFiles = []; + /** * Array of group values passed to test runner command * @@ -116,6 +120,11 @@ public function stepBefore(StepEvent $stepEvent) { //Hard set to 200; we don't expose this config in MFTF $argumentsLength = 200; + $stepKey = null; + + if (!($stepEvent->getStep() instanceof Comment)) { + $stepKey = $this->retrieveStepKey($stepEvent->getStep()->getLine()); + } // 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) { @@ -130,7 +139,11 @@ public function stepBefore(StepEvent $stepEvent) $stepArgs = $stepEvent->getStep()->getMetaStep()->getArgumentsAsString($argumentsLength); } - $stepName = $stepAction . ' ' . $stepArgs; + $stepName = ''; + if ($stepKey !== null) { + $stepName .= '[' . $stepKey . '] '; + } + $stepName .= $stepAction . ' ' . $stepArgs; // Strip control characters so that report generation does not fail $stepName = preg_replace('/[[:cntrl:]]/', '', $stepName); @@ -220,4 +233,20 @@ function () use ($rootStep, $formattedSteps) { $this->getLifecycle()->fire(new TestCaseFinishedEvent()); } + + private function retrieveStepKey($stepLine) + { + $stepKey = null; + list($filePath, $stepLine) = explode(":", $stepLine); + $prevStepLine = $stepLine - 2; + + if (!array_key_exists($filePath, $this->testFiles)) { + $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); + } + $testFile = $this->testFiles[$filePath]; + + list($stepKey) = sscanf($testFile[$prevStepLine], TestGenerator::STEP_KEY_ANNOTATION); + + return $stepKey; + } } diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php new file mode 100644 index 000000000..6f4bc4461 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -0,0 +1,97 @@ +steps or !$e->getTest() instanceof ScenarioDriven) { + return; + } + $metaStep = $e->getStep()->getMetaStep(); + if ($metaStep and $this->metaStep != $metaStep) { + $this->message(' ' . $metaStep->getPrefix()) + ->style('bold') + ->append($metaStep->__toString()) + ->writeln(); + } + $this->metaStep = $metaStep; + + $this->printStepKeys($e->getStep()); + } + + private function printStepKeys(Step $step) + { + if ($step instanceof Comment and $step->__toString() == '') { + return; // don't print empty comments + } + + $stepKey = $this->retrieveStepKey($step->getLine()); + + $msg = $this->message(' '); + if ($this->metaStep) { + $msg->append(' '); + } + if ($stepKey !== null) { + $msg->append(OutputFormatter::escape("[" . $stepKey . "] ")); + } + + if (!$this->metaStep) { + $msg->style('bold'); + } + + $msg->append(OutputFormatter::escape($step->toString($this->width))); + if ($this->metaStep) { + $msg->style('info'); + } + $msg->writeln(); + } + + /** + * @param $string + * @return Message + */ + private function message($string = '') + { + return $this->messageFactory->message($string); + } + + private function retrieveStepKey($stepLine) + { + $stepKey = null; + list($filePath, $stepLine) = explode(":", $stepLine); + $prevStepLine = $stepLine - 2; + + if (!array_key_exists($filePath, $this->testFiles)) { + $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); + } + $testFile = $this->testFiles[$filePath]; + + list($stepKey) = sscanf($testFile[$prevStepLine], TestGenerator::STEP_KEY_ANNOTATION); + + return $stepKey; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 07cb96b3a..977027c4d 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -39,6 +39,7 @@ class TestGenerator const SUITE_SCOPE = 'suite'; const PRESSKEY_ARRAY_ANCHOR_KEY = '987654321098765432109876543210'; const PERSISTED_OBJECT_NOTATION_REGEX = '/\${1,2}[\w.\[\]]+\${1,2}/'; + const STEP_KEY_ANNOTATION = "\t\t/** @stepKey %s */"; /** * Path to the export dir. @@ -697,14 +698,19 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato if (isset($customActionAttributes['storeCode'])) { $storeCode = $customActionAttributes['storeCode']; } + + if ($actionObject->getType() !== 'comment') { + $testSteps .= PHP_EOL . sprintf(self::STEP_KEY_ANNOTATION, $stepKey) . PHP_EOL; + } switch ($actionObject->getType()) { case "createData": $entity = $customActionAttributes['entity']; //Add an informative statement to help the user debug test runs $testSteps .= sprintf( - "\t\t$%s->amGoingTo(\"create entity that has the stepKey: %s\");\n", + "\t\t$%s->comment(\"[%s] create '%s' entity\");\n", $actor, - $stepKey + $stepKey, + $entity ); //TODO refactor entity field override to not be individual actionObjects @@ -759,8 +765,9 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $key .= $actionGroup; //Add an informative statement to help the user debug test runs $contextSetter = sprintf( - "\t\t$%s->amGoingTo(\"delete entity that has the createDataKey: %s\");\n", + "\t\t$%s->comment(\"[%s] delete entity '%s'\");\n", $actor, + $stepKey, $key ); @@ -802,9 +809,11 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato //Add an informative statement to help the user debug test runs $testSteps .= sprintf( - "\t\t$%s->amGoingTo(\"update entity that has the createdDataKey: %s\");\n", + "\t\t$%s->comment(\"[%s] update '%s' entity to '%s'\");\n", $actor, - $key + $stepKey, + $key, + $updateEntity ); // Build array of requiredEntities @@ -848,9 +857,10 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } //Add an informative statement to help the user debug test runs $testSteps .= sprintf( - "\t\t$%s->amGoingTo(\"get entity that has the stepKey: %s\");\n", + "\t\t$%s->comment(\"[%s] get '%s' entity\");\n", $actor, - $stepKey + $stepKey, + $entity ); // Build array of requiredEntities From eb87ccfaeefdbc6b298a56384daf9095cbc916b4 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk Date: Wed, 5 Jun 2019 16:06:00 -0500 Subject: [PATCH 07/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report - test fixes --- .../ActionGroupContainsStepKeyInArgText.txt | 12 +- .../ActionGroupMergedViaInsertAfter.txt | 16 +- .../ActionGroupMergedViaInsertBefore.txt | 16 +- .../Resources/ActionGroupToExtend.txt | 8 +- .../Resources/ActionGroupUsingCreateData.txt | 10 +- .../ActionGroupUsingNestedArgument.txt | 8 +- .../ActionGroupWithDataOverrideTest.txt | 39 ++-- .../Resources/ActionGroupWithDataTest.txt | 39 ++-- ...hDefaultArgumentAndStringSelectorParam.txt | 6 +- ...eParameterSelectorsFromDefaultArgument.txt | 6 +- .../Resources/ActionGroupWithNoArguments.txt | 6 +- .../ActionGroupWithNoDefaultTest.txt | 35 +-- ...roupWithParameterizedElementWithHyphen.txt | 6 +- ...thPassedArgumentAndStringSelectorParam.txt | 6 +- .../ActionGroupWithPersistedData.txt | 38 ++-- ...tionGroupWithSectionAndDataAsArguments.txt | 6 +- ...WithSimpleDataUsageFromDefaultArgument.txt | 6 +- ...pWithSimpleDataUsageFromPassedArgument.txt | 60 ++--- ...leParameterSelectorFromDefaultArgument.txt | 6 +- ...gleParameterSelectorFromPassedArgument.txt | 6 +- .../ActionGroupWithStepKeyReferences.txt | 48 ++-- .../ActionGroupWithTopLevelPersistedData.txt | 35 +-- .../ArgumentWithSameNameAsElement.txt | 29 +-- .../verification/Resources/AssertTest.txt | 212 +++++++++--------- .../Resources/BasicActionGroupTest.txt | 23 +- .../Resources/BasicFunctionalTest.txt | 194 ++++++++-------- .../verification/Resources/BasicMergeTest.txt | 38 ++-- .../Resources/CharacterReplacementTest.txt | 16 +- .../Resources/ChildExtendedTestAddHooks.txt | 6 +- .../Resources/ChildExtendedTestMerging.txt | 10 +- .../ChildExtendedTestRemoveAction.txt | 6 +- .../ChildExtendedTestRemoveHookAction.txt | 4 +- .../Resources/ChildExtendedTestReplace.txt | 6 +- .../ChildExtendedTestReplaceHook.txt | 6 +- .../Resources/DataActionsTest.txt | 24 +- .../Resources/DataReplacementTest.txt | 52 ++--- .../Resources/ExecuteInSeleniumTest.txt | 2 +- .../Resources/ExecuteJsEscapingTest.txt | 10 +- .../Resources/ExtendParentDataTest.txt | 13 +- .../Resources/ExtendedActionGroup.txt | 10 +- .../ExtendedChildTestInSuiteCest.txt | 6 +- .../Resources/ExtendedChildTestNotInSuite.txt | 6 +- .../Resources/ExtendedRemoveActionGroup.txt | 4 +- .../Resources/ExtendingSkippedTest.txt | 6 +- .../Resources/HookActionsTest.txt | 17 +- .../Resources/LocatorFunctionTest.txt | 27 +-- .../Resources/MergeMassViaInsertAfter.txt | 12 +- .../Resources/MergeMassViaInsertBefore.txt | 12 +- .../Resources/MergedActionGroupTest.txt | 33 +-- .../Resources/MergedReferencesTest.txt | 10 +- .../Resources/MultipleActionGroupsTest.txt | 53 ++--- .../Resources/PageReplacementTest.txt | 25 ++- .../Resources/ParameterArrayTest.txt | 47 ++-- .../Resources/ParentExtendedTest.txt | 6 +- .../PersistedAndXmlEntityArguments.txt | 6 +- .../Resources/PersistedReplacementTest.txt | 26 ++- .../PersistenceActionGroupAppendingTest.txt | 32 ++- .../Resources/PersistenceCustomFieldsTest.txt | 35 ++- .../Resources/SectionReplacementTest.txt | 73 +++--- .../Resources/functionalSuiteHooks.txt | 8 +- .../Allure/Adapter/MagentoAllureAdapter.php | 21 +- .../Codeception/Subscriber/Console.php | 41 +++- .../Handlers/ActionGroupObjectHandler.php | 4 +- .../Test/Objects/ActionGroupObject.php | 4 +- .../Util/TestGenerator.php | 18 +- 65 files changed, 864 insertions(+), 747 deletions(-) diff --git a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt index a9d6c3d27..c98120d03 100644 --- a/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt +++ b/dev/tests/verification/Resources/ActionGroupContainsStepKeyInArgText.txt @@ -24,9 +24,9 @@ class ActionGroupContainsStepKeyInArgTextCest */ public function _before(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupContainsStepKeyInArgValue (actionGroup)"); - $I->see("arg1", ".selector"); - $I->comment("Exiting Action Group actionGroupContainsStepKeyInArgValue (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupContainsStepKeyInArgValue"); + $I->see("arg1", ".selector"); // stepKey: arg1ActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupContainsStepKeyInArgValue"); } /** @@ -38,8 +38,8 @@ class ActionGroupContainsStepKeyInArgTextCest */ public function ActionGroupContainsStepKeyInArgText(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupContainsStepKeyInArgValue (actionGroup)"); - $I->see("arg1", ".selector"); - $I->comment("Exiting Action Group actionGroupContainsStepKeyInArgValue (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupContainsStepKeyInArgValue"); + $I->see("arg1", ".selector"); // stepKey: arg1ActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupContainsStepKeyInArgValue"); } } diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt index 1573c0d43..c607cb7b2 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertAfter.txt @@ -27,13 +27,13 @@ class ActionGroupMergedViaInsertAfterCest */ public function ActionGroupMergedViaInsertAfter(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupForMassMergeAfter (keyone)"); - $I->fillField("#foo", "foo"); - $I->fillField("#bar", "bar"); - $I->click("#foo2"); - $I->click("#bar2"); - $I->click("#baz2"); - $I->fillField("#baz", "baz"); - $I->comment("Exiting Action Group FunctionalActionGroupForMassMergeAfter (keyone)"); + $I->comment("Entering Action Group [keyone] FunctionalActionGroupForMassMergeAfter"); + $I->fillField("#foo", "foo"); // stepKey: fillField1Keyone + $I->fillField("#bar", "bar"); // stepKey: fillField2Keyone + $I->click("#foo2"); // stepKey: mergeAfterBarKeyone + $I->click("#bar2"); // stepKey: mergeAfterFoo2Keyone + $I->click("#baz2"); // stepKey: mergeAfterBar2Keyone + $I->fillField("#baz", "baz"); // stepKey: fillField3Keyone + $I->comment("Exiting Action Group [keyone] FunctionalActionGroupForMassMergeAfter"); } } diff --git a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt index 5dda9af14..08281a965 100644 --- a/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt +++ b/dev/tests/verification/Resources/ActionGroupMergedViaInsertBefore.txt @@ -27,13 +27,13 @@ class ActionGroupMergedViaInsertBeforeCest */ public function ActionGroupMergedViaInsertBefore(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupForMassMergeBefore (keyone)"); - $I->fillField("#foo", "foo"); - $I->click("#foo2"); - $I->click("#bar2"); - $I->click("#baz2"); - $I->fillField("#bar", "bar"); - $I->fillField("#baz", "baz"); - $I->comment("Exiting Action Group FunctionalActionGroupForMassMergeBefore (keyone)"); + $I->comment("Entering Action Group [keyone] FunctionalActionGroupForMassMergeBefore"); + $I->fillField("#foo", "foo"); // stepKey: fillField1Keyone + $I->click("#foo2"); // stepKey: mergeBeforeBarKeyone + $I->click("#bar2"); // stepKey: mergeAfterFoo2Keyone + $I->click("#baz2"); // stepKey: mergeAfterBar2Keyone + $I->fillField("#bar", "bar"); // stepKey: fillField2Keyone + $I->fillField("#baz", "baz"); // stepKey: fillField3Keyone + $I->comment("Exiting Action Group [keyone] FunctionalActionGroupForMassMergeBefore"); } } diff --git a/dev/tests/verification/Resources/ActionGroupToExtend.txt b/dev/tests/verification/Resources/ActionGroupToExtend.txt index 40fdedeb9..b91c06036 100644 --- a/dev/tests/verification/Resources/ActionGroupToExtend.txt +++ b/dev/tests/verification/Resources/ActionGroupToExtend.txt @@ -27,9 +27,9 @@ class ActionGroupToExtendCest */ public function ActionGroupToExtend(AcceptanceTester $I) { - $I->comment("Entering Action Group ActionGroupToExtend (actionGroup)"); - $grabProductsActionGroup = $I->grabMultiple("selector"); - $I->assertCount(99, $grabProductsActionGroup); - $I->comment("Exiting Action Group ActionGroupToExtend (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] ActionGroupToExtend"); + $grabProductsActionGroup = $I->grabMultiple("selector"); // stepKey: grabProductsActionGroup + $I->assertCount(99, $grabProductsActionGroup); // stepKey: assertCountActionGroup + $I->comment("Exiting Action Group [actionGroup] ActionGroupToExtend"); } } diff --git a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt index f011d307a..6831b0914 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt @@ -24,8 +24,8 @@ class ActionGroupUsingCreateDataCest */ public function _before(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithCreateData (Key1)"); - $I->amGoingTo("create entity that has the stepKey: createCategoryKey1"); + $I->comment("Entering Action Group [Key1] actionGroupWithCreateData"); + $I->comment("[createCategoryKey1] create 'ApiCategory' entity"); PersistedObjectHandler::getInstance()->createEntity( "createCategoryKey1", "hook", @@ -33,7 +33,8 @@ class ActionGroupUsingCreateDataCest [], null ); - $I->amGoingTo("create entity that has the stepKey: createConfigProductKey1"); + + $I->comment("[createConfigProductKey1] create 'ApiConfigurableProduct' entity"); PersistedObjectHandler::getInstance()->createEntity( "createConfigProductKey1", "hook", @@ -41,7 +42,8 @@ class ActionGroupUsingCreateDataCest ["createCategoryKey1"], null ); - $I->comment("Exiting Action Group actionGroupWithCreateData (Key1)"); + + $I->comment("Exiting Action Group [Key1] actionGroupWithCreateData"); } /** diff --git a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt index 8d6bf7a3a..13b67b10f 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingNestedArgument.txt @@ -27,9 +27,9 @@ class ActionGroupUsingNestedArgumentCest */ public function ActionGroupUsingNestedArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group ActionGroupToExtend (actionGroup)"); - $grabProductsActionGroup = $I->grabMultiple("selector"); - $I->assertCount(99, $grabProductsActionGroup); - $I->comment("Exiting Action Group ActionGroupToExtend (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] ActionGroupToExtend"); + $grabProductsActionGroup = $I->grabMultiple("selector"); // stepKey: grabProductsActionGroup + $I->assertCount(99, $grabProductsActionGroup); // stepKey: assertCountActionGroup + $I->comment("Exiting Action Group [actionGroup] ActionGroupToExtend"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt index a584c0f50..3785b4dd6 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt @@ -25,7 +25,7 @@ class ActionGroupWithDataOverrideTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ActionGroupWithDataOverrideTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ActionGroupWithDataOverrideTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ActionGroupWithDataOverrideTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,14 +72,14 @@ class ActionGroupWithDataOverrideTestCest */ public function ActionGroupWithDataOverrideTest(AcceptanceTester $I) { - $I->amOnPage("/someUrl"); - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroupWithDataOverride1)"); - $I->amOnPage("/John/Doe.html"); - $I->fillField("#foo", "John"); - $I->fillField("#bar", "Doe"); - $I->searchAndMultiSelectOption("#foo", ["John", "Doe"]); - $I->see("#element .John"); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroupWithDataOverride1)"); - $I->click("loginButton"); + $I->amOnPage("/someUrl"); // stepKey: step1 + $I->comment("Entering Action Group [actionGroupWithDataOverride1] FunctionalActionGroupWithData"); + $I->amOnPage("/John/Doe.html"); // stepKey: amOnPage1ActionGroupWithDataOverride1 + $I->fillField("#foo", "John"); // stepKey: fillField1ActionGroupWithDataOverride1 + $I->fillField("#bar", "Doe"); // stepKey: fillField2ActionGroupWithDataOverride1 + $I->searchAndMultiSelectOption("#foo", ["John", "Doe"]); // stepKey: multi1ActionGroupWithDataOverride1 + $I->see("#element .John"); // stepKey: see1ActionGroupWithDataOverride1 + $I->comment("Exiting Action Group [actionGroupWithDataOverride1] FunctionalActionGroupWithData"); + $I->click("loginButton"); // stepKey: step6 } } diff --git a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt index 29d822831..3e812cdd0 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt @@ -25,7 +25,7 @@ class ActionGroupWithDataTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ActionGroupWithDataTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ActionGroupWithDataTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ActionGroupWithDataTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,14 +72,14 @@ class ActionGroupWithDataTestCest */ public function ActionGroupWithDataTest(AcceptanceTester $I) { - $I->amOnPage("/someUrl"); - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroupWithData1)"); - $I->amOnPage("/Jane/Dane.html"); - $I->fillField("#foo", "Jane"); - $I->fillField("#bar", "Dane"); - $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); - $I->see("#element .Jane"); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroupWithData1)"); - $I->click("loginButton"); + $I->amOnPage("/someUrl"); // stepKey: step1 + $I->comment("Entering Action Group [actionGroupWithData1] FunctionalActionGroupWithData"); + $I->amOnPage("/Jane/Dane.html"); // stepKey: amOnPage1ActionGroupWithData1 + $I->fillField("#foo", "Jane"); // stepKey: fillField1ActionGroupWithData1 + $I->fillField("#bar", "Dane"); // stepKey: fillField2ActionGroupWithData1 + $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); // stepKey: multi1ActionGroupWithData1 + $I->see("#element .Jane"); // stepKey: see1ActionGroupWithData1 + $I->comment("Exiting Action Group [actionGroupWithData1] FunctionalActionGroupWithData"); + $I->click("loginButton"); // stepKey: step6 } } diff --git a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt index a66759a89..68f95298d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt @@ -29,8 +29,8 @@ class ActionGroupWithDefaultArgumentAndStringSelectorParamCest */ public function ActionGroupWithDefaultArgumentAndStringSelectorParam(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithDefaultArgumentAndStringSelectorParam (actionGroup)"); - $I->see("John", "#element .test1"); - $I->comment("Exiting Action Group actionGroupWithDefaultArgumentAndStringSelectorParam (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); + $I->see("John", "#element .test1"); // stepKey: seeFirstNameActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt index e726a178f..1c211ce4e 100644 --- a/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithMultipleParameterSelectorsFromDefaultArgument.txt @@ -29,8 +29,8 @@ class ActionGroupWithMultipleParameterSelectorsFromDefaultArgumentCest */ public function ActionGroupWithMultipleParameterSelectorsFromDefaultArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithMultipleParameterSelectorsFromArgument (actionGroup)"); - $I->see("Doe", "#John-Doe .test"); - $I->comment("Exiting Action Group actionGroupWithMultipleParameterSelectorsFromArgument (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithMultipleParameterSelectorsFromArgument"); + $I->see("Doe", "#John-Doe .test"); // stepKey: seeLastNameActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithMultipleParameterSelectorsFromArgument"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt index 751206193..11da2ddf6 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoArguments.txt @@ -29,8 +29,8 @@ class ActionGroupWithNoArgumentsCest */ public function ActionGroupWithNoArguments(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithoutArguments (actionGroup)"); - $I->wait(1); - $I->comment("Exiting Action Group actionGroupWithoutArguments (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithoutArguments"); + $I->wait(1); // stepKey: waitForNothingActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithoutArguments"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt index fd5846c4a..955596301 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt @@ -25,7 +25,7 @@ class ActionGroupWithNoDefaultTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ActionGroupWithNoDefaultTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ActionGroupWithNoDefaultTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ActionGroupWithNoDefaultTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,12 +72,12 @@ class ActionGroupWithNoDefaultTestCest */ public function ActionGroupWithNoDefaultTest(AcceptanceTester $I) { - $I->amOnPage("/someUrl"); - $I->comment("Entering Action Group FunctionalActionGroupNoDefault (actionGroupWithDataOverride1)"); - $I->fillField("#foo", "Jane"); - $I->fillField("#bar", "Dane"); - $I->see("#Jane .Dane"); - $I->comment("Exiting Action Group FunctionalActionGroupNoDefault (actionGroupWithDataOverride1)"); - $I->click("loginButton"); + $I->amOnPage("/someUrl"); // stepKey: step1 + $I->comment("Entering Action Group [actionGroupWithDataOverride1] FunctionalActionGroupNoDefault"); + $I->fillField("#foo", "Jane"); // stepKey: fillField1ActionGroupWithDataOverride1 + $I->fillField("#bar", "Dane"); // stepKey: fillField2ActionGroupWithDataOverride1 + $I->see("#Jane .Dane"); // stepKey: see2ActionGroupWithDataOverride1 + $I->comment("Exiting Action Group [actionGroupWithDataOverride1] FunctionalActionGroupNoDefault"); + $I->click("loginButton"); // stepKey: step6 } } diff --git a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt index 989c5af5e..7d32e2e68 100644 --- a/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt +++ b/dev/tests/verification/Resources/ActionGroupWithParameterizedElementWithHyphen.txt @@ -27,8 +27,8 @@ class ActionGroupWithParameterizedElementWithHyphenCest */ public function ActionGroupWithParameterizedElementWithHyphen(AcceptanceTester $I) { - $I->comment("Entering Action Group SectionArgumentWithParameterizedSelector (actionGroup)"); - $keyoneActionGroup = $I->executeJS("#element .full-width"); - $I->comment("Exiting Action Group SectionArgumentWithParameterizedSelector (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] SectionArgumentWithParameterizedSelector"); + $keyoneActionGroup = $I->executeJS("#element .full-width"); // stepKey: keyoneActionGroup + $I->comment("Exiting Action Group [actionGroup] SectionArgumentWithParameterizedSelector"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt index 7df77e742..6b85f8b47 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt @@ -29,8 +29,8 @@ class ActionGroupWithPassedArgumentAndStringSelectorParamCest */ public function ActionGroupWithPassedArgumentAndStringSelectorParam(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithDefaultArgumentAndStringSelectorParam (actionGroup)"); - $I->see("John" . msq("UniquePerson"), "#element .test1"); - $I->comment("Exiting Action Group actionGroupWithDefaultArgumentAndStringSelectorParam (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); + $I->see("John" . msq("UniquePerson"), "#element .test1"); // stepKey: seeFirstNameActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt index 2f58e390c..aba5c5796 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt @@ -25,7 +25,7 @@ class ActionGroupWithPersistedDataCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ActionGroupWithPersistedDataCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ActionGroupWithPersistedDataCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ActionGroupWithPersistedDataCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,7 +72,7 @@ class ActionGroupWithPersistedDataCest */ public function ActionGroupWithPersistedData(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPerson"); + $I->comment("[createPerson] create 'DefaultPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPerson", "test", @@ -79,12 +80,13 @@ class ActionGroupWithPersistedDataCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroupWithPersistedData1)"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test') . "/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test') . ".html"); - $I->fillField("#foo", PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test')); - $I->fillField("#bar", PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test')); - $I->searchAndMultiSelectOption("#foo", [PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'lastname', 'test')]); - $I->see("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createPerson', 'firstname', 'test')); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroupWithPersistedData1)"); + + $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->comment("Exiting Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt index 34c2a0ea1..20a9c5137 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSectionAndDataAsArguments.txt @@ -27,8 +27,8 @@ class ActionGroupWithSectionAndDataAsArgumentsCest */ public function ActionGroupWithSectionAndDataAsArguments(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithSectionAndData (actionGroup)"); - $I->waitForElementVisible("#element .John", 10); - $I->comment("Exiting Action Group actionGroupWithSectionAndData (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithSectionAndData"); + $I->waitForElementVisible("#element .John", 10); // stepKey: arg1ActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithSectionAndData"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt index f4840d88a..52cdeb83d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromDefaultArgument.txt @@ -29,8 +29,8 @@ class ActionGroupWithSimpleDataUsageFromDefaultArgumentCest */ public function ActionGroupWithSimpleDataUsageFromDefaultArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup)"); - $I->see("stringLiteral", "#element .stringLiteral"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithStringUsage"); + $I->see("stringLiteral", "#element .stringLiteral"); // stepKey: see1ActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithStringUsage"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt index 4f67da1aa..9ad3dd560 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSimpleDataUsageFromPassedArgument.txt @@ -29,35 +29,35 @@ class ActionGroupWithSimpleDataUsageFromPassedArgumentCest */ public function ActionGroupWithSimpleDataUsageFromPassedArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup1)"); - $I->see("overrideString", "#element .overrideString"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup1)"); - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup11)"); - $I->see("1", "#element .1"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup11)"); - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup12)"); - $I->see("1.5", "#element .1.5"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup12)"); - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup13)"); - $I->see("true", "#element .true"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup13)"); - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup2)"); - $I->see("simpleData.firstname", "#element .simpleData.firstname"); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup2)"); - $I->comment("Entering Action Group actionGroupWithStringUsage (actionGroup3)"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); - $I->comment("Exiting Action Group actionGroupWithStringUsage (actionGroup3)"); - $I->comment("Entering Action Group actionGroupWithEntityUsage (actionGroup4)"); - $I->see("John", "#element .John"); - $I->comment("Exiting Action Group actionGroupWithEntityUsage (actionGroup4)"); - $I->comment("Entering Action Group actionGroupWithEntityUsage (actionGroup5)"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname', 'test')); - $I->comment("Exiting Action Group actionGroupWithEntityUsage (actionGroup5)"); - $I->comment("Entering Action Group actionGroupWithEntityUsage (actionGroup6)"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[0]', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[0]', 'test')); - $I->comment("Exiting Action Group actionGroupWithEntityUsage (actionGroup6)"); - $I->comment("Entering Action Group actionGroupWithEntityUsage (actionGroup7)"); - $I->see(PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[data_index]', 'test'), "#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('simpleData', 'firstname[data_index]', 'test')); - $I->comment("Exiting Action Group actionGroupWithEntityUsage (actionGroup7)"); + $I->comment("Entering Action Group [actionGroup1] actionGroupWithStringUsage"); + $I->see("overrideString", "#element .overrideString"); // stepKey: see1ActionGroup1 + $I->comment("Exiting Action Group [actionGroup1] actionGroupWithStringUsage"); + $I->comment("Entering Action Group [actionGroup11] actionGroupWithStringUsage"); + $I->see("1", "#element .1"); // stepKey: see1ActionGroup11 + $I->comment("Exiting Action Group [actionGroup11] actionGroupWithStringUsage"); + $I->comment("Entering Action Group [actionGroup12] actionGroupWithStringUsage"); + $I->see("1.5", "#element .1.5"); // stepKey: see1ActionGroup12 + $I->comment("Exiting Action Group [actionGroup12] actionGroupWithStringUsage"); + $I->comment("Entering Action Group [actionGroup13] actionGroupWithStringUsage"); + $I->see("true", "#element .true"); // stepKey: see1ActionGroup13 + $I->comment("Exiting Action Group [actionGroup13] actionGroupWithStringUsage"); + $I->comment("Entering Action Group [actionGroup2] actionGroupWithStringUsage"); + $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->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->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->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->comment("Exiting Action Group [actionGroup7] actionGroupWithEntityUsage"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt index 89979bf97..48fc52ff4 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromDefaultArgument.txt @@ -29,8 +29,8 @@ class ActionGroupWithSingleParameterSelectorFromDefaultArgumentCest */ public function ActionGroupWithSingleParameterSelectorFromDefaultArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithSingleParameterSelectorFromArgument (actionGroup)"); - $I->see("Doe", "#element .John"); - $I->comment("Exiting Action Group actionGroupWithSingleParameterSelectorFromArgument (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithSingleParameterSelectorFromArgument"); + $I->see("Doe", "#element .John"); // stepKey: seeLastNameActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithSingleParameterSelectorFromArgument"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt index b4707ff0c..97c8bca5b 100644 --- a/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt +++ b/dev/tests/verification/Resources/ActionGroupWithSingleParameterSelectorFromPassedArgument.txt @@ -29,8 +29,8 @@ class ActionGroupWithSingleParameterSelectorFromPassedArgumentCest */ public function ActionGroupWithSingleParameterSelectorFromPassedArgument(AcceptanceTester $I) { - $I->comment("Entering Action Group actionGroupWithSingleParameterSelectorFromArgument (actionGroup)"); - $I->see("Doe", "#element .John" . msq("UniquePerson")); - $I->comment("Exiting Action Group actionGroupWithSingleParameterSelectorFromArgument (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] actionGroupWithSingleParameterSelectorFromArgument"); + $I->see("Doe", "#element .John" . msq("UniquePerson")); // stepKey: seeLastNameActionGroup + $I->comment("Exiting Action Group [actionGroup] actionGroupWithSingleParameterSelectorFromArgument"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index 92b54622c..2f23215c2 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -27,8 +27,8 @@ class ActionGroupWithStepKeyReferencesCest */ public function ActionGroupWithStepKeyReferences(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionActionGroupWithStepKeyReferences (actionGroup)"); - $I->amGoingTo("create entity that has the stepKey: createSimpleDataActionGroup"); + $I->comment("Entering Action Group [actionGroup] FunctionActionGroupWithStepKeyReferences"); + $I->comment("[createSimpleDataActionGroup] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createSimpleDataActionGroup", "test", @@ -36,26 +36,29 @@ class ActionGroupWithStepKeyReferencesCest [], null ); - $grabTextDataActionGroup = $I->grabTextFrom(".class"); - $I->fillField(".{$grabTextDataActionGroup}", PersistedObjectHandler::getInstance()->retrieveEntityField('createSimpleDataActionGroup', 'field', 'test')); + + $grabTextDataActionGroup = $I->grabTextFrom(".class"); // stepKey: grabTextDataActionGroup + $I->fillField(".{$grabTextDataActionGroup}", PersistedObjectHandler::getInstance()->retrieveEntityField('createSimpleDataActionGroup', 'field', 'test')); // stepKey: fill1ActionGroup $I->comment("Invocation stepKey will not be appended in non stepKey instances"); - $I->click($action0); - $I->fillField($action1); + $I->click($action0); // stepKey: action0ActionGroup + $I->fillField($action1); // stepKey: action1ActionGroup $I->comment("Invocation stepKey will be appended in non stepKey instances"); - $action3ActionGroup = $I->executeJS($action3ActionGroup); - $action4ActionGroup = $I->magentoCLI($action4ActionGroup, "\"stuffHere\""); - $I->comment($action4ActionGroup); + $action3ActionGroup = $I->executeJS($action3ActionGroup); // stepKey: action3ActionGroup + $action4ActionGroup = $I->magentoCLI($action4ActionGroup, "\"stuffHere\""); $I->comment($action4ActionGroup); + // stepKey: action4ActionGroup $date = new \DateTime(); $date->setTimestamp(strtotime("{$action5}")); $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); $action5ActionGroup = $date->format("H:i:s"); - $action6ActionGroup = $I->formatMoney($action6ActionGroup); - $I->amGoingTo("delete entity that has the createDataKey: {$action7ActionGroupActionGroup}"); + // stepKey: action5ActionGroup + $action6ActionGroup = $I->formatMoney($action6ActionGroup); // stepKey: action6ActionGroup + $I->comment("[action7ActionGroup] delete entity '{$action7ActionGroupActionGroup}'"); PersistedObjectHandler::getInstance()->deleteEntity( "{$action7ActionGroupActionGroup}", "test" ); - $I->amGoingTo("get entity that has the stepKey: action8ActionGroup"); + + $I->comment("[action8ActionGroup] get '{$action8}' entity"); PersistedObjectHandler::getInstance()->getEntity( "action8ActionGroup", "test", @@ -63,14 +66,16 @@ class ActionGroupWithStepKeyReferencesCest [], null ); - $I->amGoingTo("update entity that has the createdDataKey: 1"); + + $I->comment("[action9ActionGroup] update '1' entity to '{$action9}'"); PersistedObjectHandler::getInstance()->updateEntity( "1", "test", "{$action9}", [] ); - $I->amGoingTo("create entity that has the stepKey: action10ActionGroup"); + + $I->comment("[action10ActionGroup] create '{$action10}' entity"); PersistedObjectHandler::getInstance()->createEntity( "action10ActionGroup", "test", @@ -78,12 +83,13 @@ class ActionGroupWithStepKeyReferencesCest [], null ); - $action11ActionGroup = $I->grabAttributeFrom($action11ActionGroup, "someInput"); - $action12ActionGroup = $I->grabCookie($action12ActionGroup, ['domain' => 'www.google.com']); - $action13ActionGroup = $I->grabFromCurrentUrl($action13ActionGroup); - $action14ActionGroup = $I->grabMultiple($action14ActionGroup); - $action15ActionGroup = $I->grabTextFrom($action15ActionGroup); - $action16ActionGroup = $I->grabValueFrom($action16ActionGroup); - $I->comment("Exiting Action Group FunctionActionGroupWithStepKeyReferences (actionGroup)"); + + $action11ActionGroup = $I->grabAttributeFrom($action11ActionGroup, "someInput"); // stepKey: action11ActionGroup + $action12ActionGroup = $I->grabCookie($action12ActionGroup, ['domain' => 'www.google.com']); // stepKey: action12ActionGroup + $action13ActionGroup = $I->grabFromCurrentUrl($action13ActionGroup); // stepKey: action13ActionGroup + $action14ActionGroup = $I->grabMultiple($action14ActionGroup); // stepKey: action14ActionGroup + $action15ActionGroup = $I->grabTextFrom($action15ActionGroup); // stepKey: action15ActionGroup + $action16ActionGroup = $I->grabValueFrom($action16ActionGroup); // stepKey: action16ActionGroup + $I->comment("Exiting Action Group [actionGroup] FunctionActionGroupWithStepKeyReferences"); } } diff --git a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt index 463e5b307..fffaebbfd 100644 --- a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt @@ -25,7 +25,7 @@ class ActionGroupWithTopLevelPersistedDataCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ActionGroupWithTopLevelPersistedDataCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ActionGroupWithTopLevelPersistedDataCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ActionGroupWithTopLevelPersistedDataCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,12 +72,12 @@ class ActionGroupWithTopLevelPersistedDataCest */ public function ActionGroupWithTopLevelPersistedData(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroupWithPersistedData1)"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test') . "/" . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test') . ".html"); - $I->fillField("#foo", PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test')); - $I->fillField("#bar", PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test')); - $I->searchAndMultiSelectOption("#foo", [PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'lastname', 'test')]); - $I->see("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createPersonParam', 'firstname', 'test')); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroupWithPersistedData1)"); + $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->comment("Exiting Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); } } diff --git a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt index d1621fd73..4ccc2d169 100644 --- a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt +++ b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt @@ -25,7 +25,7 @@ class ArgumentWithSameNameAsElementCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class ArgumentWithSameNameAsElementCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class ArgumentWithSameNameAsElementCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class ArgumentWithSameNameAsElementCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,9 +72,9 @@ class ArgumentWithSameNameAsElementCest */ public function ArgumentWithSameNameAsElement(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupWithTrickyArgument (actionGroup1)"); - $I->seeElement("#element"); - $I->seeElement("#element .John"); - $I->comment("Exiting Action Group FunctionalActionGroupWithTrickyArgument (actionGroup1)"); + $I->comment("Entering Action Group [actionGroup1] FunctionalActionGroupWithTrickyArgument"); + $I->seeElement("#element"); // stepKey: see1ActionGroup1 + $I->seeElement("#element .John"); // stepKey: see2ActionGroup1 + $I->comment("Exiting Action Group [actionGroup1] FunctionalActionGroupWithTrickyArgument"); } } diff --git a/dev/tests/verification/Resources/AssertTest.txt b/dev/tests/verification/Resources/AssertTest.txt index adc764975..15388667a 100644 --- a/dev/tests/verification/Resources/AssertTest.txt +++ b/dev/tests/verification/Resources/AssertTest.txt @@ -24,7 +24,7 @@ class AssertTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createData1"); + $I->comment("[createData1] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData1", "hook", @@ -32,6 +32,7 @@ class AssertTestCest [], null ); + } /** @@ -43,7 +44,7 @@ class AssertTestCest */ public function AssertTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createData2"); + $I->comment("[createData2] create 'UniquePerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData2", "test", @@ -51,112 +52,113 @@ class AssertTestCest [], null ); - $grabTextFrom1 = $I->grabTextFrom(".copyright>span"); - $I->assertArrayIsSorted(["1", "2", "3", "4", "5"], "asc"); + + $grabTextFrom1 = $I->grabTextFrom(".copyright>span"); // stepKey: grabTextFrom1 + $I->assertArrayIsSorted(["1", "2", "3", "4", "5"], "asc"); // stepKey: assertSorted1 $I->comment("asserts without variable replacement"); - $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); - $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); - $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); - $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); - $I->assertCount(2, ['a', 'b'], "pass"); - $I->assertEmpty([], "pass"); - $I->assertEquals($text, "Copyright © 2013-2017 Magento, Inc. All rights reserved.", "pass"); - $I->assertEquals("Copyright © 2013-2017 Magento, Inc. All rights reserved.", $text, "pass"); - $I->assertFalse(false, "pass"); - $I->assertFileNotExists("/out.txt", "pass"); - $I->assertFileNotExists($text, "pass"); - $I->assertGreaterOrEquals(2, 5, "pass"); - $I->assertGreaterThan(2, 5, "pass"); - $I->assertGreaterThanOrEqual(2, 5, "pass"); - $I->assertInternalType("string", "xyz", "pass"); - $I->assertInternalType("int", 21, "pass"); - $I->assertInternalType("string", $text, "pass"); - $I->assertLessOrEquals(5, 2, "pass"); - $I->assertLessThan(5, 2, "pass"); - $I->assertLessThanOrEqual(5, 2, "pass"); - $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); - $I->assertNotContains("bc", $text, "pass"); - $I->assertNotEmpty([1, 2], "pass"); - $I->assertNotEmpty($text, "pass"); - $I->assertNotEquals(2, 5, "pass", 0); - $I->assertNotNull("abc", "pass"); - $I->assertNotNull($text, "pass"); - $I->assertNotRegExp("/foo/", "bar", "pass"); - $I->assertNotSame("log", "tag", "pass"); - $I->assertRegExp("/foo/", "foo", "pass"); - $I->assertSame("bar", "bar", "pass"); - $I->assertStringStartsNotWith("a", "banana", "pass"); - $I->assertStringStartsWith("a", "apple", "pass"); - $I->assertTrue(true, "pass"); + $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKey + $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKey + $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubset + $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertContains + $I->assertCount(2, ['a', 'b'], "pass"); // stepKey: assertCount + $I->assertEmpty([], "pass"); // stepKey: assertEmpty + $I->assertEquals($text, "Copyright © 2013-2017 Magento, Inc. All rights reserved.", "pass"); // stepKey: assertEquals1 + $I->assertEquals("Copyright © 2013-2017 Magento, Inc. All rights reserved.", $text, "pass"); // stepKey: assertEquals2 + $I->assertFalse(false, "pass"); // stepKey: assertFalse1 + $I->assertFileNotExists("/out.txt", "pass"); // stepKey: assertFileNotExists1 + $I->assertFileNotExists($text, "pass"); // stepKey: assertFileNotExists2 + $I->assertGreaterOrEquals(2, 5, "pass"); // stepKey: assertGreaterOrEquals + $I->assertGreaterThan(2, 5, "pass"); // stepKey: assertGreaterthan + $I->assertGreaterThanOrEqual(2, 5, "pass"); // stepKey: assertGreaterThanOrEqual + $I->assertInternalType("string", "xyz", "pass"); // stepKey: assertInternalType1 + $I->assertInternalType("int", 21, "pass"); // stepKey: assertInternalType2 + $I->assertInternalType("string", $text, "pass"); // stepKey: assertInternalType3 + $I->assertLessOrEquals(5, 2, "pass"); // stepKey: assertLessOrEquals + $I->assertLessThan(5, 2, "pass"); // stepKey: assertLessThan + $I->assertLessThanOrEqual(5, 2, "pass"); // stepKey: assertLessThanOrEquals + $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertNotContains1 + $I->assertNotContains("bc", $text, "pass"); // stepKey: assertNotContains2 + $I->assertNotEmpty([1, 2], "pass"); // stepKey: assertNotEmpty1 + $I->assertNotEmpty($text, "pass"); // stepKey: assertNotEmpty2 + $I->assertNotEquals(2, 5, "pass", 0); // stepKey: assertNotEquals + $I->assertNotNull("abc", "pass"); // stepKey: assertNotNull1 + $I->assertNotNull($text, "pass"); // stepKey: assertNotNull2 + $I->assertNotRegExp("/foo/", "bar", "pass"); // stepKey: assertNotRegExp + $I->assertNotSame("log", "tag", "pass"); // stepKey: assertNotSame + $I->assertRegExp("/foo/", "foo", "pass"); // stepKey: assertRegExp + $I->assertSame("bar", "bar", "pass"); // stepKey: assertSame + $I->assertStringStartsNotWith("a", "banana", "pass"); // stepKey: assertStringStartsNotWith + $I->assertStringStartsWith("a", "apple", "pass"); // stepKey: assertStringStartsWith + $I->assertTrue(true, "pass"); // stepKey: assertTrue $I->comment("asserts backward compatible"); - $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); - $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); - $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); - $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); - $I->assertCount(2, ['a', 'b'], "pass"); - $I->assertEmpty([], "pass"); - $I->assertEquals($text, "Copyright © 2013-2017 Magento, Inc. All rights reserved.", "pass"); - $I->assertEquals("Copyright © 2013-2017 Magento, Inc. All rights reserved.", $text, "pass"); - $I->assertFalse(false, "pass"); - $I->assertFileNotExists("/out.txt", "pass"); - $I->assertFileNotExists($text, "pass"); - $I->assertGreaterOrEquals(2, 5, "pass"); - $I->assertGreaterThan(2, 5, "pass"); - $I->assertGreaterThanOrEqual(2, 5, "pass"); - $I->assertInternalType("string", "xyz", "pass"); - $I->assertInternalType("int", 21, "pass"); - $I->assertInternalType("string", $text, "pass"); - $I->assertLessOrEquals(5, 2, "pass"); - $I->assertLessThan(5, 2, "pass"); - $I->assertLessThanOrEqual(5, 2, "pass"); - $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); - $I->assertNotContains("bc", $text, "pass"); - $I->assertNotEmpty([1, 2], "pass"); - $I->assertNotEmpty($text, "pass"); - $I->assertNotEquals(2, 5, "pass", 0); - $I->assertNotNull("abc", "pass"); - $I->assertNotNull($text, "pass"); - $I->assertNotRegExp("/foo/", "bar", "pass"); - $I->assertNotSame("log", "tag", "pass"); - $I->assertRegExp("/foo/", "foo", "pass"); - $I->assertSame("bar", "bar", "pass"); - $I->assertStringStartsNotWith("a", "banana", "pass"); - $I->assertStringStartsWith("a", "apple", "pass"); - $I->assertTrue(true, "pass"); - $I->assertElementContainsAttribute("#username", "class", "admin__control-text"); - $I->assertInstanceOf(User::class, $text, "pass"); - $I->assertNotInstanceOf(User::class, 21, "pass"); - $I->assertFileExists($text, "pass"); - $I->assertIsEmpty($text, "pass"); - $I->assertNull($text, "pass"); - $I->expectException(new MyException('exception msg'), function() {$this->doSomethingBad();}); + $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKeyBackwardCompatible + $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKeyBackwardCompatible + $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubsetBackwardCompatible + $I->assertContains("ab", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertContainsBackwardCompatible + $I->assertCount(2, ['a', 'b'], "pass"); // stepKey: assertCountBackwardCompatible + $I->assertEmpty([], "pass"); // stepKey: assertEmptyBackwardCompatible + $I->assertEquals($text, "Copyright © 2013-2017 Magento, Inc. All rights reserved.", "pass"); // stepKey: assertEquals1BackwardCompatible + $I->assertEquals("Copyright © 2013-2017 Magento, Inc. All rights reserved.", $text, "pass"); // stepKey: assertEquals2BackwardCompatible + $I->assertFalse(false, "pass"); // stepKey: assertFalse1BackwardCompatible + $I->assertFileNotExists("/out.txt", "pass"); // stepKey: assertFileNotExists1BackwardCompatible + $I->assertFileNotExists($text, "pass"); // stepKey: assertFileNotExists2BackwardCompatible + $I->assertGreaterOrEquals(2, 5, "pass"); // stepKey: assertGreaterOrEqualsBackwardCompatible + $I->assertGreaterThan(2, 5, "pass"); // stepKey: assertGreaterThanBackwardCompatible + $I->assertGreaterThanOrEqual(2, 5, "pass"); // stepKey: assertGreaterThanOrEqualBackwardCompatible + $I->assertInternalType("string", "xyz", "pass"); // stepKey: assertInternalType1BackwardCompatible + $I->assertInternalType("int", 21, "pass"); // stepKey: assertInternalType2BackwardCompatible + $I->assertInternalType("string", $text, "pass"); // stepKey: assertInternalType3BackwardCompatible + $I->assertLessOrEquals(5, 2, "pass"); // stepKey: assertLessOrEqualBackwardCompatibles + $I->assertLessThan(5, 2, "pass"); // stepKey: assertLessThanBackwardCompatible + $I->assertLessThanOrEqual(5, 2, "pass"); // stepKey: assertLessThanOrEqualBackwardCompatible + $I->assertNotContains("bc", ['item1' => 'a', 'item2' => 'ab'], "pass"); // stepKey: assertNotContains1BackwardCompatible + $I->assertNotContains("bc", $text, "pass"); // stepKey: assertNotContains2BackwardCompatible + $I->assertNotEmpty([1, 2], "pass"); // stepKey: assertNotEmpty1BackwardCompatible + $I->assertNotEmpty($text, "pass"); // stepKey: assertNotEmpty2BackwardCompatible + $I->assertNotEquals(2, 5, "pass", 0); // stepKey: assertNotEqualsBackwardCompatible + $I->assertNotNull("abc", "pass"); // stepKey: assertNotNull1BackwardCompatible + $I->assertNotNull($text, "pass"); // stepKey: assertNotNull2BackwardCompatible + $I->assertNotRegExp("/foo/", "bar", "pass"); // stepKey: assertNotRegExpBackwardCompatible + $I->assertNotSame("log", "tag", "pass"); // stepKey: assertNotSameBackwardCompatible + $I->assertRegExp("/foo/", "foo", "pass"); // stepKey: assertRegExpBackwardCompatible + $I->assertSame("bar", "bar", "pass"); // stepKey: assertSameBackwardCompatible + $I->assertStringStartsNotWith("a", "banana", "pass"); // stepKey: assertStringStartsNotWithBackwardCompatible + $I->assertStringStartsWith("a", "apple", "pass"); // stepKey: assertStringStartsWithBackwardCompatible + $I->assertTrue(true, "pass"); // stepKey: assertTrueBackwardCompatible + $I->assertElementContainsAttribute("#username", "class", "admin__control-text"); // stepKey: assertElementContainsAttributeBackwardCompatible + $I->assertInstanceOf(User::class, $text, "pass"); // stepKey: assertInstanceOfBackwardCompatible + $I->assertNotInstanceOf(User::class, 21, "pass"); // stepKey: assertNotInstanceOfBackwardCompatible + $I->assertFileExists($text, "pass"); // stepKey: assertFileExistsBackwardCompatible + $I->assertIsEmpty($text, "pass"); // stepKey: assertIsEmptyBackwardCompatible + $I->assertNull($text, "pass"); // stepKey: assertNullBackwardCompatible + $I->expectException(new MyException('exception msg'), function() {$this->doSomethingBad();}); // stepKey: expectExceptionBackwardCompatible $I->comment("string type that use created data"); - $I->assertStringStartsWith("D", PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test') . ", " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test'), "fail"); - $I->assertStringStartsNotWith("W", PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test') . ", " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test'), "pass"); - $I->assertEquals(PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), "pass"); + $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->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"); - $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"); - $I->assertArrayHasKey("lastname", ['lastname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test'), 'firstname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test')], "pass"); - $I->assertArrayHasKey("lastname", ['lastname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test'), 'firstname' => PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test')], "pass"); - $I->assertInstanceOf(User::class, $text, "pass"); - $I->assertNotInstanceOf(User::class, 21, "pass"); - $I->assertFileExists($text, "pass"); - $I->assertFileExists("AssertCest.php", "pass"); - $I->assertIsEmpty($text, "pass"); - $I->assertNull($text, "pass"); - $I->expectException(new MyException('exception msg'), function() {$this->doSomethingBad();}); - $I->fail("fail"); - $I->fail(PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test') . " " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'lastname', 'test')); - $I->fail(PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test') . " " . PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'lastname', 'test')); - $I->assertElementContainsAttribute("#username", "class", "admin__control-text"); - $I->assertElementContainsAttribute("#username", "name", "login[username]"); - $I->assertElementContainsAttribute("#username", "autofocus", "true"); - $I->assertElementContainsAttribute("#username", "data-validate", "{required:true}"); - $I->assertElementContainsAttribute(".admin__menu-overlay", "style", "display: none;"); - $I->assertElementContainsAttribute(".admin__menu-overlay", "border", "0"); - $I->assertElementContainsAttribute("#username", "value", PersistedObjectHandler::getInstance()->retrieveEntityField('createData2', 'firstname', 'test')); - $I->assertElementContainsAttribute("#username", "value", PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'test')); - $I->assertEquals("John", "Doe", "pass"); + $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->assertInstanceOf(User::class, $text, "pass"); // stepKey: assertInstanceOf + $I->assertNotInstanceOf(User::class, 21, "pass"); // stepKey: assertNotInstanceOf + $I->assertFileExists($text, "pass"); // stepKey: assertFileExists2 + $I->assertFileExists("AssertCest.php", "pass"); // stepKey: assertFileExists3 + $I->assertIsEmpty($text, "pass"); // stepKey: assertIsEmpty + $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->assertElementContainsAttribute("#username", "class", "admin__control-text"); // stepKey: assertElementContainsAttribute1 + $I->assertElementContainsAttribute("#username", "name", "login[username]"); // stepKey: assertElementContainsAttribute2 + $I->assertElementContainsAttribute("#username", "autofocus", "true"); // stepKey: assertElementContainsAttribute3 + $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->assertEquals("John", "Doe", "pass"); // stepKey: assertEqualsEntity } } diff --git a/dev/tests/verification/Resources/BasicActionGroupTest.txt b/dev/tests/verification/Resources/BasicActionGroupTest.txt index d62c2919d..17e5e2bdf 100644 --- a/dev/tests/verification/Resources/BasicActionGroupTest.txt +++ b/dev/tests/verification/Resources/BasicActionGroupTest.txt @@ -25,7 +25,7 @@ class BasicActionGroupTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class BasicActionGroupTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -50,11 +51,11 @@ class BasicActionGroupTestCest */ public function BasicActionGroupTest(AcceptanceTester $I) { - $I->amOnPage("/someUrl"); - $I->comment("Entering Action Group FunctionalActionGroup (actionGroup1)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (actionGroup1)"); - $I->click("loginButton"); + $I->amOnPage("/someUrl"); // stepKey: step1 + $I->comment("Entering Action Group [actionGroup1] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1ActionGroup1 + $I->fillField("#bar", "myData2"); // stepKey: fillField2ActionGroup1 + $I->comment("Exiting Action Group [actionGroup1] FunctionalActionGroup"); + $I->click("loginButton"); // stepKey: step6 } } diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index fd5f0f165..b3ab7ea9c 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -26,7 +26,7 @@ class BasicFunctionalTestCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class BasicFunctionalTestCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class BasicFunctionalTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -61,110 +61,114 @@ class BasicFunctionalTestCest $I->comment(""); $I->comment(""); $I->comment("seeComment"); - $someVarDefinition = $I->grabValueFrom(); - $I->acceptPopup(); - $I->amOnPage("/test/url"); - $I->appendField(".functionalTestSelector"); - $I->attachFile(".functionalTestSelector", "testFileAttachment"); - $I->cancelPopup(); - $I->checkOption(".functionalTestSelector"); - $I->click(".functionalTestSelector"); - $I->clickWithLeftButton(".functionalTestSelector"); - $I->clickWithRightButton(".functionalTestSelector"); - $I->clickWithLeftButton("#element#element .200", 200, 300); - $I->clickWithRightButton("#element .4123#element", 200, 300); - $I->closeTab(); - $I->conditionalClick(".functionalTestSelector", ".functionalDependentTestSelector", true); - $I->amGoingTo("delete entity that has the createDataKey: createKey1"); + $someVarDefinition = $I->grabValueFrom(); // stepKey: someVarDefinition + $I->acceptPopup(); // stepKey: acceptPopupKey1 + $I->amOnPage("/test/url"); // stepKey: amOnPageKey1 + $I->appendField(".functionalTestSelector"); // stepKey: appendFieldKey1 + $I->attachFile(".functionalTestSelector", "testFileAttachment"); // stepKey: attachFileKey1 + $I->cancelPopup(); // stepKey: cancelPopupKey1 + $I->checkOption(".functionalTestSelector"); // stepKey: checkOptionKey1 + $I->click(".functionalTestSelector"); // stepKey: clickKey1 + $I->clickWithLeftButton(".functionalTestSelector"); // stepKey: clickWithLeftButtonKey1 + $I->clickWithRightButton(".functionalTestSelector"); // stepKey: clickWithRightButtonKey1 + $I->clickWithLeftButton("#element#element .200", 200, 300); // stepKey: clickWithLeftButtonKeyXY1 + $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->dontSee("someInput", ".functionalTestSelector"); - $I->dontSeeCheckboxIsChecked(".functionalTestSelector"); - $I->dontSeeCookie("someInput"); - $I->dontSeeCurrentUrlEquals("/functionalUrl"); - $I->dontSeeCurrentUrlMatches("/[0-9]+/"); - $I->dontSeeElement(".functionalTestSelector"); - $I->dontSeeElementInDOM(".functionalTestSelector"); - $I->dontSeeInCurrentUrl("/functionalUrl"); - $I->dontSeeInField(".functionalTestSelector"); - $I->dontSeeInPageSource("someInput"); - $I->dontSeeInSource(""); - $I->dontSeeInTitle("someInput"); - $I->dontSeeLink("someInput", "/functionalUrl"); - $I->dontSeeOptionIsSelected(".functionalTestSelector", "someInput"); - $I->doubleClick(".functionalTestSelector"); - $I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2"); - $I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2", 100, 900); - $executeJSKey1 = $I->executeJS("someJSFunction"); - $I->fillField(".functionalTestSelector", "someInput"); - $I->fillField(".functionalTestSelector", "0"); + + $I->dontSee("someInput", ".functionalTestSelector"); // stepKey: dontSeeKey1 + $I->dontSeeCheckboxIsChecked(".functionalTestSelector"); // stepKey: dontSeeCheckboxIsCheckedKey1 + $I->dontSeeCookie("someInput"); // stepKey: dontSeeCookieKey1 + $I->dontSeeCurrentUrlEquals("/functionalUrl"); // stepKey: dontSeeCurrentUrlEqualsKey1 + $I->dontSeeCurrentUrlMatches("/[0-9]+/"); // stepKey: dontSeeCurrentUrlMatchesKey1 + $I->dontSeeElement(".functionalTestSelector"); // stepKey: dontSeeElementKey1 + $I->dontSeeElementInDOM(".functionalTestSelector"); // stepKey: dontSeeElementInDOMKey1 + $I->dontSeeInCurrentUrl("/functionalUrl"); // stepKey: dontSeeInCurrentUrlKey1 + $I->dontSeeInField(".functionalTestSelector"); // stepKey: dontSeeInFieldKey1 + $I->dontSeeInPageSource("someInput"); // stepKey: dontSeeInPageSourceKey1 + $I->dontSeeInSource(""); // stepKey: dontSeeInSourceKey1 + $I->dontSeeInTitle("someInput"); // stepKey: dontSeeInTitleKey1 + $I->dontSeeLink("someInput", "/functionalUrl"); // stepKey: dontSeeLinkKey1 + $I->dontSeeOptionIsSelected(".functionalTestSelector", "someInput"); // stepKey: dontSeeOptionIsSelectedKey1 + $I->doubleClick(".functionalTestSelector"); // stepKey: doubleClickKey1 + $I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2"); // stepKey: dragAndDropKey1 + $I->dragAndDrop(".functionalTestSelector", ".functionalTestSelector2", 100, 900); // stepKey: dragAndDropKey2 + $executeJSKey1 = $I->executeJS("someJSFunction"); // stepKey: executeJSKey1 + $I->fillField(".functionalTestSelector", "someInput"); // stepKey: fillFieldKey1 + $I->fillField(".functionalTestSelector", "0"); // stepKey: fillFieldKey2 $date = new \DateTime(); $date->setTimestamp(strtotime("Now")); $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); $generateDateKey = $date->format("H:i:s"); + // stepKey: generateDateKey $date = new \DateTime(); $date->setTimestamp(strtotime("Now")); $date->setTimezone(new \DateTimeZone("UTC")); $generateDateKey2 = $date->format("H:i:s"); - $grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput"); - $grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']); - $grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl"); - $grabMultipleKey1 = $I->grabMultiple(".functionalTestSelector"); - $grabTextFromKey1 = $I->grabTextFrom(".functionalTestSelector"); - $grabValueFromKey1 = $I->grabValueFrom(".functionalTestSelector"); - $magentoCli1 = $I->magentoCLI("maintenance:enable", "\"stuffHere\""); - $I->comment($magentoCli1); - $I->makeScreenshot("screenShotInput"); - $I->maximizeWindow(); - $I->moveBack(); - $I->moveForward(); - $I->moveMouseOver(".functionalTestSelector"); - $I->openNewTab(); - $I->pauseExecution(); - $I->performOn("#selector", function(\WebDriverElement $el) {return $el->isDisplayed();}, 10); - $I->pressKey("#page", "a"); - $I->pressKey("#page", ['ctrl', 'a'],'new'); - $I->pressKey("#page", ['shift', '111'],'1','x'); - $I->pressKey("#page", ['ctrl', 'a'],\Facebook\WebDriver\WebDriverKeys::DELETE); - $I->reloadPage(); - $I->resetCookie("cookieInput"); - $I->resizeWindow(0, 0); - $I->scrollTo(".functionalTestSelector"); - $I->see("someInput", ".functionalTestSelector"); - $I->seeCheckboxIsChecked(".functionalTestSelector"); - $I->seeCookie("someInput"); - $I->seeCurrentUrlEquals("/functionalUrl"); - $I->seeCurrentUrlMatches("/[0-9]+/"); - $I->seeElement(".functionalTestSelector"); - $I->seeElementInDOM(".functionalTestSelector"); - $I->seeInCurrentUrl("/functionalUrl"); - $I->seeInField(".functionalTestSelector", "someInput"); - $I->seeInPageSource(""); - $I->seeInPopup("someInput"); - $I->seeInSource(""); - $I->seeInTitle("someInput"); - $I->seeLink("someInput", "/functionalUrl"); - $I->seeNumberOfElements(".functionalTestSelector"); - $I->seeOptionIsSelected(".functionalTestSelector", "someInput"); - $I->selectOption(".functionalTestSelector"); - $I->selectMultipleOptions(".filter", ".option", ['opt1', 'opt2']); - $I->setCookie("someInput", "someCookieValue"); - $I->switchToIFrame("someInput"); - $I->switchToNextTab(); - $I->switchToPreviousTab(); - $I->switchToWindow(); - $I->typeInPopup("someInput"); - $I->uncheckOption(".functionalTestSelector"); - $I->unselectOption(".functionalTestSelector", "someInput"); - $I->wait(30); - $I->waitForElement(".functionalTestSelector", 30); - $I->waitForElementNotVisible(".functionalTestSelector", 30); - $I->waitForElementVisible(".functionalTestSelector", 30); - $I->waitForElementChange("#selector", function(\WebDriverElement $el) {return $el->isDisplayed();}, 10); - $I->waitForJS("someJsFunction", 30); - $I->waitForText("someInput", 30, ".functionalTestSelector"); + // stepKey: generateDateKey2 + $grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput"); // stepKey: grabAttributeFromKey1 + $grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']); // stepKey: grabCookieKey1 + $grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl"); // stepKey: grabFromCurrentUrlKey1 + $grabMultipleKey1 = $I->grabMultiple(".functionalTestSelector"); // stepKey: grabMultipleKey1 + $grabTextFromKey1 = $I->grabTextFrom(".functionalTestSelector"); // stepKey: grabTextFromKey1 + $grabValueFromKey1 = $I->grabValueFrom(".functionalTestSelector"); // stepKey: grabValueFromKey1 + $magentoCli1 = $I->magentoCLI("maintenance:enable", "\"stuffHere\""); $I->comment($magentoCli1); + // stepKey: magentoCli1 + $I->makeScreenshot("screenShotInput"); // stepKey: makeScreenshotKey1 + $I->maximizeWindow(); // stepKey: maximizeWindowKey1 + $I->moveBack(); // stepKey: moveBackKey1 + $I->moveForward(); // stepKey: moveForwardKey1 + $I->moveMouseOver(".functionalTestSelector"); // stepKey: moveMouseOverKey1 + $I->openNewTab(); // stepKey: openNewTabKey1 + $I->pauseExecution(); // stepKey: pauseExecutionKey1 + $I->performOn("#selector", function(\WebDriverElement $el) {return $el->isDisplayed();}, 10); // stepKey: performOnKey1 + $I->pressKey("#page", "a"); // stepKey: pressKey1 + $I->pressKey("#page", ['ctrl', 'a'],'new'); // stepKey: pressKey2 + $I->pressKey("#page", ['shift', '111'],'1','x'); // stepKey: pressKey3 + $I->pressKey("#page", ['ctrl', 'a'],\Facebook\WebDriver\WebDriverKeys::DELETE); // stepKey: pressKey4 + $I->reloadPage(); // stepKey: reloadPageKey1 + $I->resetCookie("cookieInput"); // stepKey: resetCookieKey1 + $I->resizeWindow(0, 0); // stepKey: resizeWindowKey1 + $I->scrollTo(".functionalTestSelector"); // stepKey: scrollToKey1 + $I->see("someInput", ".functionalTestSelector"); // stepKey: seeKey1 + $I->seeCheckboxIsChecked(".functionalTestSelector"); // stepKey: seeCheckboxIsCheckedKey1 + $I->seeCookie("someInput"); // stepKey: seeCookieKey1 + $I->seeCurrentUrlEquals("/functionalUrl"); // stepKey: seeCurrentUrlEqualsKey1 + $I->seeCurrentUrlMatches("/[0-9]+/"); // stepKey: seeCurrentUrlMatchesKey1 + $I->seeElement(".functionalTestSelector"); // stepKey: seeElementKey1 + $I->seeElementInDOM(".functionalTestSelector"); // stepKey: seeElementInDOMKey1 + $I->seeInCurrentUrl("/functionalUrl"); // stepKey: seeInCurrentUrlKey1 + $I->seeInField(".functionalTestSelector", "someInput"); // stepKey: seeInFieldKey1 + $I->seeInPageSource(""); // stepKey: seeInPageSourceKey1 + $I->seeInPopup("someInput"); // stepKey: seeInPopupKey1 + $I->seeInSource(""); // stepKey: seeInSourceKey1 + $I->seeInTitle("someInput"); // stepKey: seeInTitleKey1 + $I->seeLink("someInput", "/functionalUrl"); // stepKey: seeLinkKey1 + $I->seeNumberOfElements(".functionalTestSelector"); // stepKey: seeNumberOfElementsKey1 + $I->seeOptionIsSelected(".functionalTestSelector", "someInput"); // stepKey: seeOptionIsSelectedKey1 + $I->selectOption(".functionalTestSelector"); // stepKey: selectOptionKey1 + $I->selectMultipleOptions(".filter", ".option", ['opt1', 'opt2']); // stepKey: selectMultipleOpts1 + $I->setCookie("someInput", "someCookieValue"); // stepKey: setCookieKey1 + $I->switchToIFrame("someInput"); // stepKey: switchToIFrameKey1 + $I->switchToNextTab(); // stepKey: switchToNextTabKey1 + $I->switchToPreviousTab(); // stepKey: switchToPreviousTabKey1 + $I->switchToWindow(); // stepKey: switchToWindowKey1 + $I->typeInPopup("someInput"); // stepKey: typeInPopupKey1 + $I->uncheckOption(".functionalTestSelector"); // stepKey: uncheckOptionKey1 + $I->unselectOption(".functionalTestSelector", "someInput"); // stepKey: unselectOptionKey1 + $I->wait(30); // stepKey: waitKey1 + $I->waitForElement(".functionalTestSelector", 30); // stepKey: waitForElementKey1 + $I->waitForElementNotVisible(".functionalTestSelector", 30); // stepKey: waitForElementNotVisibleKey1 + $I->waitForElementVisible(".functionalTestSelector", 30); // stepKey: waitForElementVisibleKey1 + $I->waitForElementChange("#selector", function(\WebDriverElement $el) {return $el->isDisplayed();}, 10); // stepKey: waitForElementChangeKey1 + $I->waitForJS("someJsFunction", 30); // stepKey: waitForJSKey1 + $I->waitForText("someInput", 30, ".functionalTestSelector"); // stepKey: waitForText1 } } diff --git a/dev/tests/verification/Resources/BasicMergeTest.txt b/dev/tests/verification/Resources/BasicMergeTest.txt index 2f66f2ce4..8b311dac2 100644 --- a/dev/tests/verification/Resources/BasicMergeTest.txt +++ b/dev/tests/verification/Resources/BasicMergeTest.txt @@ -27,8 +27,8 @@ class BasicMergeTestCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); - $I->see("#before2"); + $I->amOnPage("/beforeUrl"); // stepKey: before1 + $I->see("#before2"); // stepKey: before2 } /** @@ -37,7 +37,7 @@ class BasicMergeTestCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl1"); + $I->amOnPage("/afterUrl1"); // stepKey: after1 } /** @@ -46,7 +46,7 @@ class BasicMergeTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -60,20 +60,20 @@ class BasicMergeTestCest */ public function BasicMergeTest(AcceptanceTester $I) { - $I->amOnPage("/step1"); - $I->click("#step2"); - $I->fillField("#username", "step3"); - $I->click("#step4"); - $I->fillField("#password", "step5"); - $I->click("#step6Merged"); - $I->click("#element .Jane .step7Merge"); - $I->comment("Entering Action Group FunctionalActionGroupWithData (step8Merge)"); - $I->amOnPage("/Jane/Dane.html"); - $I->fillField("#foo", "Jane"); - $I->fillField("#bar", "Dane"); - $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); - $I->see("#element .Jane"); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (step8Merge)"); - $I->click("#step10MergedInResult"); + $I->amOnPage("/step1"); // stepKey: step1 + $I->click("#step2"); // stepKey: step2 + $I->fillField("#username", "step3"); // stepKey: step3 + $I->click("#step4"); // stepKey: step4 + $I->fillField("#password", "step5"); // stepKey: step5 + $I->click("#step6Merged"); // stepKey: step6Merge + $I->click("#element .Jane .step7Merge"); // stepKey: step7Merge + $I->comment("Entering Action Group [step8Merge] FunctionalActionGroupWithData"); + $I->amOnPage("/Jane/Dane.html"); // stepKey: amOnPage1Step8Merge + $I->fillField("#foo", "Jane"); // stepKey: fillField1Step8Merge + $I->fillField("#bar", "Dane"); // stepKey: fillField2Step8Merge + $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); // stepKey: multi1Step8Merge + $I->see("#element .Jane"); // stepKey: see1Step8Merge + $I->comment("Exiting Action Group [step8Merge] FunctionalActionGroupWithData"); + $I->click("#step10MergedInResult"); // stepKey: step10 } } diff --git a/dev/tests/verification/Resources/CharacterReplacementTest.txt b/dev/tests/verification/Resources/CharacterReplacementTest.txt index c1fddf69b..94459d3b1 100644 --- a/dev/tests/verification/Resources/CharacterReplacementTest.txt +++ b/dev/tests/verification/Resources/CharacterReplacementTest.txt @@ -27,13 +27,13 @@ class CharacterReplacementTestCest */ public function CharacterReplacementTest(AcceptanceTester $I) { - $I->click("#element"); - $I->fillField("#element", "7700 West Parmer Lane"); - $I->click("#element .abcdefghijklmnopqrstuvwxyz1234567890"); - $I->click("#element .`~!@#$%^&*()-_=+{}[]|\;:\".,>click("#element .words, and, commas, and, spaces"); - $I->click("#abcdefghijklmnopqrstuvwxyz1234567890 .abcdefghijklmnopqrstuvwxyz1234567890"); - $I->click("#`~!@#$%^&*()-_=+{}[]|\;:\".,>click("#words, and, commas, and, spaces .words, and, commas, and, spaces"); + $I->click("#element"); // stepKey: charsInSectionElement + $I->fillField("#element", "7700 West Parmer Lane"); // stepKey: charsInDataRef + $I->click("#element .abcdefghijklmnopqrstuvwxyz1234567890"); // stepKey: allChars1 + $I->click("#element .`~!@#$%^&*()-_=+{}[]|\;:\".,>click("#element .words, and, commas, and, spaces"); // stepKey: allChars3 + $I->click("#abcdefghijklmnopqrstuvwxyz1234567890 .abcdefghijklmnopqrstuvwxyz1234567890"); // stepKey: allChars4 + $I->click("#`~!@#$%^&*()-_=+{}[]|\;:\".,>click("#words, and, commas, and, spaces .words, and, commas, and, spaces"); // stepKey: allChars6 } } diff --git a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt index 27c9a99c6..4c8ec1ea1 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestAddHooks.txt @@ -26,7 +26,7 @@ class ChildExtendedTestAddHooksCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ChildExtendedTestAddHooksCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ChildExtendedTestAddHooksCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt index 788818272..a59d141b4 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestMerging.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestMerging.txt @@ -26,9 +26,9 @@ class ChildExtendedTestMergingCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/firstUrl"); - $I->amOnPage("/beforeUrl"); - $I->amOnPage("/lastUrl"); + $I->amOnPage("/firstUrl"); // stepKey: firstBeforeAmOnPageKey + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey + $I->amOnPage("/lastUrl"); // stepKey: lastBefore } /** @@ -37,7 +37,7 @@ class ChildExtendedTestMergingCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -46,7 +46,7 @@ class ChildExtendedTestMergingCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt index 40a3184c9..b1eb8340b 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveAction.txt @@ -26,7 +26,7 @@ class ChildExtendedTestRemoveActionCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ChildExtendedTestRemoveActionCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ChildExtendedTestRemoveActionCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt index 7419e681a..cd0e6b049 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestRemoveHookAction.txt @@ -34,7 +34,7 @@ class ChildExtendedTestRemoveHookActionCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -43,7 +43,7 @@ class ChildExtendedTestRemoveHookActionCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt index 18b1984c0..6c699b7db 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplace.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplace.txt @@ -26,7 +26,7 @@ class ChildExtendedTestReplaceCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ChildExtendedTestReplaceCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ChildExtendedTestReplaceCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt index 90ebf3676..82184a206 100644 --- a/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt +++ b/dev/tests/verification/Resources/ChildExtendedTestReplaceHook.txt @@ -26,7 +26,7 @@ class ChildExtendedTestReplaceHookCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/slightlyDifferentBeforeUrl"); + $I->amOnPage("/slightlyDifferentBeforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ChildExtendedTestReplaceHookCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ChildExtendedTestReplaceHookCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/DataActionsTest.txt b/dev/tests/verification/Resources/DataActionsTest.txt index cac3b72cd..5d1ee9e00 100644 --- a/dev/tests/verification/Resources/DataActionsTest.txt +++ b/dev/tests/verification/Resources/DataActionsTest.txt @@ -24,7 +24,7 @@ class DataActionsTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createdInBefore"); + $I->comment("[createdInBefore] create 'entity' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdInBefore", "hook", @@ -32,18 +32,21 @@ class DataActionsTestCest [], null ); - $I->amGoingTo("update entity that has the createdDataKey: createdInBefore"); + + $I->comment("[updateInBefore] update 'createdInBefore' entity to 'entity'"); PersistedObjectHandler::getInstance()->updateEntity( "createdInBefore", "hook", "entity", [] ); - $I->amGoingTo("delete entity that has the createDataKey: createdInBefore"); + + $I->comment("[deleteInBefore] delete entity 'createdInBefore'"); PersistedObjectHandler::getInstance()->deleteEntity( "createdInBefore", "hook" ); + } /** @@ -55,7 +58,7 @@ class DataActionsTestCest */ public function DataActionsTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createdInTest"); + $I->comment("[createdInTest] create 'entity' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdInTest", "test", @@ -63,29 +66,34 @@ class DataActionsTestCest [], null ); - $I->amGoingTo("update entity that has the createdDataKey: createdInTest"); + + $I->comment("[updateInTest] update 'createdInTest' entity to 'entity'"); PersistedObjectHandler::getInstance()->updateEntity( "createdInTest", "test", "entity", [] ); - $I->amGoingTo("delete entity that has the createDataKey: createdInTest"); + + $I->comment("[deleteInTest] delete entity 'createdInTest'"); PersistedObjectHandler::getInstance()->deleteEntity( "createdInTest", "test" ); - $I->amGoingTo("update entity that has the createdDataKey: createdInBefore"); + + $I->comment("[updatedDataOutOfScope] update 'createdInBefore' entity to 'entity'"); PersistedObjectHandler::getInstance()->updateEntity( "createdInBefore", "test", "entity", [] ); - $I->amGoingTo("delete entity that has the createDataKey: createdInBefore"); + + $I->comment("[deleteDataOutOfScope] delete entity 'createdInBefore'"); PersistedObjectHandler::getInstance()->deleteEntity( "createdInBefore", "test" ); + } } diff --git a/dev/tests/verification/Resources/DataReplacementTest.txt b/dev/tests/verification/Resources/DataReplacementTest.txt index 60dd2faae..8cc671d3d 100644 --- a/dev/tests/verification/Resources/DataReplacementTest.txt +++ b/dev/tests/verification/Resources/DataReplacementTest.txt @@ -27,31 +27,31 @@ class DataReplacementTestCest */ public function DataReplacementTest(AcceptanceTester $I) { - $I->fillField("#selector", "StringBefore John StringAfter"); - $I->seeCurrentUrlMatches("~\/John~i"); - $I->fillField("#John", "input"); - $I->dragAndDrop("#John", "Doe"); - $I->conditionalClick("Doe", "#John", true); - $I->amOnUrl("John.html"); - $I->searchAndMultiSelectOption("#selector", ["John", "Doe"]); - $I->fillField("#selector", "StringBefore " . msq("uniqueData") . "John StringAfter"); - $I->fillField("#" . msq("uniqueData") . "John", "input"); - $I->dragAndDrop("#" . msq("uniqueData") . "John", msq("uniqueData") . "John"); - $I->conditionalClick(msq("uniqueData") . "John", "#" . msq("uniqueData") . "John", true); - $I->amOnUrl(msq("uniqueData") . "John.html"); - $I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe"]); - $I->click("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); - $I->click("#Doe" . msq("uniqueData") . "#Doe" . msq("uniqueData")); - $I->fillField("#selector", "StringBefore Doe" . msq("uniqueData") . " StringAfter"); - $I->fillField("#Doe" . msq("uniqueData"), "input"); - $I->dragAndDrop("#Doe" . msq("uniqueData"), "Doe" . msq("uniqueData")); - $I->conditionalClick("Doe" . msq("uniqueData"), "#Doe" . msq("uniqueData"), true); - $I->amOnUrl("Doe" . msq("uniqueData") . ".html"); - $I->searchAndMultiSelectOption("#selector", ["John", "Doe" . msq("uniqueData")]); - $I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); - $I->selectMultipleOptions("#Doe" . msq("uniqueData"), "#element", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); - $I->fillField(".selector", "0"); - $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); - $I->comment($insertCommand); + $I->fillField("#selector", "StringBefore John StringAfter"); // stepKey: inputReplace + $I->seeCurrentUrlMatches("~\/John~i"); // stepKey: seeInRegex + $I->fillField("#John", "input"); // stepKey: selectorReplace + $I->dragAndDrop("#John", "Doe"); // stepKey: selector12Replace + $I->conditionalClick("Doe", "#John", true); // stepKey: dependentSelectorReplace + $I->amOnUrl("John.html"); // stepKey: urlReplace + $I->searchAndMultiSelectOption("#selector", ["John", "Doe"]); // stepKey: parameterArrayReplacement + $I->fillField("#selector", "StringBefore " . msq("uniqueData") . "John StringAfter"); // stepKey: inputPrefixReplaceMSQPrefix + $I->fillField("#" . msq("uniqueData") . "John", "input"); // stepKey: selectorReplaceMSQPrefix + $I->dragAndDrop("#" . msq("uniqueData") . "John", msq("uniqueData") . "John"); // stepKey: selector12ReplaceMSQPrefix + $I->conditionalClick(msq("uniqueData") . "John", "#" . msq("uniqueData") . "John", true); // stepKey: dependentSelectorReplaceMSQPrefix + $I->amOnUrl(msq("uniqueData") . "John.html"); // stepKey: urlReplaceMSQPrefix + $I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe"]); // stepKey: parameterArrayReplacementMSQPrefix + $I->click("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); // stepKey: selectorReplaceDupedMSQPrefix + $I->click("#Doe" . msq("uniqueData") . "#Doe" . msq("uniqueData")); // stepKey: selectorReplaceDupedMSQSuffix + $I->fillField("#selector", "StringBefore Doe" . msq("uniqueData") . " StringAfter"); // stepKey: inputReplaceMSQSuffix + $I->fillField("#Doe" . msq("uniqueData"), "input"); // stepKey: selectorReplaceMSQSuffix + $I->dragAndDrop("#Doe" . msq("uniqueData"), "Doe" . msq("uniqueData")); // stepKey: selector12ReplaceMSQSuffix + $I->conditionalClick("Doe" . msq("uniqueData"), "#Doe" . msq("uniqueData"), true); // stepKey: dependentSelectorReplaceMSQSuffix + $I->amOnUrl("Doe" . msq("uniqueData") . ".html"); // stepKey: urlReplaceMSQSuffix + $I->searchAndMultiSelectOption("#selector", ["John", "Doe" . msq("uniqueData")]); // stepKey: parameterArrayReplacementMSQSuffix + $I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); // stepKey: parameterArrayReplacementMSQBoth + $I->selectMultipleOptions("#Doe" . msq("uniqueData"), "#element", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); // stepKey: multiSelectDataReplacement + $I->fillField(".selector", "0"); // stepKey: insertZero + $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); $I->comment($insertCommand); + // stepKey: insertCommand } } diff --git a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt index 323b2ffb9..0fbee0550 100644 --- a/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt +++ b/dev/tests/verification/Resources/ExecuteInSeleniumTest.txt @@ -27,6 +27,6 @@ class ExecuteInSeleniumTestCest */ public function ExecuteInSeleniumTest(AcceptanceTester $I) { - $I->executeInSelenium(function ($webdriver) { return 'Hello, World!'}); + $I->executeInSelenium(function ($webdriver) { return 'Hello, World!'}); // stepKey: executeInSeleniumStep } } diff --git a/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt b/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt index 6dd8ef3db..19140eaf9 100644 --- a/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt +++ b/dev/tests/verification/Resources/ExecuteJsEscapingTest.txt @@ -27,10 +27,10 @@ class ExecuteJsEscapingTestCest */ public function ExecuteJsEscapingTest(AcceptanceTester $I) { - $javaVariableEscape = $I->executeJS("return \$javascriptVariable"); - $mftfVariableNotEscaped = $I->executeJS("return {$doNotEscape}"); - $persistedDataNotEscaped = $I->executeJS("return " . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); - $hookPersistedDataNotEscaped = $I->executeJS("return " . PersistedObjectHandler::getInstance()->retrieveEntityField('persisted', 'data', 'test')); - $addNewAttributeForRule = $I->executeJS("document.querySelector('entity option[value=" . PersistedObjectHandler::getInstance()->retrieveEntityField('productAttribute', 'attribute_code', 'test') . "]').setAttribute('selected', 'selected')"); + $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 } } diff --git a/dev/tests/verification/Resources/ExtendParentDataTest.txt b/dev/tests/verification/Resources/ExtendParentDataTest.txt index 41bea9d6f..a80f3cf19 100644 --- a/dev/tests/verification/Resources/ExtendParentDataTest.txt +++ b/dev/tests/verification/Resources/ExtendParentDataTest.txt @@ -27,7 +27,7 @@ class ExtendParentDataTestCest */ public function ExtendParentDataTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: simpleDataKey"); + $I->comment("[simpleDataKey] create 'extendParentData' entity"); PersistedObjectHandler::getInstance()->createEntity( "simpleDataKey", "test", @@ -35,10 +35,11 @@ class ExtendParentDataTestCest [], null ); - $I->searchAndMultiSelectOption("#selector", ["otherName"]); - $I->searchAndMultiSelectOption("#selector", ["extendName"]); - $I->searchAndMultiSelectOption("#selector", ["item"]); - $I->searchAndMultiSelectOption("#selector", [msq("extendParentData") . "prename"]); - $I->searchAndMultiSelectOption("#selector", ["postnameExtend" . msq("extendParentData")]); + + $I->searchAndMultiSelectOption("#selector", ["otherName"]); // stepKey: getName + $I->searchAndMultiSelectOption("#selector", ["extendName"]); // stepKey: getNameExtend + $I->searchAndMultiSelectOption("#selector", ["item"]); // stepKey: emptyPost + $I->searchAndMultiSelectOption("#selector", [msq("extendParentData") . "prename"]); // stepKey: originalPre + $I->searchAndMultiSelectOption("#selector", ["postnameExtend" . msq("extendParentData")]); // stepKey: secondUniquePre } } diff --git a/dev/tests/verification/Resources/ExtendedActionGroup.txt b/dev/tests/verification/Resources/ExtendedActionGroup.txt index e321bfec1..66ecdbd8a 100644 --- a/dev/tests/verification/Resources/ExtendedActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedActionGroup.txt @@ -27,12 +27,12 @@ class ExtendedActionGroupCest */ public function ExtendedActionGroup(AcceptanceTester $I) { - $I->comment("Entering Action Group extendTestActionGroup (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] extendTestActionGroup"); $I->comment("New Input Before"); - $grabProductsActionGroup = $I->grabMultiple("notASelector"); + $grabProductsActionGroup = $I->grabMultiple("notASelector"); // stepKey: grabProductsActionGroup $I->comment("New Input After"); - $I->assertCount(99, $grabProductsActionGroup); - $I->assertCount(8000, $grabProductsActionGroup); - $I->comment("Exiting Action Group extendTestActionGroup (actionGroup)"); + $I->assertCount(99, $grabProductsActionGroup); // stepKey: assertCountActionGroup + $I->assertCount(8000, $grabProductsActionGroup); // stepKey: assertSecondCountActionGroup + $I->comment("Exiting Action Group [actionGroup] extendTestActionGroup"); } } diff --git a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt index da343e0e1..2483617d1 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestInSuiteCest.txt @@ -26,7 +26,7 @@ class ExtendedChildTestInSuiteCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ExtendedChildTestInSuiteCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ExtendedChildTestInSuiteCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt index cba6db454..cb5fc2e12 100644 --- a/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt +++ b/dev/tests/verification/Resources/ExtendedChildTestNotInSuite.txt @@ -25,7 +25,7 @@ class ExtendedChildTestNotInSuiteCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -34,7 +34,7 @@ class ExtendedChildTestNotInSuiteCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -43,7 +43,7 @@ class ExtendedChildTestNotInSuiteCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt index 6d7e26d87..eed17340e 100644 --- a/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt +++ b/dev/tests/verification/Resources/ExtendedRemoveActionGroup.txt @@ -27,7 +27,7 @@ class ExtendedRemoveActionGroupCest */ public function ExtendedRemoveActionGroup(AcceptanceTester $I) { - $I->comment("Entering Action Group extendRemoveTestActionGroup (actionGroup)"); - $I->comment("Exiting Action Group extendRemoveTestActionGroup (actionGroup)"); + $I->comment("Entering Action Group [actionGroup] extendRemoveTestActionGroup"); + $I->comment("Exiting Action Group [actionGroup] extendRemoveTestActionGroup"); } } diff --git a/dev/tests/verification/Resources/ExtendingSkippedTest.txt b/dev/tests/verification/Resources/ExtendingSkippedTest.txt index 2275de057..b5632c030 100644 --- a/dev/tests/verification/Resources/ExtendingSkippedTest.txt +++ b/dev/tests/verification/Resources/ExtendingSkippedTest.txt @@ -26,7 +26,7 @@ class ExtendingSkippedTestCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ExtendingSkippedTestCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ExtendingSkippedTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/HookActionsTest.txt b/dev/tests/verification/Resources/HookActionsTest.txt index 70e4ece10..74a49eca3 100644 --- a/dev/tests/verification/Resources/HookActionsTest.txt +++ b/dev/tests/verification/Resources/HookActionsTest.txt @@ -24,7 +24,7 @@ class HookActionsTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: sampleCreateBefore"); + $I->comment("[sampleCreateBefore] create 'sampleCreatedEntity' entity"); PersistedObjectHandler::getInstance()->createEntity( "sampleCreateBefore", "hook", @@ -32,12 +32,14 @@ class HookActionsTestCest [], null ); - $I->amGoingTo("delete entity that has the createDataKey: sampleCreateBefore"); + + $I->comment("[sampleDeleteBefore] delete entity 'sampleCreateBefore'"); PersistedObjectHandler::getInstance()->deleteEntity( "sampleCreateBefore", "hook" ); - $I->amGoingTo("create entity that has the stepKey: sampleCreateForAfter"); + + $I->comment("[sampleCreateForAfter] create 'sampleCreatedEntity' entity"); PersistedObjectHandler::getInstance()->createEntity( "sampleCreateForAfter", "hook", @@ -45,6 +47,7 @@ class HookActionsTestCest [], null ); + } /** @@ -53,7 +56,7 @@ class HookActionsTestCest */ public function _after(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: sampleCreateAfter"); + $I->comment("[sampleCreateAfter] create 'sampleCreatedEntity' entity"); PersistedObjectHandler::getInstance()->createEntity( "sampleCreateAfter", "hook", @@ -61,11 +64,13 @@ class HookActionsTestCest [], null ); - $I->amGoingTo("delete entity that has the createDataKey: sampleCreateForAfter"); + + $I->comment("[sampleDeleteAfter] delete entity 'sampleCreateForAfter'"); PersistedObjectHandler::getInstance()->deleteEntity( "sampleCreateForAfter", "hook" ); + } /** @@ -74,7 +79,7 @@ class HookActionsTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/LocatorFunctionTest.txt b/dev/tests/verification/Resources/LocatorFunctionTest.txt index bde511aac..4c96f100b 100644 --- a/dev/tests/verification/Resources/LocatorFunctionTest.txt +++ b/dev/tests/verification/Resources/LocatorFunctionTest.txt @@ -27,7 +27,7 @@ class LocatorFunctionTestCest */ public function LocatorFunctionTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: data"); + $I->comment("[data] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "data", "test", @@ -35,17 +35,18 @@ class LocatorFunctionTestCest [], null ); - $I->click(Locator::contains("'label'", "'Name'")); - $I->click(Locator::contains("'label'", "'Name'")); - $I->click(Locator::find("'img'", ['title' => 'diagram'])); - $I->click(Locator::contains("string", "'Name'")); - $I->click(Locator::contains("John", "'Name'")); - $I->click(Locator::contains(PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key', 'test'), "'Name'")); - $I->click(Locator::contains("string1", "string2")); - $I->click(Locator::contains("John", "Doe")); - $I->click(Locator::contains(PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key2', 'test'))); - $I->click(Locator::contains("string1", "John")); - $I->click(Locator::contains("string1", PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'))); - $I->click(Locator::contains("John", PersistedObjectHandler::getInstance()->retrieveEntityField('data', 'key1', 'test'))); + + $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("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("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 } } diff --git a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt index 5c5091566..2588e679a 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertAfter.txt @@ -27,11 +27,11 @@ class MergeMassViaInsertAfterCest */ public function MergeMassViaInsertAfter(AcceptanceTester $I) { - $I->fillField("#foo", "foo"); - $I->fillField("#bar", "bar"); - $I->click("#mergeOne"); - $I->click("#mergeTwo"); - $I->click("#mergeThree"); - $I->fillField("#baz", "baz"); + $I->fillField("#foo", "foo"); // stepKey: fillField1 + $I->fillField("#bar", "bar"); // stepKey: fillField2 + $I->click("#mergeOne"); // stepKey: clickOne + $I->click("#mergeTwo"); // stepKey: clickTwo + $I->click("#mergeThree"); // stepKey: clickThree + $I->fillField("#baz", "baz"); // stepKey: fillField3 } } diff --git a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt index 94982ec21..7f220c2b7 100644 --- a/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt +++ b/dev/tests/verification/Resources/MergeMassViaInsertBefore.txt @@ -27,11 +27,11 @@ class MergeMassViaInsertBeforeCest */ public function MergeMassViaInsertBefore(AcceptanceTester $I) { - $I->fillField("#foo", "foo"); - $I->click("#mergeOne"); - $I->click("#mergeTwo"); - $I->click("#mergeThree"); - $I->fillField("#bar", "bar"); - $I->fillField("#baz", "baz"); + $I->fillField("#foo", "foo"); // stepKey: fillField1 + $I->click("#mergeOne"); // stepKey: clickOne + $I->click("#mergeTwo"); // stepKey: clickTwo + $I->click("#mergeThree"); // stepKey: clickThree + $I->fillField("#bar", "bar"); // stepKey: fillField2 + $I->fillField("#baz", "baz"); // stepKey: fillField3 } } diff --git a/dev/tests/verification/Resources/MergedActionGroupTest.txt b/dev/tests/verification/Resources/MergedActionGroupTest.txt index 3a5da8725..03ab1287b 100644 --- a/dev/tests/verification/Resources/MergedActionGroupTest.txt +++ b/dev/tests/verification/Resources/MergedActionGroupTest.txt @@ -25,7 +25,7 @@ class MergedActionGroupTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class MergedActionGroupTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class MergedActionGroupTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class MergedActionGroupTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,11 +72,11 @@ class MergedActionGroupTestCest */ public function MergedActionGroupTest(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupForMerge (actionGroupForMerge)"); - $I->see(".merge .Jane"); - $I->see("#element .Jane"); - $I->amOnPage("/Jane/Dane.html"); - $I->click(".merge .Dane"); - $I->comment("Exiting Action Group FunctionalActionGroupForMerge (actionGroupForMerge)"); + $I->comment("Entering Action Group [actionGroupForMerge] FunctionalActionGroupForMerge"); + $I->see(".merge .Jane"); // stepKey: myMergedSeeElementActionGroupForMerge + $I->see("#element .Jane"); // stepKey: see1ActionGroupForMerge + $I->amOnPage("/Jane/Dane.html"); // stepKey: amOnPage1ActionGroupForMerge + $I->click(".merge .Dane"); // stepKey: myMergedClickActionGroupForMerge + $I->comment("Exiting Action Group [actionGroupForMerge] FunctionalActionGroupForMerge"); } } diff --git a/dev/tests/verification/Resources/MergedReferencesTest.txt b/dev/tests/verification/Resources/MergedReferencesTest.txt index 3f47703b9..456f66cc1 100644 --- a/dev/tests/verification/Resources/MergedReferencesTest.txt +++ b/dev/tests/verification/Resources/MergedReferencesTest.txt @@ -26,7 +26,7 @@ class MergedReferencesTestCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: before1 } /** @@ -35,7 +35,7 @@ class MergedReferencesTestCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: after1 } /** @@ -44,7 +44,7 @@ class MergedReferencesTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -58,7 +58,7 @@ class MergedReferencesTestCest */ public function MergedReferencesTest(AcceptanceTester $I) { - $I->fillField("#merge", "merged"); - $I->fillField("#newElement", "newField"); + $I->fillField("#merge", "merged"); // stepKey: fillField1 + $I->fillField("#newElement", "newField"); // stepKey: fillField2 } } diff --git a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt index ba99de0cb..e0796ae39 100644 --- a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt +++ b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt @@ -25,7 +25,7 @@ class MultipleActionGroupsTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createPersonParam"); + $I->comment("[createPersonParam] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createPersonParam", "hook", @@ -33,10 +33,11 @@ class MultipleActionGroupsTestCest [], null ); - $I->comment("Entering Action Group FunctionalActionGroup (beforeGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (beforeGroup)"); + + $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1BeforeGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2BeforeGroup + $I->comment("Exiting Action Group [beforeGroup] FunctionalActionGroup"); } /** @@ -45,10 +46,10 @@ class MultipleActionGroupsTestCest */ public function _after(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroup (afterGroup)"); - $I->fillField("#foo", "myData1"); - $I->fillField("#bar", "myData2"); - $I->comment("Exiting Action Group FunctionalActionGroup (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroup"); + $I->fillField("#foo", "myData1"); // stepKey: fillField1AfterGroup + $I->fillField("#bar", "myData2"); // stepKey: fillField2AfterGroup + $I->comment("Exiting Action Group [afterGroup] FunctionalActionGroup"); } /** @@ -57,7 +58,7 @@ class MultipleActionGroupsTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** @@ -71,21 +72,21 @@ class MultipleActionGroupsTestCest */ public function MultipleActionGroupsTest(AcceptanceTester $I) { - $I->amOnPage("/someUrl"); - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroup1)"); - $I->amOnPage("/Jane/Dane.html"); - $I->fillField("#foo", "Jane"); - $I->fillField("#bar", "Dane"); - $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); - $I->see("#element .Jane"); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroup1)"); - $I->click("loginButton"); - $I->comment("Entering Action Group FunctionalActionGroupWithData (actionGroupWithDataOverride2)"); - $I->amOnPage("/John/Doe.html"); - $I->fillField("#foo", "John"); - $I->fillField("#bar", "Doe"); - $I->searchAndMultiSelectOption("#foo", ["John", "Doe"]); - $I->see("#element .John"); - $I->comment("Exiting Action Group FunctionalActionGroupWithData (actionGroupWithDataOverride2)"); + $I->amOnPage("/someUrl"); // stepKey: step1 + $I->comment("Entering Action Group [actionGroup1] FunctionalActionGroupWithData"); + $I->amOnPage("/Jane/Dane.html"); // stepKey: amOnPage1ActionGroup1 + $I->fillField("#foo", "Jane"); // stepKey: fillField1ActionGroup1 + $I->fillField("#bar", "Dane"); // stepKey: fillField2ActionGroup1 + $I->searchAndMultiSelectOption("#foo", ["Jane", "Dane"]); // stepKey: multi1ActionGroup1 + $I->see("#element .Jane"); // stepKey: see1ActionGroup1 + $I->comment("Exiting Action Group [actionGroup1] FunctionalActionGroupWithData"); + $I->click("loginButton"); // stepKey: step6 + $I->comment("Entering Action Group [actionGroupWithDataOverride2] FunctionalActionGroupWithData"); + $I->amOnPage("/John/Doe.html"); // stepKey: amOnPage1ActionGroupWithDataOverride2 + $I->fillField("#foo", "John"); // stepKey: fillField1ActionGroupWithDataOverride2 + $I->fillField("#bar", "Doe"); // stepKey: fillField2ActionGroupWithDataOverride2 + $I->searchAndMultiSelectOption("#foo", ["John", "Doe"]); // stepKey: multi1ActionGroupWithDataOverride2 + $I->see("#element .John"); // stepKey: see1ActionGroupWithDataOverride2 + $I->comment("Exiting Action Group [actionGroupWithDataOverride2] FunctionalActionGroupWithData"); } } diff --git a/dev/tests/verification/Resources/PageReplacementTest.txt b/dev/tests/verification/Resources/PageReplacementTest.txt index 01ddedf78..6b27b55b1 100644 --- a/dev/tests/verification/Resources/PageReplacementTest.txt +++ b/dev/tests/verification/Resources/PageReplacementTest.txt @@ -27,7 +27,7 @@ class PageReplacementTestCest */ public function PageReplacementTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: datakey"); + $I->comment("[datakey] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "datakey", "test", @@ -35,16 +35,17 @@ class PageReplacementTestCest [], null ); - $I->amOnPage("/page.html"); - $I->amOnPage("/StringLiteral/page.html"); - $I->amOnPage("/John/page.html"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . "/page.html"); - $I->amOnPage("/StringLiteral1/StringLiteral2.html"); - $I->amOnPage("/John/StringLiteral2.html"); - $I->amOnPage("/John/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . ".html"); - $I->amOnPage("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('datakey', 'firstname', 'test') . "/StringLiteral2.html"); - $I->amOnPage("/" . getenv("MAGENTO_BACKEND_NAME") . "/backend"); - $I->amOnPage("/" . getenv("MAGENTO_BACKEND_NAME") . "/StringLiteral/page.html"); - $I->amOnUrl("http://myFullUrl.com/"); + + $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("/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("/" . 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 76e1bed32..8f49ca05c 100644 --- a/dev/tests/verification/Resources/ParameterArrayTest.txt +++ b/dev/tests/verification/Resources/ParameterArrayTest.txt @@ -27,7 +27,7 @@ class ParameterArrayTestCest */ public function ParameterArrayTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: simpleDataKey"); + $I->comment("[simpleDataKey] create 'simpleParamData' entity"); PersistedObjectHandler::getInstance()->createEntity( "simpleDataKey", "test", @@ -35,27 +35,28 @@ class ParameterArrayTestCest [], null ); - $I->searchAndMultiSelectOption("#selector", ["name"]); - $I->searchAndMultiSelectOption("#selector", [msq("simpleParamData") . "prename"]); - $I->searchAndMultiSelectOption("#selector", ["postname" . msq("simpleParamData")]); - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->searchAndMultiSelectOption("#selector", ["name", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->searchAndMultiSelectOption("#selector", ['someKey' => PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->searchAndMultiSelectOption("#selector", ['someKey' => "name"]); - $I->searchAndMultiSelectOption("#selector", ['someKey' => msq("simpleParamData") . "prename"]); - $I->searchAndMultiSelectOption("#selector", ['someKey' => "postname" . msq("simpleParamData")]); - $I->unselectOption("#selector", ['foo']); - $I->unselectOption("#selector", ['foo', 'bar']); - $I->unselectOption("#selector", ["name"]); - $I->unselectOption("#selector", [msq("simpleParamData") . "prename"]); - $I->unselectOption("#selector", ["postname" . msq("simpleParamData")]); - $I->unselectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->unselectOption("#selector", ["name", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->pressKey("#selector", PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), ['ctrl', 'a'],\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); - $I->pressKey("#selector", ['ctrl', 'a'], 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); - $I->pressKey("#selector", ['ctrl', 'a'],'new', 10, 20,\Facebook\WebDriver\WebDriverKeys::DELETE,PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')); - $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), 'a', "name"]); - $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], 0, [PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('simpleDataKey', 'name', 'test')]); - $I->pressKey("#selector", ['ctrl', 'a'],'new', 1, ['ctrl'], ['shift', 'ctrl', 'del'], [msq("simpleParamData") . "prename", "postname" . msq("simpleParamData")]); + + $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", ['someKey' => "name"]); // stepKey: literalKeyToStatic + $I->searchAndMultiSelectOption("#selector", ['someKey' => msq("simpleParamData") . "prename"]); // stepKey: literalKeyToPrefixUnique + $I->searchAndMultiSelectOption("#selector", ['someKey' => "postname" . msq("simpleParamData")]); // stepKey: literalKeyToSuffixUnique + $I->unselectOption("#selector", ['foo']); // stepKey: 000 + $I->unselectOption("#selector", ['foo', 'bar']); // stepKey: 001 + $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->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 c3d7217b3..7c0375190 100644 --- a/dev/tests/verification/Resources/ParentExtendedTest.txt +++ b/dev/tests/verification/Resources/ParentExtendedTest.txt @@ -26,7 +26,7 @@ class ParentExtendedTestCest */ public function _before(AcceptanceTester $I) { - $I->amOnPage("/beforeUrl"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey } /** @@ -35,7 +35,7 @@ class ParentExtendedTestCest */ public function _after(AcceptanceTester $I) { - $I->amOnPage("/afterUrl"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey } /** @@ -44,7 +44,7 @@ class ParentExtendedTestCest */ public function _failed(AcceptanceTester $I) { - $I->saveScreenshot(); + $I->saveScreenshot(); // stepKey: saveScreenshot } /** diff --git a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt index 510e99018..7840afc76 100644 --- a/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt +++ b/dev/tests/verification/Resources/PersistedAndXmlEntityArguments.txt @@ -27,8 +27,8 @@ class PersistedAndXmlEntityArgumentsCest */ public function PersistedAndXmlEntityArguments(AcceptanceTester $I) { - $I->comment("Entering Action Group FunctionalActionGroupWithXmlAndPersistedData (afterGroup)"); - $I->seeInCurrentUrl("/" . PersistedObjectHandler::getInstance()->retrieveEntityField('persistedInTest', 'urlKey', 'test') . ".html?___store=" . msq("uniqueData") . "John"); - $I->comment("Exiting Action Group FunctionalActionGroupWithXmlAndPersistedData (afterGroup)"); + $I->comment("Entering Action Group [afterGroup] FunctionalActionGroupWithXmlAndPersistedData"); + $I->seeInCurrentUrl("/" . PersistedObjectHandler::getInstance()->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 c19e33ee7..2c5d99bc2 100644 --- a/dev/tests/verification/Resources/PersistedReplacementTest.txt +++ b/dev/tests/verification/Resources/PersistedReplacementTest.txt @@ -24,7 +24,7 @@ class PersistedReplacementTestCest */ public function _before(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createData1"); + $I->comment("[createData1] create 'ReplacementPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData1", "hook", @@ -32,6 +32,7 @@ class PersistedReplacementTestCest [], null ); + } /** @@ -43,7 +44,7 @@ class PersistedReplacementTestCest */ public function PersistedReplacementTest(AcceptanceTester $I) { - $I->amGoingTo("create entity that has the stepKey: createdData"); + $I->comment("[createdData] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData", "test", @@ -51,15 +52,16 @@ class PersistedReplacementTestCest [], null ); - $I->fillField("#selector", "StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); - $I->fillField("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); - $I->fillField("#" . getenv("MAGENTO_BASE_URL") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); - $I->fillSecretField("#" . CredentialStore::getInstance()->getSecret("SECRET_PARAM") . "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "input"); - $I->dragAndDrop("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test')); - $I->conditionalClick(PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test'), "#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), true); - $I->amOnUrl(PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . ".html"); - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'lastname', 'test')]); - $I->fillField("#selector", "John " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " stringLiteral"); - $I->searchAndMultiSelectOption("#selector", [PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test'), "John", "stringLiteral"]); + + $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 } } diff --git a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt index e255a0338..af6507abc 100644 --- a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt +++ b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt @@ -24,8 +24,8 @@ class PersistenceActionGroupAppendingTestCest */ public function _before(AcceptanceTester $I) { - $I->comment("Entering Action Group DataPersistenceAppendingActionGroup (ACTIONGROUPBEFORE)"); - $I->amGoingTo("create entity that has the stepKey: createDataACTIONGROUPBEFORE"); + $I->comment("Entering Action Group [ACTIONGROUPBEFORE] DataPersistenceAppendingActionGroup"); + $I->comment("[createDataACTIONGROUPBEFORE] create 'entity' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataACTIONGROUPBEFORE", "hook", @@ -33,19 +33,22 @@ class PersistenceActionGroupAppendingTestCest [], null ); - $I->amGoingTo("update entity that has the createdDataKey: createDataACTIONGROUPBEFORE"); + + $I->comment("[updateDataACTIONGROUPBEFORE] update 'createDataACTIONGROUPBEFORE' entity to 'newEntity'"); PersistedObjectHandler::getInstance()->updateEntity( "createDataACTIONGROUPBEFORE", "hook", "newEntity", [] ); - $I->amGoingTo("delete entity that has the createDataKey: createDataACTIONGROUPBEFORE"); + + $I->comment("[deleteDataACTIONGROUPBEFORE] delete entity 'createDataACTIONGROUPBEFORE'"); PersistedObjectHandler::getInstance()->deleteEntity( "createDataACTIONGROUPBEFORE", "hook" ); - $I->amGoingTo("get entity that has the stepKey: getDataACTIONGROUPBEFORE"); + + $I->comment("[getDataACTIONGROUPBEFORE] get 'someEneity' entity"); PersistedObjectHandler::getInstance()->getEntity( "getDataACTIONGROUPBEFORE", "hook", @@ -53,8 +56,9 @@ class PersistenceActionGroupAppendingTestCest [], null ); + $I->comment(PersistedObjectHandler::getInstance()->retrieveEntityField('createData', 'field', 'hook')); - $I->comment("Exiting Action Group DataPersistenceAppendingActionGroup (ACTIONGROUPBEFORE)"); + $I->comment("Exiting Action Group [ACTIONGROUPBEFORE] DataPersistenceAppendingActionGroup"); } /** @@ -66,8 +70,8 @@ class PersistenceActionGroupAppendingTestCest */ public function PersistenceActionGroupAppendingTest(AcceptanceTester $I) { - $I->comment("Entering Action Group DataPersistenceAppendingActionGroup (ACTIONGROUP)"); - $I->amGoingTo("create entity that has the stepKey: createDataACTIONGROUP"); + $I->comment("Entering Action Group [ACTIONGROUP] DataPersistenceAppendingActionGroup"); + $I->comment("[createDataACTIONGROUP] create 'entity' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataACTIONGROUP", "test", @@ -75,19 +79,22 @@ class PersistenceActionGroupAppendingTestCest [], null ); - $I->amGoingTo("update entity that has the createdDataKey: createDataACTIONGROUP"); + + $I->comment("[updateDataACTIONGROUP] update 'createDataACTIONGROUP' entity to 'newEntity'"); PersistedObjectHandler::getInstance()->updateEntity( "createDataACTIONGROUP", "test", "newEntity", [] ); - $I->amGoingTo("delete entity that has the createDataKey: createDataACTIONGROUP"); + + $I->comment("[deleteDataACTIONGROUP] delete entity 'createDataACTIONGROUP'"); PersistedObjectHandler::getInstance()->deleteEntity( "createDataACTIONGROUP", "test" ); - $I->amGoingTo("get entity that has the stepKey: getDataACTIONGROUP"); + + $I->comment("[getDataACTIONGROUP] get 'someEneity' entity"); PersistedObjectHandler::getInstance()->getEntity( "getDataACTIONGROUP", "test", @@ -95,7 +102,8 @@ class PersistenceActionGroupAppendingTestCest [], null ); + $I->comment(PersistedObjectHandler::getInstance()->retrieveEntityField('createDataACTIONGROUP', 'field', 'test')); - $I->comment("Exiting Action Group DataPersistenceAppendingActionGroup (ACTIONGROUP)"); + $I->comment("Exiting Action Group [ACTIONGROUP] DataPersistenceAppendingActionGroup"); } } diff --git a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt index 2db1b498f..92b128808 100644 --- a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt +++ b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt @@ -25,8 +25,10 @@ class PersistenceCustomFieldsTestCest public function _before(AcceptanceTester $I) { $createData1Fields['firstname'] = "Mac"; + // stepKey: createData1Firstname $createData1Fields['lastname'] = "Doe"; - $I->amGoingTo("create entity that has the stepKey: createData1"); + // stepKey: createData1Lastname + $I->comment("[createData1] create 'DefaultPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData1", "hook", @@ -34,8 +36,10 @@ class PersistenceCustomFieldsTestCest [], $createData1Fields ); + $createData2Fields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'hook'); - $I->amGoingTo("create entity that has the stepKey: createData2"); + // stepKey: createData2Firstname + $I->comment("[createData2] create 'uniqueData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData2", "hook", @@ -43,6 +47,7 @@ class PersistenceCustomFieldsTestCest ["createData1"], $createData2Fields ); + } /** @@ -55,8 +60,10 @@ class PersistenceCustomFieldsTestCest public function PersistenceCustomFieldsTest(AcceptanceTester $I) { $createdDataFields['favoriteIndex'] = "1"; + // stepKey: createdDataFavoriteIndex $createdDataFields['middlename'] = "Kovacs"; - $I->amGoingTo("create entity that has the stepKey: createdData"); + // stepKey: createdDataMiddlename + $I->comment("[createdData] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData", "test", @@ -64,9 +71,12 @@ class PersistenceCustomFieldsTestCest [], $createdDataFields ); + $createdData3Fields['firstname'] = "Takeshi"; + // stepKey: createdData3Firstname $createdData3Fields['lastname'] = "Kovacs"; - $I->amGoingTo("create entity that has the stepKey: createdData3"); + // stepKey: createdData3Lastname + $I->comment("[createdData3] create 'UniquePerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData3", "test", @@ -74,9 +84,11 @@ class PersistenceCustomFieldsTestCest ["createdData"], $createdData3Fields ); - $I->comment("Entering Action Group PersistenceActionGroup (createdAG)"); + + $I->comment("Entering Action Group [createdAG] PersistenceActionGroup"); $createDataAG1CreatedAGFields['firstname'] = "string1"; - $I->amGoingTo("create entity that has the stepKey: createDataAG1CreatedAG"); + // stepKey: createDataAG1FirstnameCreatedAG + $I->comment("[createDataAG1CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG1CreatedAG", "test", @@ -84,8 +96,10 @@ class PersistenceCustomFieldsTestCest [], $createDataAG1CreatedAGFields ); + $createDataAG2CreatedAGFields['firstname'] = "Jane"; - $I->amGoingTo("create entity that has the stepKey: createDataAG2CreatedAG"); + // stepKey: createDataAG2FirstnameCreatedAG + $I->comment("[createDataAG2CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG2CreatedAG", "test", @@ -93,8 +107,10 @@ class PersistenceCustomFieldsTestCest [], $createDataAG2CreatedAGFields ); + $createDataAG3CreatedAGFields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createdData3', 'firstname', 'test'); - $I->amGoingTo("create entity that has the stepKey: createDataAG3CreatedAG"); + // stepKey: createDataAG3FirstnameCreatedAG + $I->comment("[createDataAG3CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG3CreatedAG", "test", @@ -102,6 +118,7 @@ class PersistenceCustomFieldsTestCest [], $createDataAG3CreatedAGFields ); - $I->comment("Exiting Action Group PersistenceActionGroup (createdAG)"); + + $I->comment("Exiting Action Group [createdAG] PersistenceActionGroup"); } } diff --git a/dev/tests/verification/Resources/SectionReplacementTest.txt b/dev/tests/verification/Resources/SectionReplacementTest.txt index c4d738811..a237faf38 100644 --- a/dev/tests/verification/Resources/SectionReplacementTest.txt +++ b/dev/tests/verification/Resources/SectionReplacementTest.txt @@ -27,26 +27,26 @@ class SectionReplacementTestCest */ public function SectionReplacementTest(AcceptanceTester $I) { - $I->click("#element"); - $I->click("#foo"); - $I->waitForPageLoad(30); - $I->click("#element .stringLiteral"); - $I->click("#stringLiteral1 .stringLiteral2"); - $I->click("#stringLiteral1-stringLiteral2 .stringLiteral3"); - $I->click("#stringLiteral1-stringLiteral2 .stringLiteral1 [stringLiteral3]"); - $I->click("#element .John"); - $I->click("#John .Doe"); - $I->click("#John-Doe .Tiberius"); - $I->click("#John-Doe .John [Tiberius]"); - $I->click("#element ." . msq("uniqueData") . "John"); - $I->click("#" . msq("uniqueData") . "John .stringLiteral2"); - $I->click("#" . msq("uniqueData") . "John-stringLiteral2 .stringLiteral3"); - $I->click("#" . msq("uniqueData") . "John-stringLiteral2 ." . msq("uniqueData") . "John [stringLiteral3]"); - $I->click("#element .Doe" . msq("uniqueData")); - $I->click("#Doe" . msq("uniqueData") . " .stringLiteral2"); - $I->click("#Doe" . msq("uniqueData") . "-stringLiteral2 .stringLiteral3"); - $I->click("#Doe" . msq("uniqueData") . "-stringLiteral2 .Doe" . msq("uniqueData") . " [stringLiteral3]"); - $I->amGoingTo("create entity that has the stepKey: createdData"); + $I->click("#element"); // stepKey: selectorReplace + $I->click("#foo"); // stepKey: selectorReplaceTimeout + $I->waitForPageLoad(30); // stepKey: selectorReplaceTimeoutWaitForPageLoad + $I->click("#element .stringLiteral"); // stepKey: selectorReplaceOneParam + $I->click("#stringLiteral1 .stringLiteral2"); // stepKey: selectorReplaceTwoParam + $I->click("#stringLiteral1-stringLiteral2 .stringLiteral3"); // stepKey: selectorReplaceThreeParam + $I->click("#stringLiteral1-stringLiteral2 .stringLiteral1 [stringLiteral3]"); // stepKey: selectorReplaceThreeParamOneDupe + $I->click("#element .John"); // stepKey: selectorReplaceOneParamDataRef + $I->click("#John .Doe"); // stepKey: selectorReplaceTwoParamDataRef + $I->click("#John-Doe .Tiberius"); // stepKey: selectorReplaceThreeParamDataRef + $I->click("#John-Doe .John [Tiberius]"); // stepKey: selectorReplaceThreeParamOneDupeDataRef + $I->click("#element ." . msq("uniqueData") . "John"); // stepKey: selectorReplaceOneParamDataRefMSQPrefix + $I->click("#" . msq("uniqueData") . "John .stringLiteral2"); // stepKey: selectorReplaceTwoParamDataRefMSQPrefix + $I->click("#" . msq("uniqueData") . "John-stringLiteral2 .stringLiteral3"); // stepKey: selectorReplaceThreeParamDataRefMSQPrefix + $I->click("#" . msq("uniqueData") . "John-stringLiteral2 ." . msq("uniqueData") . "John [stringLiteral3]"); // stepKey: selectorReplaceThreeParamOneDupeDataRefMSQPrefix + $I->click("#element .Doe" . msq("uniqueData")); // stepKey: selectorReplaceOneParamDataRefMSQSuffix + $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", @@ -54,21 +54,22 @@ class SectionReplacementTestCest [], null ); - $I->click("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .stringLiteral2"); - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 .stringLiteral3"); - $I->click("#" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . "-stringLiteral2 ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " [stringLiteral3]"); - $I->click("#element .{$data}"); - $I->click("#{$data1} .{$data2}"); - $I->click("#{$data1}-{$data2} .{$data3}"); - $I->click("#John-Doe .John [Tiberius]"); - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .John"); - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .{$data}"); - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " ." . msq("uniqueData") . "John"); - $I->click("#stringLiteral1-" . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " .Doe" . msq("uniqueData")); - $I->click("#element .1#element .2"); - $I->click("#element .1#element .{$data}"); - $I->click("(//div[@data-role='slide'])[1]/a[@data-element='link'][contains(@href,'')]"); - $I->click("(//div[@data-role='slide'])[1]/a[@data-element='link'][contains(@href,' ')]"); + + $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->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("#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 + $I->click("(//div[@data-role='slide'])[1]/a[@data-element='link'][contains(@href,' ')]"); // stepKey: selectorParamWithASpace } } diff --git a/dev/tests/verification/Resources/functionalSuiteHooks.txt b/dev/tests/verification/Resources/functionalSuiteHooks.txt index d9ff2a344..ee0770ce8 100644 --- a/dev/tests/verification/Resources/functionalSuiteHooks.txt +++ b/dev/tests/verification/Resources/functionalSuiteHooks.txt @@ -60,9 +60,9 @@ class functionalSuiteHooks extends \Codeception\GroupObject $createFields ); $webDriver->click(PersistedObjectHandler::getInstance()->retrieveEntityField('create', 'data', 'suite')); - print("Entering Action Group actionGroupWithTwoArguments (AC)"); + print("Entering Action Group [AC] actionGroupWithTwoArguments"); $webDriver->see("John", msq("uniqueData") . "John"); - print("Exiting Action Group actionGroupWithTwoArguments (AC)"); + print("Exiting Action Group [AC] actionGroupWithTwoArguments"); // reset configuration and close session $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig(); @@ -122,9 +122,9 @@ class functionalSuiteHooks extends \Codeception\GroupObject $webDriver->_initializeSession(); $webDriver->amOnPage("some.url"); $webDriver->deleteEntityByUrl("deleteThis"); - print("Entering Action Group actionGroupWithTwoArguments (AC)"); + print("Entering Action Group [AC] actionGroupWithTwoArguments"); $webDriver->see("John", msq("uniqueData") . "John"); - print("Exiting Action Group actionGroupWithTwoArguments (AC)"); + print("Exiting Action Group [AC] actionGroupWithTwoArguments"); } catch (\Exception $exception) { print $exception->getMessage(); } diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 2784555af..512fcafaf 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -32,7 +32,11 @@ class MagentoAllureAdapter extends AllureCodeception { const STEP_PASSED = "passed"; - + /** + * Test files cache. + * + * @var array + */ private $testFiles = []; /** @@ -234,18 +238,27 @@ function () use ($rootStep, $formattedSteps) { $this->getLifecycle()->fire(new TestCaseFinishedEvent()); } + /** + * Reading stepKey from file. + * + * @param string $stepLine + * @return string|null + */ private function retrieveStepKey($stepLine) { $stepKey = null; list($filePath, $stepLine) = explode(":", $stepLine); - $prevStepLine = $stepLine - 2; + $stepLine = $stepLine - 1; if (!array_key_exists($filePath, $this->testFiles)) { $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - $testFile = $this->testFiles[$filePath]; + $testLineTrimmed = substr( + $this->testFiles[$filePath][$stepLine], + strpos($this->testFiles[$filePath][$stepLine], '//') + ); - list($stepKey) = sscanf($testFile[$prevStepLine], TestGenerator::STEP_KEY_ANNOTATION); + list($stepKey) = sscanf($testLineTrimmed, TestGenerator::STEP_KEY_ANNOTATION); return $stepKey; } diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 6f4bc4461..6cec4ea69 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -1,4 +1,9 @@ steps or !$e->getTest() instanceof ScenarioDriven) { @@ -43,6 +59,12 @@ public function beforeStep(StepEvent $e) $this->printStepKeys($e->getStep()); } + /** + * Print output to cli with stepKey. + * + * @param Step $step + * @return void + */ private function printStepKeys(Step $step) { if ($step instanceof Comment and $step->__toString() == '') { @@ -71,7 +93,9 @@ private function printStepKeys(Step $step) } /** - * @param $string + * Message instance. + * + * @param string $string * @return Message */ private function message($string = '') @@ -79,18 +103,27 @@ private function message($string = '') return $this->messageFactory->message($string); } + /** + * Reading stepKey from file. + * + * @param string $stepLine + * @return string|null + */ private function retrieveStepKey($stepLine) { $stepKey = null; list($filePath, $stepLine) = explode(":", $stepLine); - $prevStepLine = $stepLine - 2; + $stepLine = $stepLine - 1; if (!array_key_exists($filePath, $this->testFiles)) { $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - $testFile = $this->testFiles[$filePath]; + $testLineTrimmed = substr( + $this->testFiles[$filePath][$stepLine], + strpos($this->testFiles[$filePath][$stepLine], '//') + ); - list($stepKey) = sscanf($testFile[$prevStepLine], TestGenerator::STEP_KEY_ANNOTATION); + list($stepKey) = sscanf($testLineTrimmed, TestGenerator::STEP_KEY_ANNOTATION); return $stepKey; } diff --git a/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php b/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php index d4a46adb9..18a6402ea 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/Test/Handlers/ActionGroupObjectHandler.php @@ -107,9 +107,9 @@ private function initActionGroups() $parsedActionGroups = $actionGroupParser->readActionGroupData(); $actionGroupObjectExtractor = new ActionGroupObjectExtractor(); + $neededActionGroup = $parsedActionGroups[ActionGroupObjectHandler::ACTION_GROUP_ROOT]; - foreach ($parsedActionGroups[ActionGroupObjectHandler::ACTION_GROUP_ROOT] as - $actionGroupName => $actionGroupData) { + foreach ($neededActionGroup as $actionGroupName => $actionGroupData) { if (!is_array($actionGroupData)) { continue; } diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index ef2e11c03..1e86cff77 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -532,8 +532,8 @@ private function replaceCreateDataKeys($action, $replacementStepKeys) */ private function addContextCommentsToActionList($actionList, $actionReferenceKey) { - $actionStartComment = self::ACTION_GROUP_CONTEXT_START . $this->name . " (" . $actionReferenceKey . ")"; - $actionEndComment = self::ACTION_GROUP_CONTEXT_END . $this->name . " (" . $actionReferenceKey . ")"; + $actionStartComment = self::ACTION_GROUP_CONTEXT_START . "[" . $actionReferenceKey . "] " . $this->name; + $actionEndComment = self::ACTION_GROUP_CONTEXT_END . "[" . $actionReferenceKey . "] " . $this->name; $startAction = new ActionObject( $actionStartComment, ActionObject::ACTION_TYPE_COMMENT, diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 977027c4d..a49256202 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -39,7 +39,8 @@ class TestGenerator const SUITE_SCOPE = 'suite'; const PRESSKEY_ARRAY_ANCHOR_KEY = '987654321098765432109876543210'; const PERSISTED_OBJECT_NOTATION_REGEX = '/\${1,2}[\w.\[\]]+\${1,2}/'; - const STEP_KEY_ANNOTATION = "\t\t/** @stepKey %s */"; + const NO_STEPKEY_ACTIONS = ['comment', 'createData', 'deleteData', 'updateData', 'getData']; + const STEP_KEY_ANNOTATION = " // stepKey: %s"; /** * Path to the export dir. @@ -699,9 +700,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $storeCode = $customActionAttributes['storeCode']; } - if ($actionObject->getType() !== 'comment') { - $testSteps .= PHP_EOL . sprintf(self::STEP_KEY_ANNOTATION, $stepKey) . PHP_EOL; - } switch ($actionObject->getType()) { case "createData": $entity = $customActionAttributes['entity']; @@ -737,7 +735,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } 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}\","; @@ -815,7 +813,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $key, $updateEntity ); - + // Build array of requiredEntities $requiredEntityKeys = []; foreach ($actionObject->getCustomActionAttributes() as $actionAttribute) { @@ -1305,6 +1303,10 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $parameter ); } + if (!in_array($actionObject->getType(), self::NO_STEPKEY_ACTIONS)) { + $testSteps .= sprintf(self::STEP_KEY_ANNOTATION, $stepKey); + } + $testSteps .= PHP_EOL; } return $testSteps; @@ -1801,7 +1803,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; })) . ");\n"; + $output .= implode(", ", array_filter($args, function($value) { return $value !== null; })) . ");"; return $output; } @@ -1833,7 +1835,7 @@ 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; })) . ");\n"; + $output .= implode(", ", array_filter($args, function($value) { return $value !== null; })) . ");"; return $output; } // @codingStandardsIgnoreEnd From 8aee6af47b424a441260c145034d9dedf03532d9 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk Date: Thu, 6 Jun 2019 11:57:00 -0500 Subject: [PATCH 08/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report - test fixes --- .../ActionGroupWithStepKeyReferences.txt | 7 +- .../Resources/BasicFunctionalTest.txt | 9 +- .../Resources/DataReplacementTest.txt | 5 +- .../Allure/Adapter/MagentoAllureAdapter.php | 23 ++++- .../Codeception/Subscriber/Console.php | 91 +++++++++++++------ .../Util/TestGenerator.php | 11 ++- 6 files changed, 102 insertions(+), 44 deletions(-) diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index 2f23215c2..336cd6610 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -44,13 +44,14 @@ class ActionGroupWithStepKeyReferencesCest $I->fillField($action1); // stepKey: action1ActionGroup $I->comment("Invocation stepKey will be appended in non stepKey instances"); $action3ActionGroup = $I->executeJS($action3ActionGroup); // stepKey: action3ActionGroup - $action4ActionGroup = $I->magentoCLI($action4ActionGroup, "\"stuffHere\""); $I->comment($action4ActionGroup); - // stepKey: action4ActionGroup + $action4ActionGroup = $I->magentoCLI($action4ActionGroup, "\"stuffHere\""); // stepKey: action4ActionGroup + $I->comment($action4ActionGroup); + $date = new \DateTime(); $date->setTimestamp(strtotime("{$action5}")); $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); $action5ActionGroup = $date->format("H:i:s"); - // stepKey: action5ActionGroup + $action6ActionGroup = $I->formatMoney($action6ActionGroup); // stepKey: action6ActionGroup $I->comment("[action7ActionGroup] delete entity '{$action7ActionGroupActionGroup}'"); PersistedObjectHandler::getInstance()->deleteEntity( diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index b3ab7ea9c..3cb373a4c 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -107,20 +107,21 @@ class BasicFunctionalTestCest $date->setTimestamp(strtotime("Now")); $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); $generateDateKey = $date->format("H:i:s"); - // stepKey: generateDateKey + $date = new \DateTime(); $date->setTimestamp(strtotime("Now")); $date->setTimezone(new \DateTimeZone("UTC")); $generateDateKey2 = $date->format("H:i:s"); - // stepKey: generateDateKey2 + $grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput"); // stepKey: grabAttributeFromKey1 $grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']); // stepKey: grabCookieKey1 $grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl"); // stepKey: grabFromCurrentUrlKey1 $grabMultipleKey1 = $I->grabMultiple(".functionalTestSelector"); // stepKey: grabMultipleKey1 $grabTextFromKey1 = $I->grabTextFrom(".functionalTestSelector"); // stepKey: grabTextFromKey1 $grabValueFromKey1 = $I->grabValueFrom(".functionalTestSelector"); // stepKey: grabValueFromKey1 - $magentoCli1 = $I->magentoCLI("maintenance:enable", "\"stuffHere\""); $I->comment($magentoCli1); - // stepKey: magentoCli1 + $magentoCli1 = $I->magentoCLI("maintenance:enable", "\"stuffHere\""); // stepKey: magentoCli1 + $I->comment($magentoCli1); + $I->makeScreenshot("screenShotInput"); // stepKey: makeScreenshotKey1 $I->maximizeWindow(); // stepKey: maximizeWindowKey1 $I->moveBack(); // stepKey: moveBackKey1 diff --git a/dev/tests/verification/Resources/DataReplacementTest.txt b/dev/tests/verification/Resources/DataReplacementTest.txt index 8cc671d3d..211dfd5a1 100644 --- a/dev/tests/verification/Resources/DataReplacementTest.txt +++ b/dev/tests/verification/Resources/DataReplacementTest.txt @@ -51,7 +51,8 @@ class DataReplacementTestCest $I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); // stepKey: parameterArrayReplacementMSQBoth $I->selectMultipleOptions("#Doe" . msq("uniqueData"), "#element", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]); // stepKey: multiSelectDataReplacement $I->fillField(".selector", "0"); // stepKey: insertZero - $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); $I->comment($insertCommand); - // stepKey: insertCommand + $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); // stepKey: insertCommand + $I->comment($insertCommand); + } } diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 512fcafaf..bce6ec339 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -196,17 +196,31 @@ public function testEnd() $formattedSteps = []; $actionGroupStepContainer = null; + $actionGroupStepKey = null; foreach ($rootStep->getSteps() as $step) { + if ($actionGroupStepKey !== null) { + $stepKey = str_replace($actionGroupStepKey, '', $step->getName()); + if ($stepKey !== '[]' && $stepKey !== null) { + $step->setName($stepKey); + } + } // if actionGroup flag, start nesting if (strpos($step->getName(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false) { $step->setName(str_replace(ActionGroupObject::ACTION_GROUP_CONTEXT_START, '', $step->getName())); $actionGroupStepContainer = $step; + + preg_match('/\[(?.*)\]/', $step->getName(), $matches); + if (!empty($matches['actionGroupStepKey'])) { + $actionGroupStepKey = ucfirst($matches['actionGroupStepKey']); + } continue; } + // if actionGroup ended, add stack to steps if (stripos($step->getName(), ActionGroupObject::ACTION_GROUP_CONTEXT_END) !== false) { $formattedSteps[] = $actionGroupStepContainer; $actionGroupStepContainer = null; + $actionGroupStepKey = null; continue; } @@ -253,12 +267,11 @@ private function retrieveStepKey($stepLine) if (!array_key_exists($filePath, $this->testFiles)) { $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - $testLineTrimmed = substr( - $this->testFiles[$filePath][$stepLine], - strpos($this->testFiles[$filePath][$stepLine], '//') - ); - list($stepKey) = sscanf($testLineTrimmed, TestGenerator::STEP_KEY_ANNOTATION); + preg_match("/\/\/ stepKey: (?.*)/", $this->testFiles[$filePath][$stepLine], $matches); + if (!empty($matches['stepKey'])) { + $stepKey = $matches['stepKey']; + } return $stepKey; } diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 6cec4ea69..bc830e3cf 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -1,31 +1,13 @@ steps or !$e->getTest() instanceof ScenarioDriven) { + if ($this->silent or !$this->steps or !$e->getTest() instanceof ScenarioDriven) { return; } + $metaStep = $e->getStep()->getMetaStep(); if ($metaStep and $this->metaStep != $metaStep) { $this->message(' ' . $metaStep->getPrefix()) @@ -59,6 +49,20 @@ public function beforeStep(StepEvent $e) $this->printStepKeys($e->getStep()); } + /** + * If step failed we move back from action group to test scope + * + * @param StepEvent $e + * @return void + */ + public function afterStep(StepEvent $e) + { + parent::afterStep($e); + if ($e->getStep()->hasFailed()) { + $this->actionGroupStepKey = null; + } + } + /** * Print output to cli with stepKey. * @@ -73,20 +77,44 @@ private function printStepKeys(Step $step) $stepKey = $this->retrieveStepKey($step->getLine()); - $msg = $this->message(' '); - if ($this->metaStep) { + $isActionGroup = (strpos($step->__toString(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false); + if ($isActionGroup) { + preg_match('/\[(?.*)\]/', $step->__toString(), $matches); + if (!empty($matches['actionGroupStepKey'])) { + $this->actionGroupStepKey = ucfirst($matches['actionGroupStepKey']); + } + } + + if (strpos($step->__toString(), ActionGroupObject::ACTION_GROUP_CONTEXT_END) !== false) { + $this->actionGroupStepKey = null; + return; + } + + $msg = $this->message(); + if ($this->metaStep || ($this->actionGroupStepKey !== null && !$isActionGroup)) { $msg->append(' '); } if ($stepKey !== null) { $msg->append(OutputFormatter::escape("[" . $stepKey . "] ")); + $msg->style('bold'); } if (!$this->metaStep) { $msg->style('bold'); } - $msg->append(OutputFormatter::escape($step->toString($this->width))); - if ($this->metaStep) { + $stepString = str_replace( + [ActionGroupObject::ACTION_GROUP_CONTEXT_START, ActionGroupObject::ACTION_GROUP_CONTEXT_END], + '', + $step->toString(150) + ); + + + $msg->append(OutputFormatter::escape($stepString)); + if ($isActionGroup) { + $msg->style('comment'); + } + if ($this->metaStep || ($this->actionGroupStepKey !== null && !$isActionGroup)) { $msg->style('info'); } $msg->writeln(); @@ -118,12 +146,17 @@ private function retrieveStepKey($stepLine) if (!array_key_exists($filePath, $this->testFiles)) { $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - $testLineTrimmed = substr( - $this->testFiles[$filePath][$stepLine], - strpos($this->testFiles[$filePath][$stepLine], '//') - ); - list($stepKey) = sscanf($testLineTrimmed, TestGenerator::STEP_KEY_ANNOTATION); + preg_match("/\/\/ stepKey: (?.*)/", $this->testFiles[$filePath][$stepLine], $matches); + if (!empty($matches['stepKey'])) { + $stepKey = $matches['stepKey']; + } + + if ($this->actionGroupStepKey !== null) { + $stepKey = str_replace($this->actionGroupStepKey, '', $stepKey); + } + + $stepKey = $stepKey === '[]' ? null : $stepKey; return $stepKey; } diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index a49256202..628145e66 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -39,7 +39,15 @@ class TestGenerator 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']; + const NO_STEPKEY_ACTIONS = [ + 'comment', + 'createData', + 'deleteData', + 'updateData', + 'getData', + 'magentoCLI', + 'generateDate' + ]; const STEP_KEY_ANNOTATION = " // stepKey: %s"; /** @@ -1262,6 +1270,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $command, $arguments ); + $testSteps .= sprintf(self::STEP_KEY_ANNOTATION, $stepKey) . PHP_EOL; $testSteps .= sprintf( "\t\t$%s->comment(\$%s);\n", $actor, From ff1236472e496496d1d4db84e759960d49b287b3 Mon Sep 17 00:00:00 2001 From: John S Date: Thu, 6 Jun 2019 13:05:00 -0500 Subject: [PATCH 09/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- dev/tests/unit/Resources/alteredDocumentation.txt | 1 + dev/tests/unit/Resources/basicDocumentation.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index 5e4d70774..bdb3daae3 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -8,3 +8,4 @@ This documentation contains a list of all Action Groups. **Located In**: - filename *** + diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 43f1c9521..fd5156087 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -8,3 +8,4 @@ This documentation contains a list of all Action Groups. **Located In**: - filename *** + From 17b8b9d8fb42e90e9cd58125a6d727f03b6d1626 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk Date: Thu, 6 Jun 2019 13:11:19 -0500 Subject: [PATCH 10/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report - test fixes --- .../Codeception/Subscriber/Console.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index bc830e3cf..750c9fca4 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -109,7 +109,6 @@ private function printStepKeys(Step $step) $step->toString(150) ); - $msg->append(OutputFormatter::escape($stepString)); if ($isActionGroup) { $msg->style('comment'); From 29e24774da17412364e8acd48003f69c0820d065 Mon Sep 17 00:00:00 2001 From: John S Date: Thu, 6 Jun 2019 13:15:26 -0500 Subject: [PATCH 11/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- dev/tests/unit/Resources/alteredDocumentation.txt | 1 - dev/tests/unit/Resources/basicDocumentation.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index bdb3daae3..5e4d70774 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -8,4 +8,3 @@ This documentation contains a list of all Action Groups. **Located In**: - filename *** - diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index fd5156087..43f1c9521 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -8,4 +8,3 @@ This documentation contains a list of all Action Groups. **Located In**: - filename *** - From 9c7bf5f07df3030038c31e305edce67bf10f8af3 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk Date: Fri, 7 Jun 2019 11:49:22 -0500 Subject: [PATCH 12/59] MQE-1234: Allow XML Parser to read XML comment into comment action --- .../functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml | 2 +- .../functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml | 4 ++++ dev/tests/verification/Resources/AssertTest.txt | 8 ++++++++ .../Test/Config/Converter/Dom/Flat.php | 6 ++++++ .../Test/Objects/ActionObject.php | 5 +++-- .../Test/Util/ActionObjectExtractor.php | 4 +++- .../Test/Util/AnnotationExtractor.php | 4 ++++ .../FunctionalTestingFramework/Util/TestGenerator.php | 2 ++ 8 files changed, 31 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml b/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml index 2b706ed67..88c577aef 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Page/MFTFDocPage.xml @@ -8,7 +8,7 @@ - +
diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml index eceeb3f58..ff9e0220d 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml @@ -10,6 +10,7 @@ xsi:noNamespaceSchemaLocation="../../../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + @@ -18,7 +19,10 @@ <group value="mftf"/> </annotations> + <!-- Open MFTF DevDocs Page --> <amOnPage stepKey="openMFTFDevDocPage" url="{{MFTFDocPage.url}}" /> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> + <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="asdf" /> <see stepKey="verifyPageIntroText" selector="{{contentSection.pageIntro}}" userInput="Introduction to the Magento Functional Testing Framework" /> </test> </tests> diff --git a/dev/tests/verification/Resources/AssertTest.txt b/dev/tests/verification/Resources/AssertTest.txt index 15388667a..697bc3d21 100644 --- a/dev/tests/verification/Resources/AssertTest.txt +++ b/dev/tests/verification/Resources/AssertTest.txt @@ -54,8 +54,10 @@ class AssertTestCest ); $grabTextFrom1 = $I->grabTextFrom(".copyright>span"); // stepKey: grabTextFrom1 + $I->comment("custom asserts"); $I->assertArrayIsSorted(["1", "2", "3", "4", "5"], "asc"); // stepKey: assertSorted1 $I->comment("asserts without variable replacement"); + $I->comment("asserts without variable replacement"); $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKey $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKey $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubset @@ -91,6 +93,7 @@ class AssertTestCest $I->assertStringStartsWith("a", "apple", "pass"); // stepKey: assertStringStartsWith $I->assertTrue(true, "pass"); // stepKey: assertTrue $I->comment("asserts backward compatible"); + $I->comment("asserts backward compatible"); $I->assertArrayHasKey("apple", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayHasKeyBackwardCompatible $I->assertArrayNotHasKey("kiwi", ['orange' => 2, 'apple' => 1], "pass"); // stepKey: assertArrayNotHasKeyBackwardCompatible $I->assertArraySubset([1, 2], [1, 2, 3, 5], "pass"); // stepKey: assertArraySubsetBackwardCompatible @@ -133,14 +136,17 @@ class AssertTestCest $I->assertNull($text, "pass"); // stepKey: assertNullBackwardCompatible $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->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->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 $I->assertFileExists($text, "pass"); // stepKey: assertFileExists2 @@ -151,6 +157,7 @@ class AssertTestCest $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->comment("assertElementContainsAttribute examples"); $I->assertElementContainsAttribute("#username", "class", "admin__control-text"); // stepKey: assertElementContainsAttribute1 $I->assertElementContainsAttribute("#username", "name", "login[username]"); // stepKey: assertElementContainsAttribute2 $I->assertElementContainsAttribute("#username", "autofocus", "true"); // stepKey: assertElementContainsAttribute3 @@ -159,6 +166,7 @@ class AssertTestCest $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->comment("assert entity resolution"); $I->assertEquals("John", "Doe", "pass"); // stepKey: assertEqualsEntity } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php index dd72264b9..a01841041 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php @@ -124,6 +124,12 @@ public function convertXml(\DOMNode $source, $basePath = '') ) { $value = $node->nodeValue; break; + } elseif ($node->nodeType == XML_COMMENT_NODE) { + $uniqid = uniqid(str_replace("#", "", $node->nodeName)); + $value[$uniqid] = [ + 'value' => trim($node->nodeValue), + 'nodeName' => $node->nodeName, + ]; } } $result = $this->getNodeAttributes($source); diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index 8a3bb27a6..19bd58721 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -23,6 +23,7 @@ */ class ActionObject { + const COMMENT_ACTION = '#comment'; const __ENV = "_ENV"; const __CREDS = "_CREDS"; const RUNTIME_REFERENCES = [ @@ -148,7 +149,7 @@ public function __construct( $actionOrigin = null ) { $this->stepKey = $stepKey; - $this->type = $type; + $this->type = $type === self::COMMENT_ACTION ? self::ACTION_TYPE_COMMENT : $type; $this->actionAttributes = $actionAttributes; $this->linkedAction = $linkedAction; $this->actionOrigin = $actionOrigin; @@ -554,7 +555,7 @@ private function findAndReplaceReferences($objectHandler, $inputString) } if ($replacement === null) { - if (get_class($objectHandler) != DataObjectHandler::class) { + if (!($objectHandler instanceof DataObjectHandler)) { return $this->findAndReplaceReferences(DataObjectHandler::getInstance(), $outputString); } else { throw new TestReferenceException( diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php index 5cd7b7ac5..605a1fdc2 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php @@ -58,7 +58,9 @@ public function extractActions($testActions, $testName = null) $stepKeyRefs = []; foreach ($testActions as $actionName => $actionData) { - $stepKey = $actionData[self::TEST_STEP_MERGE_KEY]; + $stepKey = strpos($actionData[self::NODE_NAME], ActionObject::COMMENT_ACTION) === false + ? $actionData[self::TEST_STEP_MERGE_KEY] + : $actionName; $actionType = $actionData[self::NODE_NAME]; if (empty($stepKey)) { diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php index 3b857e29f..d30ed351e 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/AnnotationExtractor.php @@ -8,6 +8,7 @@ use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Magento\FunctionalTestingFramework\Exceptions\XmlException; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; /** @@ -67,6 +68,9 @@ public function extractAnnotations($testAnnotations, $filename) // parse the Test annotations foreach ($annotations as $annotationKey => $annotationData) { + if (strpos($annotationKey, ActionObject::ACTION_TYPE_COMMENT) !== false) { + continue; + } $annotationValues = []; // Only transform severity annotation if ($annotationKey == "severity") { diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 628145e66..60f12a1d1 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1303,6 +1303,8 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato case "skipReadinessCheck": $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $customActionAttributes['state']); break; + case "comment": + $input = $input === null ? strtr($value, ['$' => '\$', '{' => '\{', '}' => '\}']) : $input; default: $testSteps .= $this->wrapFunctionCall( $actor, From 4074560491a288f26131b5e23f3c588383e07f7f Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 7 Jun 2019 12:00:10 -0500 Subject: [PATCH 13/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report --- .../Allure/Adapter/MagentoAllureAdapter.php | 8 +++----- .../Codeception/Subscriber/Console.php | 6 ++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index bce6ec339..f97c1fb7f 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -198,11 +198,9 @@ public function testEnd() $actionGroupStepKey = null; foreach ($rootStep->getSteps() as $step) { - if ($actionGroupStepKey !== null) { - $stepKey = str_replace($actionGroupStepKey, '', $step->getName()); - if ($stepKey !== '[]' && $stepKey !== null) { - $step->setName($stepKey); - } + $stepKey = str_replace($actionGroupStepKey, '', $step->getName()); + if ($stepKey !== '[]' && $stepKey !== null) { + $step->setName($stepKey); } // if actionGroup flag, start nesting if (strpos($step->getName(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false) { diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 750c9fca4..7636f9a91 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -1,4 +1,9 @@ <?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + namespace Magento\FunctionalTestingFramework\Codeception\Subscriber; use Codeception\Event\StepEvent; @@ -68,6 +73,7 @@ public function afterStep(StepEvent $e) * * @param Step $step * @return void + * @SuppressWarnings(PHPMD) */ private function printStepKeys(Step $step) { From 9e19969e26a07e60ea9ec70555834baa128d66eb Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 7 Jun 2019 13:41:43 -0500 Subject: [PATCH 14/59] MQE-659: [ALLURE] Include the test "stepKey" in the MFTF Allure Report --- .../Allure/Adapter/MagentoAllureAdapter.php | 5 +++-- .../Codeception/Subscriber/Console.php | 5 +++-- .../FunctionalTestingFramework/Util/TestGenerator.php | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index f97c1fb7f..81a6fe3ba 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -115,6 +115,7 @@ private function sanitizeGroupName($group) * Override of parent method: * prevent replacing of . to • * strips control characters + * inserts stepKey into step name * * @param StepEvent $stepEvent * @return void @@ -207,7 +208,7 @@ public function testEnd() $step->setName(str_replace(ActionGroupObject::ACTION_GROUP_CONTEXT_START, '', $step->getName())); $actionGroupStepContainer = $step; - preg_match('/\[(?<actionGroupStepKey>.*)\]/', $step->getName(), $matches); + preg_match(TestGenerator::ACTION_GROUP_STEP_KEY_REGEX, $step->getName(), $matches); if (!empty($matches['actionGroupStepKey'])) { $actionGroupStepKey = ucfirst($matches['actionGroupStepKey']); } @@ -266,7 +267,7 @@ private function retrieveStepKey($stepLine) $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - preg_match("/\/\/ stepKey: (?<stepKey>.*)/", $this->testFiles[$filePath][$stepLine], $matches); + preg_match(TestGenerator::ACTION_STEP_KEY_REGEX, $this->testFiles[$filePath][$stepLine], $matches); if (!empty($matches['stepKey'])) { $stepKey = $matches['stepKey']; } diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 7636f9a91..8c56e7733 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -12,6 +12,7 @@ use Codeception\Step\Comment; use Codeception\Test\Interfaces\ScenarioDriven; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; +use Magento\FunctionalTestingFramework\Util\TestGenerator; use Symfony\Component\Console\Formatter\OutputFormatter; class Console extends \Codeception\Subscriber\Console @@ -85,7 +86,7 @@ private function printStepKeys(Step $step) $isActionGroup = (strpos($step->__toString(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false); if ($isActionGroup) { - preg_match('/\[(?<actionGroupStepKey>.*)\]/', $step->__toString(), $matches); + preg_match(TestGenerator::ACTION_GROUP_STEP_KEY_REGEX, $step->__toString(), $matches); if (!empty($matches['actionGroupStepKey'])) { $this->actionGroupStepKey = ucfirst($matches['actionGroupStepKey']); } @@ -152,7 +153,7 @@ private function retrieveStepKey($stepLine) $this->testFiles[$filePath] = explode(PHP_EOL, file_get_contents($filePath)); } - preg_match("/\/\/ stepKey: (?<stepKey>.*)/", $this->testFiles[$filePath][$stepLine], $matches); + preg_match(TestGenerator::ACTION_STEP_KEY_REGEX, $this->testFiles[$filePath][$stepLine], $matches); if (!empty($matches['stepKey'])) { $stepKey = $matches['stepKey']; } diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 628145e66..2b9b85416 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -31,6 +31,8 @@ */ class TestGenerator { + const ACTION_GROUP_STEP_KEY_REGEX = "/\[(?<actionGroupStepKey>.*)\]/"; + const ACTION_STEP_KEY_REGEX = "/\/\/ stepKey: (?<stepKey>.*)/"; const REQUIRED_ENTITY_REFERENCE = 'createDataKey'; const GENERATED_DIR = '_generated'; const DEFAULT_DIR = 'default'; From b8f76671a16a19aeb8da4e981abc2dc94f4586ad Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Fri, 7 Jun 2019 15:20:14 -0500 Subject: [PATCH 15/59] MQE-1234: Allow XML Parser to read XML comment into comment action --- dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml | 3 +-- .../ActionGroupWithDefaultArgumentAndStringSelectorParam.txt | 1 + .../ActionGroupWithPassedArgumentAndStringSelectorParam.txt | 1 + .../verification/TestModule/ActionGroup/BasicActionGroup.xml | 3 +++ dev/tests/verification/TestModule/Test/ActionGroupTest.xml | 3 +++ .../Test/Config/Converter/Dom/Flat.php | 2 +- .../Test/Util/ActionGroupObjectExtractor.php | 5 +++++ .../Test/Util/ActionObjectExtractor.php | 3 ++- .../FunctionalTestingFramework/Util/TestGenerator.php | 1 + 9 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml index ff9e0220d..373bedb30 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml @@ -10,7 +10,7 @@ xsi:noNamespaceSchemaLocation="../../../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> <test name="DevDocsTest"> <annotations> - <!-- Hwello --> + <!-- Comment in Annotations for DevDocs Test are not affecting test generation --> <features value="DevDocs available"/> <stories value="MFTF DevDocs available"/> <title value="Magento Functional Testing Framework Documentation is available."/> @@ -21,7 +21,6 @@ <!-- Open MFTF DevDocs Page --> <amOnPage stepKey="openMFTFDevDocPage" url="{{MFTFDocPage.url}}" /> - <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="asdf" /> <see stepKey="verifyPageIntroText" selector="{{contentSection.pageIntro}}" userInput="Introduction to the Magento Functional Testing Framework" /> </test> diff --git a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt index 68f95298d..d77d33d1f 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt @@ -30,6 +30,7 @@ class ActionGroupWithDefaultArgumentAndStringSelectorParamCest public function ActionGroupWithDefaultArgumentAndStringSelectorParam(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id\">/"); $I->see("John", "#element .test1"); // stepKey: seeFirstNameActionGroup $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } diff --git a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt index 6b85f8b47..c7be840c8 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt @@ -30,6 +30,7 @@ class ActionGroupWithPassedArgumentAndStringSelectorParamCest public function ActionGroupWithPassedArgumentAndStringSelectorParam(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id\">/"); $I->see("John" . msq("UniquePerson"), "#element .test1"); // stepKey: seeFirstNameActionGroup $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml index 45ccdbd24..f90a44b0a 100644 --- a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml @@ -13,9 +13,12 @@ <actionGroup name="actionGroupWithDefaultArgumentAndStringSelectorParam"> <arguments> + <!-- Comments in arguments are not affecting test generation --> + <!-- <argument name="someArgument" defaultValue="ReplacementPerson" /> --> <argument name="someArgument" defaultValue="ReplacementPerson" /> </arguments> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <see selector="{{SampleSection.oneParamElement('test1')}}" userInput="{{someArgument.firstname}}" stepKey="seeFirstName" /> </actionGroup> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml index 56be24441..1b736611d 100644 --- a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml @@ -15,8 +15,11 @@ <actionGroup ref="actionGroupWithoutArguments" stepKey="actionGroup"/> </test> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <test name="ActionGroupWithDefaultArgumentAndStringSelectorParam"> <annotations> + <!-- Comments in Test annotations are not affecting test generation --> + <!-- <severity value="BLOCKER"/> --> <severity value="BLOCKER"/> <title value="Action Group With Default Argument Value and Hardcoded Value in Param"/> </annotations> diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php index a01841041..6d08c367c 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php @@ -125,7 +125,7 @@ public function convertXml(\DOMNode $source, $basePath = '') $value = $node->nodeValue; break; } elseif ($node->nodeType == XML_COMMENT_NODE) { - $uniqid = uniqid(str_replace("#", "", $node->nodeName)); + $uniqid = uniqid($node->nodeName); $value[$uniqid] = [ 'value' => trim($node->nodeValue), 'nodeName' => $node->nodeName, diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php index 74665cf75..34da71231 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php @@ -9,6 +9,7 @@ use Magento\FunctionalTestingFramework\Data\Argument\Interpreter\Argument; use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; +use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Objects\ArgumentObject; /** @@ -117,6 +118,10 @@ private function extractArguments($arguments) self::NODE_NAME ); + $argData = array_filter($argData, function ($key) { + return strpos($key, ActionObject::COMMENT_ACTION) === false; + }, ARRAY_FILTER_USE_KEY); + foreach ($argData as $argName => $argValue) { $parsedArguments[] = new ArgumentObject( $argValue[ArgumentObject::ARGUMENT_NAME], diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php index 605a1fdc2..fc874fa24 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionObjectExtractor.php @@ -58,9 +58,10 @@ public function extractActions($testActions, $testName = null) $stepKeyRefs = []; foreach ($testActions as $actionName => $actionData) { + // Removing # from nodeName to match stepKey requirements $stepKey = strpos($actionData[self::NODE_NAME], ActionObject::COMMENT_ACTION) === false ? $actionData[self::TEST_STEP_MERGE_KEY] - : $actionName; + : str_replace("#", "", $actionName); $actionType = $actionData[self::NODE_NAME]; if (empty($stepKey)) { diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index c9a1e6c00..8c9420337 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1306,6 +1306,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $customActionAttributes['state']); break; case "comment": + // Combining userInput from native XML comment and <comment /> action and fall-through 'default' case. $input = $input === null ? strtr($value, ['$' => '\$', '{' => '\{', '}' => '\}']) : $input; default: $testSteps .= $this->wrapFunctionCall( From 11ad7df4277a3ebd224315e32d7ea3382157cd42 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 10 Jun 2019 09:18:29 -0500 Subject: [PATCH 16/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- dev/tests/unit/Resources/alteredDocumentation.txt | 1 + dev/tests/unit/Resources/basicDocumentation.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index 5e4d70774..0684134f5 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -6,5 +6,6 @@ This documentation contains a list of all Action Groups. - alteredDescription **Located In**: + - filename *** diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 43f1c9521..3bc16cbac 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -6,5 +6,6 @@ This documentation contains a list of all Action Groups. - someDescription **Located In**: + - filename *** From 96210c9fbb5d7191d67344624186c9a36df1a519 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 10 Jun 2019 09:28:45 -0500 Subject: [PATCH 17/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- src/Magento/FunctionalTestingFramework/Util/DocGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php index 0eacf46e2..2642a715f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -128,7 +128,7 @@ private function transformToMarkdown($annotationList) $markdown .= "**Located In**:" . PHP_EOL; foreach ($annotations[self::FILENAMES] as $filename) { $relativeFilename = str_replace(MAGENTO_BP . DIRECTORY_SEPARATOR, "", $filename); - $markdown .= "- $relativeFilename"; + $markdown .= PHP_EOL . "- $relativeFilename"; } $markdown .= PHP_EOL . "***" . PHP_EOL; } From aa456207769ef63ec08fe6d74cdcc11de39d3787 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 10 Jun 2019 09:58:19 -0500 Subject: [PATCH 18/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- src/Magento/FunctionalTestingFramework/Util/DocGenerator.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php index 2642a715f..ea5f4df7f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -111,6 +111,7 @@ private function transformToMarkdown($annotationList) $markdown .= "---" . PHP_EOL; foreach ($annotationList as $group => $objects) { foreach ($objects as $name => $annotations) { + $markdown .= PHP_EOL; $markdown .= "###$name" . PHP_EOL; $markdown .= "**Description**:" . PHP_EOL; $markdown .= "- " . $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] . PHP_EOL . PHP_EOL; From 4dadaf78d198b6b136bbfb4310b4a4e82f584359 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Mon, 10 Jun 2019 10:07:07 -0500 Subject: [PATCH 19/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correcting the expected Text in the Static Test. --- src/Magento/FunctionalTestingFramework/Util/DocGenerator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php index ea5f4df7f..2642a715f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -111,7 +111,6 @@ private function transformToMarkdown($annotationList) $markdown .= "---" . PHP_EOL; foreach ($annotationList as $group => $objects) { foreach ($objects as $name => $annotations) { - $markdown .= PHP_EOL; $markdown .= "###$name" . PHP_EOL; $markdown .= "**Description**:" . PHP_EOL; $markdown .= "- " . $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] . PHP_EOL . PHP_EOL; From 9e44d05bba823e433753550a891e3689451393a4 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Mon, 10 Jun 2019 10:48:36 -0500 Subject: [PATCH 20/59] MQE-1234: Allow XML Parser to read XML comment into comment action --- .../tests/MFTF/DevDocs/Test/DevDocsTest.xml | 1 - ...hDefaultArgumentAndStringSelectorParam.txt | 1 - ...thPassedArgumentAndStringSelectorParam.txt | 1 - .../Resources/XmlCommentedActionGroupTest.txt | 37 ++++++++++ .../Resources/XmlCommentedTest.txt | 74 +++++++++++++++++++ .../ActionGroup/BasicActionGroup.xml | 3 - .../ActionGroup/XmlCommentedActionGroup.xml | 20 +++++ .../TestModule/Test/ActionGroupTest.xml | 3 - .../Test/XmlCommentedActionGroupTest.xml | 17 +++++ .../TestModule/Test/XmlCommentedTest.xml | 42 +++++++++++ .../Tests/ActionGroupGenerationTest.php | 11 +++ .../Tests/BasicCestGenerationTest.php | 15 ++++ .../Test/Util/ActionGroupObjectExtractor.php | 1 + .../Util/TestGenerator.php | 2 +- 14 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt create mode 100644 dev/tests/verification/Resources/XmlCommentedTest.txt create mode 100644 dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml create mode 100644 dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml create mode 100644 dev/tests/verification/TestModule/Test/XmlCommentedTest.xml diff --git a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml index 373bedb30..3bdeeb9e8 100644 --- a/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml +++ b/dev/tests/functional/tests/MFTF/DevDocs/Test/DevDocsTest.xml @@ -21,7 +21,6 @@ <!-- Open MFTF DevDocs Page --> <amOnPage stepKey="openMFTFDevDocPage" url="{{MFTFDocPage.url}}" /> - <actionGroup ref="AdminNavigateMenuActionGroup" stepKey="asdf" /> <see stepKey="verifyPageIntroText" selector="{{contentSection.pageIntro}}" userInput="Introduction to the Magento Functional Testing Framework" /> </test> </tests> diff --git a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt index d77d33d1f..68f95298d 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDefaultArgumentAndStringSelectorParam.txt @@ -30,7 +30,6 @@ class ActionGroupWithDefaultArgumentAndStringSelectorParamCest public function ActionGroupWithDefaultArgumentAndStringSelectorParam(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); - $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id\">/"); $I->see("John", "#element .test1"); // stepKey: seeFirstNameActionGroup $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } diff --git a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt index c7be840c8..6b85f8b47 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPassedArgumentAndStringSelectorParam.txt @@ -30,7 +30,6 @@ class ActionGroupWithPassedArgumentAndStringSelectorParamCest public function ActionGroupWithPassedArgumentAndStringSelectorParam(AcceptanceTester $I) { $I->comment("Entering Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); - $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id\">/"); $I->see("John" . msq("UniquePerson"), "#element .test1"); // stepKey: seeFirstNameActionGroup $I->comment("Exiting Action Group [actionGroup] actionGroupWithDefaultArgumentAndStringSelectorParam"); } diff --git a/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt b/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt new file mode 100644 index 000000000..4605cc350 --- /dev/null +++ b/dev/tests/verification/Resources/XmlCommentedActionGroupTest.txt @@ -0,0 +1,37 @@ +<?php +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; +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; + +/** + * @Title("[NO TESTCASEID]: Action Group With comment block in arguments and action group body") + */ +class XmlCommentedActionGroupTestCest +{ + /** + * @Severity(level = SeverityLevel::CRITICAL) + * @Features({"TestModule"}) + * @Parameter(name = "AcceptanceTester", value="$I") + * @param AcceptanceTester $I + * @return void + * @throws \Exception + */ + public function XmlCommentedActionGroupTest(AcceptanceTester $I) + { + $I->comment("Entering Action Group [actionGroup] XmlCommentedActionGroup"); + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id\">/"); + $I->see("John", "#element .test1"); // stepKey: seeFirstNameActionGroup + $I->comment("Exiting Action Group [actionGroup] XmlCommentedActionGroup"); + } +} diff --git a/dev/tests/verification/Resources/XmlCommentedTest.txt b/dev/tests/verification/Resources/XmlCommentedTest.txt new file mode 100644 index 000000000..1d8bca5aa --- /dev/null +++ b/dev/tests/verification/Resources/XmlCommentedTest.txt @@ -0,0 +1,74 @@ +<?php +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; +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; + +/** + * @Title("[NO TESTCASEID]: Test With comment blocks in root element 'tests', in annotations and in test body.") + */ +class XmlCommentedTestCest +{ + /** + * @param AcceptanceTester $I + * @throws \Exception + */ + public function _before(AcceptanceTester $I) + { + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_1\">/"); + $I->amOnPage("/beforeUrl"); // stepKey: beforeAmOnPageKey + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_2\">/"); + } + + /** + * @param AcceptanceTester $I + * @throws \Exception + */ + public function _after(AcceptanceTester $I) + { + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_1\">/"); + $I->amOnPage("/afterUrl"); // stepKey: afterAmOnPageKey + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_2\">/"); + } + + /** + * @param AcceptanceTester $I + * @throws \Exception + */ + public function _failed(AcceptanceTester $I) + { + $I->saveScreenshot(); // stepKey: saveScreenshot + } + + /** + * @Severity(level = SeverityLevel::CRITICAL) + * @Features({"TestModule"}) + * @Parameter(name = "AcceptanceTester", value="$I") + * @param AcceptanceTester $I + * @return void + * @throws \Exception + */ + public function XmlCommentedTest(AcceptanceTester $I) + { + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_1\">/"); + $someVarDefinition = $I->grabValueFrom(); // stepKey: someVarDefinition + $I->acceptPopup(); // stepKey: acceptPopupKey1 + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_2\">/"); + $I->amOnPage("/test/url"); // stepKey: amOnPageKey1 + $I->appendField(".functionalTestSelector"); // stepKey: appendFieldKey1 + $I->comment("< > & \$abc \" abc ' <click stepKey=\"click\" userInput=\"\$\$createDataHook.firstname\$\$\" selector=\"#id_3\">/"); + $I->attachFile(".functionalTestSelector", "testFileAttachment"); // stepKey: attachFileKey1 + $I->comment("<cancelPopup stepKey=\"cancelPopupKey1\"/>"); + $I->checkOption(".functionalTestSelector"); // stepKey: checkOptionKey1 + } +} diff --git a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml index f90a44b0a..45ccdbd24 100644 --- a/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml +++ b/dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml @@ -13,12 +13,9 @@ <actionGroup name="actionGroupWithDefaultArgumentAndStringSelectorParam"> <arguments> - <!-- Comments in arguments are not affecting test generation --> - <!-- <argument name="someArgument" defaultValue="ReplacementPerson" /> --> <argument name="someArgument" defaultValue="ReplacementPerson" /> </arguments> - <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <see selector="{{SampleSection.oneParamElement('test1')}}" userInput="{{someArgument.firstname}}" stepKey="seeFirstName" /> </actionGroup> diff --git a/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml b/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml new file mode 100644 index 000000000..a46dab939 --- /dev/null +++ b/dev/tests/verification/TestModule/ActionGroup/XmlCommentedActionGroup.xml @@ -0,0 +1,20 @@ +<?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="XmlCommentedActionGroup"> + <arguments> + <!-- Comments in arguments are not affecting test generation --> + <!-- <argument name="someArgument" defaultValue="ReplacementPerson" /> --> + <argument name="someArgument" defaultValue="ReplacementPerson" /> + </arguments> + + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> + <see selector="{{SampleSection.oneParamElement('test1')}}" userInput="{{someArgument.firstname}}" stepKey="seeFirstName" /> + </actionGroup> +</actionGroups> diff --git a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml index 1b736611d..56be24441 100644 --- a/dev/tests/verification/TestModule/Test/ActionGroupTest.xml +++ b/dev/tests/verification/TestModule/Test/ActionGroupTest.xml @@ -15,11 +15,8 @@ <actionGroup ref="actionGroupWithoutArguments" stepKey="actionGroup"/> </test> - <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> <test name="ActionGroupWithDefaultArgumentAndStringSelectorParam"> <annotations> - <!-- Comments in Test annotations are not affecting test generation --> - <!-- <severity value="BLOCKER"/> --> <severity value="BLOCKER"/> <title value="Action Group With Default Argument Value and Hardcoded Value in Param"/> </annotations> diff --git a/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml b/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml new file mode 100644 index 000000000..f7fbd8dd6 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/XmlCommentedActionGroupTest.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="XmlCommentedActionGroupTest"> + <annotations> + <severity value="CRITICAL"/> + <title value="Action Group With comment block in arguments and action group body"/> + </annotations> + <actionGroup ref="XmlCommentedActionGroup" stepKey="actionGroup"/> + </test> +</tests> diff --git a/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml b/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml new file mode 100644 index 000000000..133588872 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/XmlCommentedTest.xml @@ -0,0 +1,42 @@ +<?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"> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id">/--> + <test name="XmlCommentedTest"> + <annotations> + <!-- Comments in Test annotations are not affecting test generation --> + <!-- <severity value="BLOCKER"/> --> + <severity value="CRITICAL"/> + <title value="Test With comment blocks in root element 'tests', in annotations and in test body."/> + </annotations> + <before> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_1">/--> + <amOnPage url="/beforeUrl" stepKey="beforeAmOnPageKey"/> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_2">/--> + </before> + <after> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_1">/--> + <amOnPage url="/afterUrl" stepKey="afterAmOnPageKey"/> + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_2">/--> + </after> + + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_1">/--> + <grabValueFrom stepKey="someVarDefinition"/> + <acceptPopup stepKey="acceptPopupKey1"/> + + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_2">/--> + <amOnPage stepKey="amOnPageKey1" url="/test/url"/> + <appendField selector=".functionalTestSelector" stepKey="appendFieldKey1" /> + + <!--< > & $abc " abc ' <click stepKey="click" userInput="$$createDataHook.firstname$$" selector="#id_3">/--> + <attachFile userInput="testFileAttachment" selector=".functionalTestSelector" stepKey="attachFileKey1" /> +<!-- <cancelPopup stepKey="cancelPopupKey1"/>--> + <checkOption selector=".functionalTestSelector" stepKey="checkOptionKey1"/> + </test> +</tests> diff --git a/dev/tests/verification/Tests/ActionGroupGenerationTest.php b/dev/tests/verification/Tests/ActionGroupGenerationTest.php index 613d6cb72..604f546b2 100644 --- a/dev/tests/verification/Tests/ActionGroupGenerationTest.php +++ b/dev/tests/verification/Tests/ActionGroupGenerationTest.php @@ -206,4 +206,15 @@ public function testActionGroupWithHyphen() { $this->generateAndCompareTest('ActionGroupWithParameterizedElementWithHyphen'); } + + /** + * Test generation of a test referencing an action group with xml comment in arguments and action group body. + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testActionGroupWithXmlComments() + { + $this->generateAndCompareTest('XmlCommentedActionGroupTest'); + } } diff --git a/dev/tests/verification/Tests/BasicCestGenerationTest.php b/dev/tests/verification/Tests/BasicCestGenerationTest.php index b03cbc487..793b2a502 100644 --- a/dev/tests/verification/Tests/BasicCestGenerationTest.php +++ b/dev/tests/verification/Tests/BasicCestGenerationTest.php @@ -19,4 +19,19 @@ public function testBasicGeneration() { $this->generateAndCompareTest('BasicFunctionalTest'); } + + /** + * Tests flat generation of a hardcoded test file with no external references and with XML comments in: + * - root `tests` element + * - test body + * - test before and after blocks + * - annotations block + * + * @throws \Exception + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + */ + public function testWithXmlComments() + { + $this->generateAndCompareTest('XmlCommentedTest'); + } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php index 34da71231..e41329cb3 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php @@ -118,6 +118,7 @@ private function extractArguments($arguments) self::NODE_NAME ); + // Filtering XML comments from action group arguments. $argData = array_filter($argData, function ($key) { return strpos($key, ActionObject::COMMENT_ACTION) === false; }, ARRAY_FILTER_USE_KEY); diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 8c9420337..bd4e2d3be 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1306,8 +1306,8 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $customActionAttributes['state']); break; case "comment": - // Combining userInput from native XML comment and <comment /> action and fall-through 'default' case. $input = $input === null ? strtr($value, ['$' => '\$', '{' => '\{', '}' => '\}']) : $input; + // Combining userInput from native XML comment and <comment/> action to fall-through 'default' case default: $testSteps .= $this->wrapFunctionCall( $actor, From f6eb3ab6ba63a4a00b565063b58ab9de4524c91d Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Tue, 11 Jun 2019 11:28:51 -0500 Subject: [PATCH 21/59] MQE-1234: Allow XML Parser to read XML comment into comment action - bugfix + new verification tests --- .../Resources/PersistenceCustomFieldsTest.txt | 20 +-- .../Resources/functionalSuiteHooks.txt | 10 +- .../Resources/functionalSuiteWithComments.txt | 134 ++++++++++++++++++ .../Tests/SuiteGenerationTest.php | 59 ++++++++ .../verification/_suite/functionalSuite.xml | 24 ++++ .../Suite/Generators/GroupClassGenerator.php | 8 +- .../Util/TestGenerator.php | 3 +- 7 files changed, 239 insertions(+), 19 deletions(-) create mode 100644 dev/tests/verification/Resources/functionalSuiteWithComments.txt diff --git a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt index 92b128808..68ded6711 100644 --- a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt +++ b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt @@ -25,9 +25,9 @@ class PersistenceCustomFieldsTestCest public function _before(AcceptanceTester $I) { $createData1Fields['firstname'] = "Mac"; - // stepKey: createData1Firstname + $createData1Fields['lastname'] = "Doe"; - // stepKey: createData1Lastname + $I->comment("[createData1] create 'DefaultPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData1", @@ -38,7 +38,7 @@ class PersistenceCustomFieldsTestCest ); $createData2Fields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'hook'); - // stepKey: createData2Firstname + $I->comment("[createData2] create 'uniqueData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData2", @@ -60,9 +60,9 @@ class PersistenceCustomFieldsTestCest public function PersistenceCustomFieldsTest(AcceptanceTester $I) { $createdDataFields['favoriteIndex'] = "1"; - // stepKey: createdDataFavoriteIndex + $createdDataFields['middlename'] = "Kovacs"; - // stepKey: createdDataMiddlename + $I->comment("[createdData] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData", @@ -73,9 +73,9 @@ class PersistenceCustomFieldsTestCest ); $createdData3Fields['firstname'] = "Takeshi"; - // stepKey: createdData3Firstname + $createdData3Fields['lastname'] = "Kovacs"; - // stepKey: createdData3Lastname + $I->comment("[createdData3] create 'UniquePerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData3", @@ -87,7 +87,7 @@ class PersistenceCustomFieldsTestCest $I->comment("Entering Action Group [createdAG] PersistenceActionGroup"); $createDataAG1CreatedAGFields['firstname'] = "string1"; - // stepKey: createDataAG1FirstnameCreatedAG + $I->comment("[createDataAG1CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG1CreatedAG", @@ -98,7 +98,7 @@ class PersistenceCustomFieldsTestCest ); $createDataAG2CreatedAGFields['firstname'] = "Jane"; - // stepKey: createDataAG2FirstnameCreatedAG + $I->comment("[createDataAG2CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG2CreatedAG", @@ -109,7 +109,7 @@ class PersistenceCustomFieldsTestCest ); $createDataAG3CreatedAGFields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createdData3', 'firstname', 'test'); - // stepKey: createDataAG3FirstnameCreatedAG + $I->comment("[createDataAG3CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG3CreatedAG", diff --git a/dev/tests/verification/Resources/functionalSuiteHooks.txt b/dev/tests/verification/Resources/functionalSuiteHooks.txt index ee0770ce8..4df805329 100644 --- a/dev/tests/verification/Resources/functionalSuiteHooks.txt +++ b/dev/tests/verification/Resources/functionalSuiteHooks.txt @@ -51,7 +51,7 @@ class functionalSuiteHooks extends \Codeception\GroupObject // initialize the webdriver session $webDriver->_initializeSession(); - $webDriver->amOnPage("some.url"); + $webDriver->amOnPage("some.url"); // stepKey: before $createFields['someKey'] = "dataHere"; PersistedObjectHandler::getInstance()->createEntity( "create", @@ -59,9 +59,9 @@ class functionalSuiteHooks extends \Codeception\GroupObject "createThis", $createFields ); - $webDriver->click(PersistedObjectHandler::getInstance()->retrieveEntityField('create', 'data', 'suite')); + $webDriver->click(PersistedObjectHandler::getInstance()->retrieveEntityField('create', 'data', 'suite')); // stepKey: clickWithData print("Entering Action Group [AC] actionGroupWithTwoArguments"); - $webDriver->see("John", msq("uniqueData") . "John"); + $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC print("Exiting Action Group [AC] actionGroupWithTwoArguments"); // reset configuration and close session @@ -120,10 +120,10 @@ class functionalSuiteHooks extends \Codeception\GroupObject // initialize the webdriver session $webDriver->_initializeSession(); - $webDriver->amOnPage("some.url"); + $webDriver->amOnPage("some.url"); // stepKey: after $webDriver->deleteEntityByUrl("deleteThis"); print("Entering Action Group [AC] actionGroupWithTwoArguments"); - $webDriver->see("John", msq("uniqueData") . "John"); + $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC print("Exiting Action Group [AC] actionGroupWithTwoArguments"); } catch (\Exception $exception) { print $exception->getMessage(); diff --git a/dev/tests/verification/Resources/functionalSuiteWithComments.txt b/dev/tests/verification/Resources/functionalSuiteWithComments.txt new file mode 100644 index 000000000..d0e059aab --- /dev/null +++ b/dev/tests/verification/Resources/functionalSuiteWithComments.txt @@ -0,0 +1,134 @@ +<?php + +namespace Group; + +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\PersistedObjectHandler; + +/** + * Group class is Codeception Extension which is allowed to handle to all internal events. + * This class itself can be used to listen events for test execution of one particular group. + * It may be especially useful to create fixtures data, prepare server, etc. + * + * INSTALLATION: + * + * To use this group extension, include it to "extensions" option of global Codeception config. + */ +class functionalSuiteWithComments extends \Codeception\GroupObject +{ + public static $group = 'functionalSuiteWithComments'; + private $testCount = 1; + private $preconditionFailure = null; + private $currentTestRun = 0; + private static $HOOK_EXECUTION_INIT = "\n/******** Beginning execution of functionalSuiteWithComments suite %s block ********/\n"; + private static $HOOK_EXECUTION_END = "\n/******** Execution of functionalSuiteWithComments suite %s block complete ********/\n"; + + public function _before(\Codeception\Event\TestEvent $e) + { + // increment test count per execution + $this->currentTestRun++; + $this->executePreConditions(); + + if ($this->preconditionFailure != null) { + //if our preconditions fail, we need to mark all the tests as incomplete. + $e->getTest()->getMetadata()->setIncomplete("SUITE PRECONDITION FAILED:" . PHP_EOL . $this->preconditionFailure); + } + } + + + private function executePreConditions() + { + if ($this->currentTestRun == 1) { + print sprintf(self::$HOOK_EXECUTION_INIT, "before"); + + try { + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + + // close any open sessions + if ($webDriver->webDriver != null) { + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + } + + // initialize the webdriver session + $webDriver->_initializeSession(); + print("Comment in Before"); + $webDriver->amOnPage("some.url"); // stepKey: before + $createFields['someKey'] = "dataHere"; + PersistedObjectHandler::getInstance()->createEntity( + "create", + "suite", + "createThis", + $createFields + ); + print("<click stepKey=\"comment with element\" userInput=\"helloworld\"/>"); + $webDriver->click(PersistedObjectHandler::getInstance()->retrieveEntityField('create', 'data', 'suite')); // stepKey: clickWithData + print("Entering Action Group [AC] actionGroupWithTwoArguments"); + $webDriver->see("John", msq("uniqueData") . "John"); // stepKey: seeFirstNameAC + print("Exiting Action Group [AC] actionGroupWithTwoArguments"); + + // reset configuration and close session + $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig(); + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + + } catch (\Exception $exception) { + $this->preconditionFailure = $exception->getMessage(); + } + + print sprintf(self::$HOOK_EXECUTION_END, "before"); + } + } + + public function _after(\Codeception\Event\TestEvent $e) + { + $this->executePostConditions($e); + } + + + private function executePostConditions(\Codeception\Event\TestEvent $e) + { + if ($this->currentTestRun == $this->testCount) { + print sprintf(self::$HOOK_EXECUTION_INIT, "after"); + + try { + // Find out if Test in Suite failed, will cause potential failures in suite after + $cest = $e->getTest(); + + //Access private TestResultObject to find stack and if there are any errors (as opposed to failures) + $testResultObject = call_user_func(\Closure::bind( + function () use ($cest) { + return $cest->getTestResultObject(); + }, + $cest + )); + $errors = $testResultObject->errors(); + + if (!empty($errors)) { + foreach ($errors as $error) { + if ($error->failedTest()->getTestMethod() == $cest->getName()) { + // Do not attempt to run _after if failure was in the _after block + // Try to run _after but catch exceptions to prevent them from overwriting original failure. + print("LAST TEST IN SUITE FAILED, TEST AFTER MAY NOT BE SUCCESSFUL\n"); + } + } + } + $webDriver = $this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + + // close any open sessions + if ($webDriver->webDriver != null) { + $webDriver->webDriver->close(); + $webDriver->webDriver = null; + } + + // initialize the webdriver session + $webDriver->_initializeSession(); + print("afterBlock"); + } catch (\Exception $exception) { + print $exception->getMessage(); + } + + PersistedObjectHandler::getInstance()->clearSuiteObjects(); + print sprintf(self::$HOOK_EXECUTION_END, "after"); + } + } +} diff --git a/dev/tests/verification/Tests/SuiteGenerationTest.php b/dev/tests/verification/Tests/SuiteGenerationTest.php index f305e565f..d2242fb52 100644 --- a/dev/tests/verification/Tests/SuiteGenerationTest.php +++ b/dev/tests/verification/Tests/SuiteGenerationTest.php @@ -327,6 +327,65 @@ public function testSuiteGenerationWithExtends() } } + /** + * Test comments generated during suite generation + */ + public function testSuiteCommentsGeneration() + { + $groupName = 'functionalSuiteWithComments'; + + $expectedContents = [ + 'IncludeTestCest.php' + ]; + + // Generate the Suite + SuiteGenerator::getInstance()->generateSuite($groupName); + + // Validate log message and add group name for later deletion + TestLoggingUtil::getInstance()->validateMockLogStatement( + 'info', + "suite generated", + ['suite' => $groupName, 'relative_path' => "_generated" . DIRECTORY_SEPARATOR . $groupName] + ); + self::$TEST_GROUPS[] = $groupName; + + // Validate Yaml file updated + $yml = Yaml::parse(file_get_contents(self::CONFIG_YML_FILE)); + $this->assertArrayHasKey($groupName, $yml['groups']); + + $suiteResultBaseDir = self::GENERATE_RESULT_DIR . + DIRECTORY_SEPARATOR . + $groupName . + DIRECTORY_SEPARATOR; + + // Validate tests have been generated + $dirContents = array_diff(scandir($suiteResultBaseDir), ['..', '.']); + + foreach ($expectedContents as $expectedFile) { + $this->assertTrue(in_array($expectedFile, $dirContents)); + } + + //assert group file created and contains correct contents + $groupFile = PROJECT_ROOT . + DIRECTORY_SEPARATOR . + "src" . + DIRECTORY_SEPARATOR . + "Magento" . + DIRECTORY_SEPARATOR . + "FunctionalTestingFramework" . + DIRECTORY_SEPARATOR . + "Group" . + DIRECTORY_SEPARATOR . + $groupName . + ".php"; + + $this->assertTrue(file_exists($groupFile)); + $this->assertFileEquals( + self::RESOURCES_PATH . DIRECTORY_SEPARATOR . $groupName . ".txt", + $groupFile + ); + } + /** * revert any changes made to config.yml * remove _generated directory diff --git a/dev/tests/verification/_suite/functionalSuite.xml b/dev/tests/verification/_suite/functionalSuite.xml index 439445c24..cfdaa3557 100644 --- a/dev/tests/verification/_suite/functionalSuite.xml +++ b/dev/tests/verification/_suite/functionalSuite.xml @@ -29,4 +29,28 @@ <test name="ExcludeTest2"/> </exclude> </suite> + <suite name="functionalSuiteWithComments"> + <include> + <!-- Comment Block--> + <test name="IncludeTest"/> + </include> + <before> + <!-- Comment in Before--> + <amOnPage url="some.url" stepKey="before"/> + <createData entity="createThis" stepKey="create"> + <!--Comment in Nested Element--> + <field key="someKey">dataHere</field> + </createData> + <!-- <click stepKey="comment with element" userInput="helloworld"/> --> + <click stepKey="clickWithData" userInput="$create.data$"/> + <actionGroup ref="actionGroupWithTwoArguments" stepKey="AC"> + <!--Comment in AG Args--> + <argument name="somePerson" value="simpleData"/> + <argument name="anotherPerson" value="uniqueData"/> + </actionGroup> + </before> + <after> + <comment userInput="afterBlock" stepKey="afterBlock"/> + </after> + </suite> </suites> diff --git a/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php b/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php index a84f6b1b3..415d884b6 100644 --- a/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Suite/Generators/GroupClassGenerator.php @@ -172,10 +172,11 @@ private function buildHookMustacheArray($hookObj) private function buildWebDriverActionsMustacheArray($action, $actionEntries) { $step = TestGenerator::getInstance()->generateStepsPhp([$action], TestGenerator::SUITE_SCOPE, 'webDriver'); - $rawPhp = str_replace(["\t", "\n"], "", $step); - $multipleCommands = explode(";", $rawPhp, -1); + $rawPhp = str_replace(["\t"], "", $step); + $multipleCommands = explode(PHP_EOL, $rawPhp, -1); + $multipleCommands = array_filter($multipleCommands); foreach ($multipleCommands as $command) { - $actionEntries = $this->replaceReservedTesterFunctions($command . ";", $actionEntries, 'webDriver'); + $actionEntries = $this->replaceReservedTesterFunctions($command . PHP_EOL, $actionEntries, 'webDriver'); } return $actionEntries; @@ -192,6 +193,7 @@ private function buildWebDriverActionsMustacheArray($action, $actionEntries) */ private function replaceReservedTesterFunctions($formattedStep, $actionEntries, $actor) { + $formattedStep = rtrim($formattedStep); foreach (self::REPLACEMENT_ACTIONS as $testAction => $replacement) { $testActionCall = "\${$actor}->{$testAction}"; if (substr($formattedStep, 0, strlen($testActionCall)) == $testActionCall) { diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index bd4e2d3be..9e878277e 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -48,7 +48,8 @@ class TestGenerator 'updateData', 'getData', 'magentoCLI', - 'generateDate' + 'generateDate', + 'field' ]; const STEP_KEY_ANNOTATION = " // stepKey: %s"; From b7d28307c529f2c2d673b37be87805319551366a Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@donalds-mbp.corp.adobe.com> Date: Tue, 11 Jun 2019 13:21:29 -0500 Subject: [PATCH 22/59] Updated Selenium version number. --- docs/getting-started.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/getting-started.md b/docs/getting-started.md index 727dc3b18..2d3a6b8d9 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -13,7 +13,7 @@ Make sure that you have the following software installed and configured on your - [PHP version supported by the Magento instance under test][php] - [Composer 1.3 or later][composer] - [Java 1.8 or later][java] -- [Selenium Server Standalone 3.6 or later][selenium server] and [ChromeDriver 2.33 or later][chrome driver] or other webdriver in the same directory +- [Selenium Server Standalone 3.1 or later][selenium server] and [ChromeDriver 2.33 or later][chrome driver] or other webdriver in the same directory <div class="bs-callout bs-callout-tip" markdown="1"> [PhpStorm] supports [Codeception test execution][], which is helpful when debugging. @@ -63,7 +63,7 @@ A Selenium web driver cannot enter data to fields with WYSIWYG. To disable the WYSIWYG and enable the web driver to process these fields as simple text areas: 1. Log in to the Magento Admin as an administrator. -2. Navigate to **Stores \> Configuration \> General \> Content Management**. +2. Navigate to **Stores** > Settings > **Configuration** > **General** > **Content Management**. 3. In the WYSIWYG Options section set the **Enable WYSIWYG Editor** option to **Disabled Completely**. 4. Click **Save Config**. @@ -75,16 +75,16 @@ When you want to test the WYSIWYG functionality, re-enable WYSIWYG in your test To enable the **Admin Account Sharing** setting, to avoid unpredictable logout during a testing session, and disable the **Add Secret Key in URLs** setting, to open pages using direct URLs: -1. Navigate to **Stores \> Configuration \> Advanced \> Admin \> Security**. +1. Navigate to **Stores** > Settings > **Configuration** > **Advanced** > **Admin** > **Security**. 2. Set **Admin Account Sharing** to **Yes**. 3. Set **Add Secret Key to URLs** to **No**. 4. Click **Save Config**. ### Nginx settings {#nginx-settings} -If Nginx Web server is used on your development environment then **Use Web Server Rewrites** setting in **Stores \> Configuration \> Web \> Search Engine Optimization** must be set to **Yes**. +If Nginx Web server is used on your development environment then **Use Web Server Rewrites** setting in **Stores** > Settings > **Configuration** > **Web** > **Search Engine Optimization** must be set to **Yes**. -To be able to run Magento command line commands in tests add the following location block to Nginx configuration file: +To be able to run Magento command line commands in tests add the following location block to Nginx configuration file: ```conf location ~* ^/dev/tests/acceptance/utils($|/) { @@ -97,6 +97,7 @@ location ~* ^/dev/tests/acceptance/utils($|/) { } } ``` + ## Set up an embedded MFTF {#setup-framework} This is a default setup that you would need to start using the MFTF to cover your Magento project with functional testing. @@ -129,7 +130,7 @@ If the file does not exist, add the `--force` option to create it: vendor/bin/mftf generate:urn-catalog --force .idea/ ``` -See [`generate:urn-catalog`][] for more details.' +See [`generate:urn-catalog`][] for more details. <div class="bs-callout bs-callout-tip" markdown="1"> You can simplify command entry by adding the absolute path to the `vendor/bin` directory path to your PATH environment variable. @@ -176,7 +177,7 @@ cp dev/tests/acceptance/.htaccess.sample dev/tests/acceptance/.htaccess To run tests, you need a running Selenium server and [`mftf`][] commands. -#### Run the Selenium server {#selenium-server} +#### Run the Selenium server {#selenium-server} Run the Selenium server in terminal. For example, the following commands run the Selenium server for Google Chrome: @@ -215,7 +216,7 @@ vendor/bin/mftf run:test AdminLoginTest --remove See more commands in [`mftf`][]. -### Step 5. Generate reports {#reports} +### Step 5. Generate reports {#reports} During testing, the MFTF generates test reports in CLI. You can generate visual representations of the report data using [Allure Framework][]. From 4c0c7df95228cf0e92f524fe2200eef5f1871665 Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@adobe.com> Date: Tue, 11 Jun 2019 14:55:40 -0500 Subject: [PATCH 23/59] Fixed spelling error. --- .../FunctionalTestingFramework/Console/BuildProjectCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php b/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php index 9fa28dcc5..6b421a332 100644 --- a/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php @@ -49,7 +49,7 @@ protected function configure() "upgrade", 'u', InputOption::VALUE_NONE, - 'upgrade existing MFTF tests according to last major release requiements' + 'upgrade existing MFTF tests according to last major release requirements' ); $this->envProcessor = new EnvProcessor(TESTS_BP . DIRECTORY_SEPARATOR . '.env'); $env = $this->envProcessor->getEnv(); From e397e0f1473b8543d49a43de2d505154e997f5df Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Wed, 12 Jun 2019 08:51:06 -0500 Subject: [PATCH 24/59] MQE-1427: Support _CREDS in <magentoCLI> action and in Data - Removing "updateData", does NOT contain a <field>. --- dev/tests/unit/Resources/alteredDocumentation.txt | 1 + dev/tests/unit/Resources/basicDocumentation.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index 0684134f5..d69a38775 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -1,6 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. + ###testActionGroupObject **Description**: - alteredDescription diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 3bc16cbac..22e4b2a89 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -1,6 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. + ###testActionGroupObject **Description**: - someDescription From b90e9e2627220470a7d4d0b220c427d52d146f75 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Wed, 12 Jun 2019 08:51:06 -0500 Subject: [PATCH 25/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Correct unit test text. --- dev/tests/unit/Resources/alteredDocumentation.txt | 1 + dev/tests/unit/Resources/basicDocumentation.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index 0684134f5..d69a38775 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -1,6 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. + ###testActionGroupObject **Description**: - alteredDescription diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 3bc16cbac..22e4b2a89 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -1,6 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. + ###testActionGroupObject **Description**: - someDescription From fcecdd4f60595567d9c38ad58b45b47c57759412 Mon Sep 17 00:00:00 2001 From: John S <john00ivy@gmail.com> Date: Wed, 12 Jun 2019 09:21:45 -0500 Subject: [PATCH 26/59] MQE-1580: Remove the "page" attribute from the Action Group annotations node. - Fixed the Unit Test finally. --- dev/tests/unit/Resources/alteredDocumentation.txt | 2 +- dev/tests/unit/Resources/basicDocumentation.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt index d69a38775..228683db4 100644 --- a/dev/tests/unit/Resources/alteredDocumentation.txt +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -1,7 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. - +--- ###testActionGroupObject **Description**: - alteredDescription diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt index 22e4b2a89..cdc67a491 100644 --- a/dev/tests/unit/Resources/basicDocumentation.txt +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -1,7 +1,7 @@ #Action Group Information This documentation contains a list of all Action Groups. - +--- ###testActionGroupObject **Description**: - someDescription From daf51e091a496c299706fee6404592504b7c4051 Mon Sep 17 00:00:00 2001 From: Alex Kolesnyk <kolesnyk@adobe.com> Date: Wed, 12 Jun 2019 16:46:49 -0500 Subject: [PATCH 27/59] MQE-1234: Allow XML Parser to read XML comment into comment action - do not humanize comment actions --- .../Allure/Adapter/MagentoAllureAdapter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 81a6fe3ba..68dbe09ae 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -132,7 +132,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) { + if (strpos($stepEvent->getStep()->getAction(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false + || $stepEvent->getStep() instanceof Comment + ) { $stepAction = $stepEvent->getStep()->getAction(); } else { $stepAction = $stepEvent->getStep()->getHumanizedActionWithoutArguments(); From 94d0c15deb6c4922a82fbe202a54186e66c27a9f Mon Sep 17 00:00:00 2001 From: Soumya Unnikrishnan <sunnikri@adobe.com> Date: Mon, 24 Jun 2019 13:09:18 -0500 Subject: [PATCH 28/59] MQE-1597: MFTF 2.4.0 and above has incompatible dependencies with msp/twofactorauth updated composer.json and .lock to fix packaging issues --- composer.json | 4 +- composer.lock | 175 ++++++++++---------------------------------------- 2 files changed, 37 insertions(+), 142 deletions(-) diff --git a/composer.json b/composer.json index d226371ea..126fa3101 100755 --- a/composer.json +++ b/composer.json @@ -14,7 +14,6 @@ "ext-curl": "*", "codeception/codeception": "~2.3.4 || ~2.4.0 ", "consolidation/robo": "^1.0.0", - "epfremme/swagger-php": "^2.0", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", @@ -36,6 +35,9 @@ "php-coveralls/php-coveralls": "^1.0", "symfony/stopwatch": "~3.4.6" }, + "suggest": { + "epfremme/swagger-php": "^2.0" + }, "autoload": { "files": ["src/Magento/FunctionalTestingFramework/_bootstrap.php"], "psr-4": { diff --git a/composer.lock b/composer.lock index c858ceff4..7cb40776e 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": "6b2b6a074f053fe28df2633e8bce095f", + "content-hash": "1937995160ceef8d4506d847291206f3", "packages": [ { "name": "allure-framework/allure-codeception", @@ -795,73 +795,6 @@ ], "time": "2017-02-24T16:22:25+00:00" }, - { - "name": "doctrine/collections", - "version": "v1.4.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", - "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2017-01-03T10:49:41+00:00" - }, { "name": "doctrine/instantiator", "version": "1.0.5", @@ -918,21 +851,24 @@ }, { "name": "doctrine/lexer", - "version": "v1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", "shasum": "" }, "require": { "php": ">=5.3.2" }, + "require-dev": { + "phpunit/phpunit": "^4.5" + }, "type": "library", "extra": { "branch-alias": { @@ -940,8 +876,8 @@ } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } }, "notification-url": "https://packagist.org/downloads/", @@ -962,59 +898,16 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ + "annotations", + "docblock", "lexer", - "parser" - ], - "time": "2014-09-09T13:34:57+00:00" - }, - { - "name": "epfremme/swagger-php", - "version": "v2.0.0", - "source": { - "type": "git", - "url": "https://github.com/epfremmer/swagger-php.git", - "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/epfremmer/swagger-php/zipball/eee28a442b7e6220391ec953d3c9b936354f23bc", - "reference": "eee28a442b7e6220391ec953d3c9b936354f23bc", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.2", - "doctrine/collections": "^1.3", - "jms/serializer": "^1.1", - "php": ">=5.5", - "phpoption/phpoption": "^1.1", - "symfony/yaml": "^2.7|^3.1" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "~4.8|~5.0", - "satooshi/php-coveralls": "^1.0" - }, - "type": "package", - "autoload": { - "psr-4": { - "Epfremme\\Swagger\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Edward Pfremmer", - "email": "epfremme@nerdery.com" - } + "parser", + "php" ], - "description": "Library for parsing swagger documentation into PHP entities for use in testing and code generation", - "time": "2016-09-26T17:24:17+00:00" + "time": "2019-06-08T11:03:04+00:00" }, { "name": "facebook/webdriver", @@ -1568,16 +1461,16 @@ }, { "name": "jms/serializer", - "version": "1.13.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "00863e1d55b411cc33ad3e1de09a4c8d3aae793c" + "reference": "ee96d57024af9a7716d56fcbe3aa94b3d030f3ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/00863e1d55b411cc33ad3e1de09a4c8d3aae793c", - "reference": "00863e1d55b411cc33ad3e1de09a4c8d3aae793c", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/ee96d57024af9a7716d56fcbe3aa94b3d030f3ca", + "reference": "ee96d57024af9a7716d56fcbe3aa94b3d030f3ca", "shasum": "" }, "require": { @@ -1617,7 +1510,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.13-dev" + "dev-1.x": "1.14-dev" } }, "autoload": { @@ -1648,7 +1541,7 @@ "serialization", "xml" ], - "time": "2018-07-25T13:58:54+00:00" + "time": "2019-04-17T08:12:16+00:00" }, { "name": "league/container", @@ -4083,16 +3976,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { @@ -4104,7 +3997,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-master": "1.11-dev" } }, "autoload": { @@ -4137,7 +4030,7 @@ "polyfill", "portable" ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2019-02-06T07:57:58+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -4308,16 +4201,16 @@ }, { "name": "symfony/yaml", - "version": "v3.4.18", + "version": "v3.4.28", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f" + "reference": "212a27b731e5bfb735679d1ffaac82bd6a1dc996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/640b6c27fed4066d64b64d5903a86043f4a4de7f", - "reference": "640b6c27fed4066d64b64d5903a86043f4a4de7f", + "url": "https://api.github.com/repos/symfony/yaml/zipball/212a27b731e5bfb735679d1ffaac82bd6a1dc996", + "reference": "212a27b731e5bfb735679d1ffaac82bd6a1dc996", "shasum": "" }, "require": { @@ -4363,7 +4256,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-10-02T16:33:53+00:00" + "time": "2019-03-25T07:48:46+00:00" }, { "name": "theseer/tokenizer", From 7818b9cc7ea4f4111714bfdadc4dbeaa9497486b Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Thu, 27 Jun 2019 13:35:43 -0500 Subject: [PATCH 29/59] MQE-1613: Add release to CHANGELOG.MD - Changelog updated - composer version bumped --- CHANGELOG.md | 9 +++++++++ bin/mftf | 2 +- composer.json | 2 +- composer.lock | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee0d665e5..72b6f857d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ Magento Functional Testing Framework Changelog ================================================ +2.4.2 +----- +* Traceability + * Test action `stepKey`s are now included in both console output and Allure report. + * XML Comments are now automatically converted into a `<comment>` action. + +### Fixes +* Moved `epfremme/swagger-php` dependency to `suggests` block due to a conflict with Magento extensions. + 2.4.1 ----- * Traceability diff --git a/bin/mftf b/bin/mftf index 207dab6ff..b026f33c1 100755 --- a/bin/mftf +++ b/bin/mftf @@ -29,7 +29,7 @@ try { try { $application = new Symfony\Component\Console\Application(); $application->setName('Magento Functional Testing Framework CLI'); - $application->setVersion('2.4.1'); + $application->setVersion('2.4.2'); /** @var \Magento\FunctionalTestingFramework\Console\CommandListInterface $commandList */ $commandList = new \Magento\FunctionalTestingFramework\Console\CommandList; foreach ($commandList->getCommands() as $command) { diff --git a/composer.json b/composer.json index 126fa3101..8af401526 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.4.1", + "version": "2.4.2", "license": "AGPL-3.0", "keywords": ["magento", "automation", "functional", "testing"], "config": { diff --git a/composer.lock b/composer.lock index 7cb40776e..ca4e287fc 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": "1937995160ceef8d4506d847291206f3", + "content-hash": "d5879be29cb6bbe70ce7e4a42828303a", "packages": [ { "name": "allure-framework/allure-codeception", From 09f81b67482406962bdbe8157e880b5df00ed1d5 Mon Sep 17 00:00:00 2001 From: John S <ivy00johns@users.noreply.github.com> Date: Fri, 28 Jun 2019 11:18:57 -0500 Subject: [PATCH 30/59] MQE-1427 - Support _CREDS in <magentoCLI> action and in Data (#368) - added support for _creds in magentoCLI and Data --- .../Test/Util/ActionMergeUtilTest.php | 121 +++++++++++++++++- .../Resources/ActionGroupUsingCreateData.txt | 4 +- .../ActionGroupWithDataOverrideTest.txt | 2 +- .../Resources/ActionGroupWithDataTest.txt | 2 +- .../ActionGroupWithNoDefaultTest.txt | 2 +- .../ActionGroupWithPersistedData.txt | 4 +- .../ActionGroupWithStepKeyReferences.txt | 5 +- .../ActionGroupWithTopLevelPersistedData.txt | 2 +- .../ArgumentWithSameNameAsElement.txt | 2 +- .../verification/Resources/AssertTest.txt | 4 +- .../Resources/BasicActionGroupTest.txt | 2 +- .../Resources/BasicFunctionalTest.txt | 1 - .../Resources/DataActionsTest.txt | 4 +- .../Resources/DataReplacementTest.txt | 1 - .../Resources/ExtendParentDataTest.txt | 2 +- .../Resources/ExtendedParameterArrayTest.txt | 2 +- .../Resources/HookActionsTest.txt | 6 +- .../Resources/LocatorFunctionTest.txt | 2 +- .../Resources/MergedActionGroupTest.txt | 2 +- .../Resources/MultipleActionGroupsTest.txt | 2 +- .../Resources/PageReplacementTest.txt | 2 +- .../Resources/ParameterArrayTest.txt | 2 +- .../Resources/PersistedReplacementTest.txt | 4 +- .../PersistenceActionGroupAppendingTest.txt | 4 +- .../Resources/PersistenceCustomFieldsTest.txt | 10 -- .../Resources/SectionReplacementTest.txt | 2 +- .../Test/SecretCredentialDataTest.xml | 27 ++++ .../Tests/SecretCredentialDataTest.php | 75 +++++++++++ .../Handlers/CredentialStore.php | 18 +++ .../Handlers/PersistedObjectHandler.php | 4 + .../Module/MagentoWebDriver.php | 20 ++- .../Test/Objects/ActionObject.php | 2 +- .../Test/Util/ActionMergeUtil.php | 34 +++-- .../Util/TestGenerator.php | 11 +- 34 files changed, 322 insertions(+), 65 deletions(-) create mode 100644 dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml create mode 100644 dev/tests/verification/Tests/SecretCredentialDataTest.php diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php index 0f367c226..7917d663b 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionMergeUtilTest.php @@ -8,6 +8,8 @@ use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; +use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; @@ -100,7 +102,7 @@ public function testResolveActionStepEntityData() $dataFieldName = 'myfield'; $dataFieldValue = 'myValue'; $userInputKey = "userInput"; - $userinputValue = "{{" . "${dataObjectName}.${dataFieldName}}}"; + $userInputValue = "{{" . "${dataObjectName}.${dataFieldName}}}"; $actionName = "myAction"; $actionType = "myCustomType"; @@ -113,10 +115,10 @@ public function testResolveActionStepEntityData() AspectMock::double(DataObjectHandler::class, ['getInstance' => $mockDOHInstance]); // Create test object and action object - $actionAttributes = [$userInputKey => $userinputValue]; + $actionAttributes = [$userInputKey => $userInputValue]; $actions[$actionName] = new ActionObject($actionName, $actionType, $actionAttributes); - $this->assertEquals($userinputValue, $actions[$actionName]->getCustomActionAttributes()[$userInputKey]); + $this->assertEquals($userInputValue, $actions[$actionName]->getCustomActionAttributes()[$userInputKey]); $mergeUtil = new ActionMergeUtil("test", "TestCase"); $resolvedActions = $mergeUtil->resolveActionSteps($actions); @@ -127,8 +129,14 @@ public function testResolveActionStepEntityData() /** * Verify that an XmlException is thrown when an action references a non-existant action. * + * @throws TestReferenceException + * @throws XmlException * @return void */ + /** + * @throws TestReferenceException + * @throws XmlException + */ public function testNoActionException() { $actionObjects = []; @@ -151,6 +159,8 @@ public function testNoActionException() /** * Verify that a <waitForPageLoad> action is added after actions that have a wait (timeout property). * + * @throws TestReferenceException + * @throws XmlException * @return void */ public function testInsertWait() @@ -173,6 +183,111 @@ public function testInsertWait() $this->assertEquals($expected, $actual); } + /** + * Verify that a <fillField> action is replaced by <fillSecretField> when secret _CREDS are referenced. + * + * @throws TestReferenceException + * @throws XmlException + */ + public function testValidFillFieldSecretFunction() + { + $actionObjectOne = new ActionObject( + 'actionKey1', + 'fillField', + ['userInput' => '{{_CREDS.username}}'] + ); + $actionObject = [$actionObjectOne]; + + $actionMergeUtil = new ActionMergeUtil('actionMergeUtilTest', 'TestCase'); + + $result = $actionMergeUtil->resolveActionSteps($actionObject); + + $expectedValue = new ActionObject( + 'actionKey1', + 'fillSecretField', + ['userInput' => '{{_CREDS.username}}'] + ); + $this->assertEquals($expectedValue, $result['actionKey1']); + } + + /** + * Verify that a <magentoCLI> action uses <magentoCLI> when secret _CREDS are referenced. + * + * @throws TestReferenceException + * @throws XmlException + */ + public function testValidMagentoCLISecretFunction() + { + $actionObjectOne = new ActionObject( + 'actionKey1', + 'magentoCLI', + ['command' => 'config:set cms/wysiwyg/enabled {{_CREDS.payment_authorizenet_login}}'] + ); + $actionObject = [$actionObjectOne]; + + $actionMergeUtil = new ActionMergeUtil('actionMergeUtilTest', 'TestCase'); + + $result = $actionMergeUtil->resolveActionSteps($actionObject); + + $expectedValue = new ActionObject( + 'actionKey1', + 'magentoCLISecret', + ['command' => 'config:set cms/wysiwyg/enabled {{_CREDS.payment_authorizenet_login}}'] + ); + $this->assertEquals($expectedValue, $result['actionKey1']); + } + + /** + * Verify that a <field> override in a <createData> action uses <field> when secret _CREDS are referenced. + * + * @throws TestReferenceException + * @throws XmlException + */ + public function testValidCreateDataSecretFunction() + { + $actionObjectOne = new ActionObject( + 'actionKey1', + 'field', + ['value' => '{{_CREDS.payment_authorizenet_login}}'] + ); + $actionObject = [$actionObjectOne]; + + $actionMergeUtil = new ActionMergeUtil('actionMergeUtilTest', 'TestCase'); + + $result = $actionMergeUtil->resolveActionSteps($actionObject); + + $expectedValue = new ActionObject( + 'actionKey1', + 'field', + ['value' => '{{_CREDS.payment_authorizenet_login}}'] + ); + $this->assertEquals($expectedValue, $result['actionKey1']); + } + + /** + * Verify that a <click> action throws an exception when secret _CREDS are referenced. + * + * @throws TestReferenceException + * @throws XmlException + */ + public function testInvalidSecretFunctions() + { + $this->expectException(TestReferenceException::class); + $this->expectExceptionMessage( + 'You cannot reference secret data outside of the fillField, magentoCLI and createData actions' + ); + + $actionObjectOne = new ActionObject( + 'actionKey1', + 'click', + ['userInput' => '{{_CREDS.username}}'] + ); + $actionObject = [$actionObjectOne]; + + $actionMergeUtil = new ActionMergeUtil('actionMergeUtilTest', 'TestCase'); + $actionMergeUtil->resolveActionSteps($actionObject); + } + /** * After class functionality * @return void diff --git a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt index 6831b0914..97369c6ea 100644 --- a/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt +++ b/dev/tests/verification/Resources/ActionGroupUsingCreateData.txt @@ -31,7 +31,7 @@ class ActionGroupUsingCreateDataCest "hook", "ApiCategory", [], - null + [] ); $I->comment("[createConfigProductKey1] create 'ApiConfigurableProduct' entity"); @@ -40,7 +40,7 @@ class ActionGroupUsingCreateDataCest "hook", "ApiConfigurableProduct", ["createCategoryKey1"], - null + [] ); $I->comment("Exiting Action Group [Key1] actionGroupWithCreateData"); diff --git a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt index 3785b4dd6..f9984944a 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataOverrideTest.txt @@ -31,7 +31,7 @@ class ActionGroupWithDataOverrideTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt index 3e812cdd0..79bda5f1b 100644 --- a/dev/tests/verification/Resources/ActionGroupWithDataTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithDataTest.txt @@ -31,7 +31,7 @@ class ActionGroupWithDataTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt index 955596301..b24362028 100644 --- a/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt +++ b/dev/tests/verification/Resources/ActionGroupWithNoDefaultTest.txt @@ -31,7 +31,7 @@ class ActionGroupWithNoDefaultTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt index aba5c5796..f774269ea 100644 --- a/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithPersistedData.txt @@ -31,7 +31,7 @@ class ActionGroupWithPersistedDataCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); @@ -78,7 +78,7 @@ class ActionGroupWithPersistedDataCest "test", "DefaultPerson", [], - null + [] ); $I->comment("Entering Action Group [actionGroupWithPersistedData1] FunctionalActionGroupWithData"); diff --git a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt index 336cd6610..d83447d03 100644 --- a/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt +++ b/dev/tests/verification/Resources/ActionGroupWithStepKeyReferences.txt @@ -34,7 +34,7 @@ class ActionGroupWithStepKeyReferencesCest "test", "simpleData", [], - null + [] ); $grabTextDataActionGroup = $I->grabTextFrom(".class"); // stepKey: grabTextDataActionGroup @@ -46,7 +46,6 @@ class ActionGroupWithStepKeyReferencesCest $action3ActionGroup = $I->executeJS($action3ActionGroup); // stepKey: action3ActionGroup $action4ActionGroup = $I->magentoCLI($action4ActionGroup, "\"stuffHere\""); // stepKey: action4ActionGroup $I->comment($action4ActionGroup); - $date = new \DateTime(); $date->setTimestamp(strtotime("{$action5}")); $date->setTimezone(new \DateTimeZone("America/Los_Angeles")); @@ -82,7 +81,7 @@ class ActionGroupWithStepKeyReferencesCest "test", "{$action10}", [], - null + [] ); $action11ActionGroup = $I->grabAttributeFrom($action11ActionGroup, "someInput"); // stepKey: action11ActionGroup diff --git a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt index fffaebbfd..c579d165e 100644 --- a/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt +++ b/dev/tests/verification/Resources/ActionGroupWithTopLevelPersistedData.txt @@ -31,7 +31,7 @@ class ActionGroupWithTopLevelPersistedDataCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt index 4ccc2d169..5b9f838a4 100644 --- a/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt +++ b/dev/tests/verification/Resources/ArgumentWithSameNameAsElement.txt @@ -31,7 +31,7 @@ class ArgumentWithSameNameAsElementCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/AssertTest.txt b/dev/tests/verification/Resources/AssertTest.txt index 697bc3d21..1f8eef56e 100644 --- a/dev/tests/verification/Resources/AssertTest.txt +++ b/dev/tests/verification/Resources/AssertTest.txt @@ -30,7 +30,7 @@ class AssertTestCest "hook", "ReplacementPerson", [], - null + [] ); } @@ -50,7 +50,7 @@ class AssertTestCest "test", "UniquePerson", [], - null + [] ); $grabTextFrom1 = $I->grabTextFrom(".copyright>span"); // stepKey: grabTextFrom1 diff --git a/dev/tests/verification/Resources/BasicActionGroupTest.txt b/dev/tests/verification/Resources/BasicActionGroupTest.txt index 17e5e2bdf..c6b3cec81 100644 --- a/dev/tests/verification/Resources/BasicActionGroupTest.txt +++ b/dev/tests/verification/Resources/BasicActionGroupTest.txt @@ -31,7 +31,7 @@ class BasicActionGroupTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index 3cb373a4c..fc4284005 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -121,7 +121,6 @@ class BasicFunctionalTestCest $grabValueFromKey1 = $I->grabValueFrom(".functionalTestSelector"); // stepKey: grabValueFromKey1 $magentoCli1 = $I->magentoCLI("maintenance:enable", "\"stuffHere\""); // stepKey: magentoCli1 $I->comment($magentoCli1); - $I->makeScreenshot("screenShotInput"); // stepKey: makeScreenshotKey1 $I->maximizeWindow(); // stepKey: maximizeWindowKey1 $I->moveBack(); // stepKey: moveBackKey1 diff --git a/dev/tests/verification/Resources/DataActionsTest.txt b/dev/tests/verification/Resources/DataActionsTest.txt index 5d1ee9e00..728bef2e7 100644 --- a/dev/tests/verification/Resources/DataActionsTest.txt +++ b/dev/tests/verification/Resources/DataActionsTest.txt @@ -30,7 +30,7 @@ class DataActionsTestCest "hook", "entity", [], - null + [] ); $I->comment("[updateInBefore] update 'createdInBefore' entity to 'entity'"); @@ -64,7 +64,7 @@ class DataActionsTestCest "test", "entity", [], - null + [] ); $I->comment("[updateInTest] update 'createdInTest' entity to 'entity'"); diff --git a/dev/tests/verification/Resources/DataReplacementTest.txt b/dev/tests/verification/Resources/DataReplacementTest.txt index 211dfd5a1..4eb305e32 100644 --- a/dev/tests/verification/Resources/DataReplacementTest.txt +++ b/dev/tests/verification/Resources/DataReplacementTest.txt @@ -53,6 +53,5 @@ class DataReplacementTestCest $I->fillField(".selector", "0"); // stepKey: insertZero $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); // stepKey: insertCommand $I->comment($insertCommand); - } } diff --git a/dev/tests/verification/Resources/ExtendParentDataTest.txt b/dev/tests/verification/Resources/ExtendParentDataTest.txt index a80f3cf19..a91c2f464 100644 --- a/dev/tests/verification/Resources/ExtendParentDataTest.txt +++ b/dev/tests/verification/Resources/ExtendParentDataTest.txt @@ -33,7 +33,7 @@ class ExtendParentDataTestCest "test", "extendParentData", [], - null + [] ); $I->searchAndMultiSelectOption("#selector", ["otherName"]); // stepKey: getName diff --git a/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt b/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt index 41bea9d6f..21212ba1a 100644 --- a/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt +++ b/dev/tests/verification/Resources/ExtendedParameterArrayTest.txt @@ -33,7 +33,7 @@ class ExtendParentDataTestCest "test", "extendParentData", [], - null + [] ); $I->searchAndMultiSelectOption("#selector", ["otherName"]); $I->searchAndMultiSelectOption("#selector", ["extendName"]); diff --git a/dev/tests/verification/Resources/HookActionsTest.txt b/dev/tests/verification/Resources/HookActionsTest.txt index 74a49eca3..3068e6ac1 100644 --- a/dev/tests/verification/Resources/HookActionsTest.txt +++ b/dev/tests/verification/Resources/HookActionsTest.txt @@ -30,7 +30,7 @@ class HookActionsTestCest "hook", "sampleCreatedEntity", [], - null + [] ); $I->comment("[sampleDeleteBefore] delete entity 'sampleCreateBefore'"); @@ -45,7 +45,7 @@ class HookActionsTestCest "hook", "sampleCreatedEntity", [], - null + [] ); } @@ -62,7 +62,7 @@ class HookActionsTestCest "hook", "sampleCreatedEntity", [], - null + [] ); $I->comment("[sampleDeleteAfter] delete entity 'sampleCreateForAfter'"); diff --git a/dev/tests/verification/Resources/LocatorFunctionTest.txt b/dev/tests/verification/Resources/LocatorFunctionTest.txt index 4c96f100b..ad9a1a9e7 100644 --- a/dev/tests/verification/Resources/LocatorFunctionTest.txt +++ b/dev/tests/verification/Resources/LocatorFunctionTest.txt @@ -33,7 +33,7 @@ class LocatorFunctionTestCest "test", "ReplacementPerson", [], - null + [] ); $I->click(Locator::contains("'label'", "'Name'")); // stepKey: SimpleLocator diff --git a/dev/tests/verification/Resources/MergedActionGroupTest.txt b/dev/tests/verification/Resources/MergedActionGroupTest.txt index 03ab1287b..9bd6c0ded 100644 --- a/dev/tests/verification/Resources/MergedActionGroupTest.txt +++ b/dev/tests/verification/Resources/MergedActionGroupTest.txt @@ -31,7 +31,7 @@ class MergedActionGroupTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt index e0796ae39..4f12b2f07 100644 --- a/dev/tests/verification/Resources/MultipleActionGroupsTest.txt +++ b/dev/tests/verification/Resources/MultipleActionGroupsTest.txt @@ -31,7 +31,7 @@ class MultipleActionGroupsTestCest "hook", "ReplacementPerson", [], - null + [] ); $I->comment("Entering Action Group [beforeGroup] FunctionalActionGroup"); diff --git a/dev/tests/verification/Resources/PageReplacementTest.txt b/dev/tests/verification/Resources/PageReplacementTest.txt index 6b27b55b1..c7bede23e 100644 --- a/dev/tests/verification/Resources/PageReplacementTest.txt +++ b/dev/tests/verification/Resources/PageReplacementTest.txt @@ -33,7 +33,7 @@ class PageReplacementTestCest "test", "simpleData", [], - null + [] ); $I->amOnPage("/page.html"); // stepKey: noParamPage diff --git a/dev/tests/verification/Resources/ParameterArrayTest.txt b/dev/tests/verification/Resources/ParameterArrayTest.txt index 8f49ca05c..8e278b826 100644 --- a/dev/tests/verification/Resources/ParameterArrayTest.txt +++ b/dev/tests/verification/Resources/ParameterArrayTest.txt @@ -33,7 +33,7 @@ class ParameterArrayTestCest "test", "simpleParamData", [], - null + [] ); $I->searchAndMultiSelectOption("#selector", ["name"]); // stepKey: xmlSimpleReplace diff --git a/dev/tests/verification/Resources/PersistedReplacementTest.txt b/dev/tests/verification/Resources/PersistedReplacementTest.txt index 2c5d99bc2..6058e34f5 100644 --- a/dev/tests/verification/Resources/PersistedReplacementTest.txt +++ b/dev/tests/verification/Resources/PersistedReplacementTest.txt @@ -30,7 +30,7 @@ class PersistedReplacementTestCest "hook", "ReplacementPerson", [], - null + [] ); } @@ -50,7 +50,7 @@ class PersistedReplacementTestCest "test", "simpleData", [], - null + [] ); $I->fillField("#selector", "StringBefore " . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test') . " StringAfter"); // stepKey: inputReplace diff --git a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt index af6507abc..bc5e16294 100644 --- a/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt +++ b/dev/tests/verification/Resources/PersistenceActionGroupAppendingTest.txt @@ -31,7 +31,7 @@ class PersistenceActionGroupAppendingTestCest "hook", "entity", [], - null + [] ); $I->comment("[updateDataACTIONGROUPBEFORE] update 'createDataACTIONGROUPBEFORE' entity to 'newEntity'"); @@ -77,7 +77,7 @@ class PersistenceActionGroupAppendingTestCest "test", "entity", [], - null + [] ); $I->comment("[updateDataACTIONGROUP] update 'createDataACTIONGROUP' entity to 'newEntity'"); diff --git a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt index 68ded6711..4853619e1 100644 --- a/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt +++ b/dev/tests/verification/Resources/PersistenceCustomFieldsTest.txt @@ -25,9 +25,7 @@ class PersistenceCustomFieldsTestCest public function _before(AcceptanceTester $I) { $createData1Fields['firstname'] = "Mac"; - $createData1Fields['lastname'] = "Doe"; - $I->comment("[createData1] create 'DefaultPerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData1", @@ -38,7 +36,6 @@ class PersistenceCustomFieldsTestCest ); $createData2Fields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createData1', 'firstname', 'hook'); - $I->comment("[createData2] create 'uniqueData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createData2", @@ -60,9 +57,7 @@ class PersistenceCustomFieldsTestCest public function PersistenceCustomFieldsTest(AcceptanceTester $I) { $createdDataFields['favoriteIndex'] = "1"; - $createdDataFields['middlename'] = "Kovacs"; - $I->comment("[createdData] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData", @@ -73,9 +68,7 @@ class PersistenceCustomFieldsTestCest ); $createdData3Fields['firstname'] = "Takeshi"; - $createdData3Fields['lastname'] = "Kovacs"; - $I->comment("[createdData3] create 'UniquePerson' entity"); PersistedObjectHandler::getInstance()->createEntity( "createdData3", @@ -87,7 +80,6 @@ class PersistenceCustomFieldsTestCest $I->comment("Entering Action Group [createdAG] PersistenceActionGroup"); $createDataAG1CreatedAGFields['firstname'] = "string1"; - $I->comment("[createDataAG1CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG1CreatedAG", @@ -98,7 +90,6 @@ class PersistenceCustomFieldsTestCest ); $createDataAG2CreatedAGFields['firstname'] = "Jane"; - $I->comment("[createDataAG2CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG2CreatedAG", @@ -109,7 +100,6 @@ class PersistenceCustomFieldsTestCest ); $createDataAG3CreatedAGFields['firstname'] = PersistedObjectHandler::getInstance()->retrieveEntityField('createdData3', 'firstname', 'test'); - $I->comment("[createDataAG3CreatedAG] create 'simpleData' entity"); PersistedObjectHandler::getInstance()->createEntity( "createDataAG3CreatedAG", diff --git a/dev/tests/verification/Resources/SectionReplacementTest.txt b/dev/tests/verification/Resources/SectionReplacementTest.txt index a237faf38..aab4a87a0 100644 --- a/dev/tests/verification/Resources/SectionReplacementTest.txt +++ b/dev/tests/verification/Resources/SectionReplacementTest.txt @@ -52,7 +52,7 @@ class SectionReplacementTestCest "test", "simpleData", [], - null + [] ); $I->click("#element ." . PersistedObjectHandler::getInstance()->retrieveEntityField('createdData', 'firstname', 'test')); // stepKey: selectorReplaceOneParamPersisted diff --git a/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml b/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml new file mode 100644 index 000000000..4044a86e3 --- /dev/null +++ b/dev/tests/verification/TestModule/Test/SecretCredentialDataTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + /** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + <test name="secretCredentialDataTest"> + <createData entity="_defaultProduct" stepKey="createProductWithFieldOverridesUsingHardcodedData1"> + <field key="qty">123</field> + <field key="price">12.34</field> + </createData> + <createData entity="_defaultProduct" stepKey="createProductWithFieldOverridesUsingSecretCredData1"> + <field key="qty">{{_CREDS.payment_authorizenet_trans_key}}</field> + <field key="price">{{_CREDS.carriers_dhl_account_eu}}</field> + </createData> + + <fillField selector="{{AdminLoginFormSection.username}}" userInput="Hardcoded" stepKey="fillFieldUsingHardCodedData1"/> + <fillField selector="{{AdminLoginFormSection.username}}" userInput="{{_CREDS.carriers_dhl_id_eu}}" stepKey="fillFieldUsingSecretCredData1"/> + + <magentoCLI command="config:set cms/wysiwyg/enabled 0" stepKey="magentoCliUsingHardcodedData1"/> + <magentoCLI command="config:set cms/wysiwyg/enabled {{_CREDS.payment_authorizenet_login}}" stepKey="magentoCliUsingSecretCredData1"/> + </test> +</tests> diff --git a/dev/tests/verification/Tests/SecretCredentialDataTest.php b/dev/tests/verification/Tests/SecretCredentialDataTest.php new file mode 100644 index 000000000..46391feee --- /dev/null +++ b/dev/tests/verification/Tests/SecretCredentialDataTest.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +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; +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; + +/** + */ +class SecretCredentialDataTestCest +{ + /** + * @Features({"AdminNotification"}) + * @Parameter(name = "AcceptanceTester", value="$I") + * @param AcceptanceTester $I + * @return void + * @throws \Exception + */ + public function secretCredentialDataTest(AcceptanceTester $I) + { + $createProductWithFieldOverridesUsingHardcodedData1Fields['qty'] = "123"; + + $createProductWithFieldOverridesUsingHardcodedData1Fields['price'] = "12.34"; + + $I->comment("[createProductWithFieldOverridesUsingHardcodedData1] create '_defaultProduct' entity"); + PersistedObjectHandler::getInstance()->createEntity( + "createProductWithFieldOverridesUsingHardcodedData1", + "test", + "_defaultProduct", + [], + $createProductWithFieldOverridesUsingHardcodedData1Fields + ); + + $createProductWithFieldOverridesUsingSecretCredData1Fields['qty'] = + CredentialStore::getInstance()->getSecret("payment_authorizenet_trans_key"); + + $createProductWithFieldOverridesUsingSecretCredData1Fields['price'] = + CredentialStore::getInstance()->getSecret("carriers_dhl_account_eu"); + + $I->comment("[createProductWithFieldOverridesUsingSecretCredData1] create '_defaultProduct' entity"); + PersistedObjectHandler::getInstance()->createEntity( + "createProductWithFieldOverridesUsingSecretCredData1", + "test", + "_defaultProduct", + [], + $createProductWithFieldOverridesUsingSecretCredData1Fields + ); + + $I->fillField("#username", "Hardcoded"); // stepKey: fillFieldUsingHardCodedData1 + $I->fillSecretField("#username", CredentialStore::getInstance()->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")); + // stepKey: magentoCliUsingSecretCredData1 + $I->comment($magentoCliUsingSecretCredData1); + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index 3f635a040..a83540683 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -156,4 +156,22 @@ public function decryptSecretValue($value) { return openssl_decrypt($value, self::ENCRYPTION_ALGO, $this->encodedKey, 0, $this->iv); } + + /** + * Takes a string that contains encrypted data at runtime and decrypts each value. + * + * @param string $string + * @return mixed + */ + public function decryptAllSecretsInString($string) + { + $newString = $string; + foreach ($this->credentials as $name => $secretValue) { + if (strpos($newString, $secretValue) !== false) { + $decryptedValue = $this->decryptSecretValue($secretValue); + $newString = str_replace($secretValue, $decryptedValue, $newString); + } + } + return $newString; + } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php index 64bb5f0a0..cc35bbc52 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/PersistedObjectHandler.php @@ -84,6 +84,10 @@ public function createEntity( foreach ($dependentObjectKeys as $objectKey) { $retrievedDependentObjects[] = $this->retrieveEntity($objectKey, $scope); } + + foreach ($overrideFields as $index => $field) { + $overrideFields[$index] = CredentialStore::getInstance()->decryptAllSecretsInString($field); + } $retrievedEntity = DataObjectHandler::getInstance()->getObject($entity); $persistedObject = new DataPersistenceHandler( diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 93e6a5968..d268e23b4 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -620,7 +620,7 @@ public function dragAndDrop($source, $target, $xOffset = null, $yOffset = null) } /** - * Function used to fill sensitive crednetials with user data, data is decrypted immediately prior to fill to avoid + * Function used to fill sensitive credentials with user data, data is decrypted immediately prior to fill to avoid * exposure in console or log. * * @param string $field @@ -636,6 +636,24 @@ public function fillSecretField($field, $value) $this->fillField($field, $decryptedValue); } + /** + * Function used to create data that contains sensitive credentials in a <createData> <field> override. + * The data is decrypted immediately prior to data creation to avoid exposure in console or log. + * + * @param string $command + * @param null $arguments + * @throws TestFrameworkException + * @return string + */ + public function magentoCLISecret($command, $arguments = null) + { + // to protect any secrets from being printed to console the values are executed only at the webdriver level as a + // decrypted value + + $decryptedCommand = CredentialStore::getInstance()->decryptAllSecretsInString($command); + return $this->magentoCLI($decryptedCommand, $arguments); + } + /** * Override for _failed method in Codeception method. Adds png and html attachments to allure report * following parent execution of test failure processing. diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index 19bd58721..dd7c20b18 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -154,7 +154,7 @@ public function __construct( $this->linkedAction = $linkedAction; $this->actionOrigin = $actionOrigin; - if ($order == ActionObject::MERGE_ACTION_ORDER_AFTER) { + if ($order === ActionObject::MERGE_ACTION_ORDER_AFTER) { $this->orderOffset = 1; } } diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index 65fe7c857..2a939a8c7 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -29,6 +29,8 @@ class ActionMergeUtil const DEFAULT_SKIP_ON_ORDER = 'before'; const DEFAULT_SKIP_OFF_ORDER = 'after'; const DEFAULT_WAIT_ORDER = 'after'; + const APPROVED_ACTIONS = ['fillField', 'magentoCLI', 'field']; + const SECRET_MAPPING = ['fillField' => 'fillSecretField', 'magentoCLI' => 'magentoCLISecret']; /** * Array holding final resulting steps @@ -95,7 +97,7 @@ public function resolveActionSteps($parsedSteps, $skipActionGroupResolution = fa /** * Takes an array of actions and resolves any references to secret fields. The function then validates whether the - * refernece is valid and replaces the function name accordingly to hide arguments at runtime. + * reference is valid and replaces the function name accordingly to hide arguments at runtime. * * @param ActionObject[] $resolvedActions * @return ActionObject[] @@ -106,22 +108,28 @@ private function resolveSecretFieldAccess($resolvedActions) $actions = []; foreach ($resolvedActions as $resolvedAction) { $action = $resolvedAction; - $hasSecretRef = $this->actionAttributeContainsSecretRef($resolvedAction->getCustomActionAttributes()); + $actionHasSecretRef = $this->actionAttributeContainsSecretRef($resolvedAction->getCustomActionAttributes()); + $actionType = $resolvedAction->getType(); - if ($resolvedAction->getType() !== 'fillField' && $hasSecretRef) { - throw new TestReferenceException("You cannot reference secret data outside of fill field actions"); + if ($actionHasSecretRef && !(in_array($actionType, self::APPROVED_ACTIONS))) { + throw new TestReferenceException("You cannot reference secret data outside " . + "of the fillField, magentoCLI and createData actions"); } - if ($resolvedAction->getType() === 'fillField' && $hasSecretRef) { - $action = new ActionObject( - $action->getStepKey(), - 'fillSecretField', - $action->getCustomActionAttributes(), - $action->getLinkedAction(), - $action->getActionOrigin() - ); + // Do NOT remap actions that don't need it. + if (isset(self::SECRET_MAPPING[$actionType]) && $actionHasSecretRef) { + $actionType = self::SECRET_MAPPING[$actionType]; } + $action = new ActionObject( + $action->getStepKey(), + $actionType, + $action->getCustomActionAttributes(), + $action->getLinkedAction(), + $action->getOrderOffset(), + $action->getActionOrigin() + ); + $actions[$action->getStepKey()] = $action; } @@ -261,7 +269,7 @@ private function insertReadinessSkips() * * @param array $parsedSteps * @return void - * @throws XmlException + * @throws TestReferenceException */ private function sortActions($parsedSteps) { diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 9e878277e..d07c5e1e0 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -755,7 +755,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato if (count($customEntityFields) > 1) { $createEntityFunctionCall .= ",\n\t\t\t\${$stepKey}Fields"; } else { - $createEntityFunctionCall .= ",\n\t\t\tnull"; + $createEntityFunctionCall .= ",\n\t\t\t[]"; } if ($storeCode !== null) { $createEntityFunctionCall .= ",\n\t\t\t\"{$storeCode}\""; @@ -1266,6 +1266,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato ); break; case "magentoCLI": + case "magentoCLISecret": $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, @@ -1275,7 +1276,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato ); $testSteps .= sprintf(self::STEP_KEY_ANNOTATION, $stepKey) . PHP_EOL; $testSteps .= sprintf( - "\t\t$%s->comment(\$%s);\n", + "\t\t$%s->comment(\$%s);", $actor, $stepKey ); @@ -1287,7 +1288,11 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $actionObject->getActionOrigin() )[0]; $argRef = "\t\t\$"; - $argRef .= str_replace(ucfirst($fieldKey), "", $stepKey) . "Fields['{$fieldKey}'] = ${input};\n"; + + $input = $this->resolveAllRuntimeReferences([$input])[0]; + $argRef .= str_replace(ucfirst($fieldKey), "", $stepKey) . + "Fields['{$fieldKey}'] = ${input};"; + $testSteps .= $argRef; break; case "generateDate": From 6a7a8d87b2cb26a15d6fbc649f53f5f8dae9e0be Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Fri, 28 Jun 2019 11:41:33 -0500 Subject: [PATCH 31/59] MQE-1510 - fix to command.php --- etc/config/command.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/etc/config/command.php b/etc/config/command.php index 047af324a..9de9e31c7 100644 --- a/etc/config/command.php +++ b/etc/config/command.php @@ -11,9 +11,9 @@ $magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER); $tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class); - $tokenPassedIn = urldecode($_POST['token']); - $command = urldecode($_POST['command']); - $arguments = urldecode($_POST['arguments']); + $tokenPassedIn = urldecode($_POST['token'] ?? ""); + $command = urldecode($_POST['command'] ?? ""); + $arguments = urldecode($_POST['arguments'] ?? ""); // Token returned will be null if the token we passed in is invalid $tokenFromMagento = $tokenModel->loadByToken($tokenPassedIn)->getToken(); @@ -22,7 +22,12 @@ $magentoBinary = $php . ' -f ../../../../bin/magento'; $valid = validateCommand($magentoBinary, $command); if ($valid) { - $process = new Symfony\Component\Process\Process($magentoBinary . " $command" . " $arguments"); + // Turn string into array for symfony escaping + $commandParts = array_filter(explode(" ", $command)); + $argumentParts = array_filter(explode(" ", $arguments)); + $magentoBinaryParts = array_filter(explode(" ", $magentoBinary)); + $commandArray = array_merge($magentoBinaryParts, $commandParts); + $process = new Symfony\Component\Process\Process($commandArray); $process->setIdleTimeout(60); $process->setTimeout(0); $idleTimeout = false; From 0232087bd810d2fea79348aba23ea047131a0659 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Thu, 11 Jul 2019 13:58:28 -0500 Subject: [PATCH 32/59] MQE-1622: MFTF Console Printer does not correctly consider --steps - Added constructor to Console class --- .../Codeception/Subscriber/Console.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php index 8c56e7733..6e61189bc 100644 --- a/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php +++ b/src/Magento/FunctionalTestingFramework/Codeception/Subscriber/Console.php @@ -31,6 +31,20 @@ class Console extends \Codeception\Subscriber\Console */ private $actionGroupStepKey = null; + /** + * 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. + * + * @param array $extensionOptions + * @param array $options + * + * @SuppressWarnings(PHPMD) + */ + public function __construct($extensionOptions = [], $options = []) + { + parent::__construct($options); + } + /** * Printing stepKey in before step action. * From e9647eb77424a25824c8fba292bf46d2bb28819d Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 16 Jul 2019 10:07:18 -0500 Subject: [PATCH 33/59] MQE-1623: Add selector best practices to devdocs --- docs/selectors.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docs/selectors.md diff --git a/docs/selectors.md b/docs/selectors.md new file mode 100644 index 000000000..ea904e3ea --- /dev/null +++ b/docs/selectors.md @@ -0,0 +1,25 @@ +# Selectors + +The tips and tricks below will help you to write high quality selectors. + +### Selectors SHOULD be written in CSS instead of Xpath whenever possible. + +### Xpath selectors SHOULD NOT use `@attribute="foo"` instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any attribute such as `@text` or `@class` for example. + +### CSS and Xpath selectors SHOULD be implemented in their most simple form. + +* <span class="color:green">GOOD:</span> `#foo` +* <span class="color:red">BAD:</span> `button[contains(@id, "foo")]` + +### CSS and Xpath selectors SHOULD avoid making use of hardcoded indices. Instead you SHOULD parameterize the selector. + +* <span class="color:green">GOOD:</span> `.foo:nth-of-type({{index}})` +* <span class="color:red">BAD:</span> `.foo:nth-of-type(1)` + +* <span class="color:green">GOOD:</span> `button[contains(@id, "foo")][{{index}}]` +* <span class="color:red">BAD:</span> `button[contains(@id, "foo")][1]` + +* <span class="color:green">GOOD:</span> `#actions__{{index}}__aggregator` +* <span class="color:red">BAD:</span> `#actions__1__aggregator` + +### CSS and XPath selectors MUST NOT reference the `@data-bind` attribute. \ No newline at end of file From 6ec227fb0b7ec473518984405fd10a9a14677977 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Tue, 16 Jul 2019 14:51:44 -0500 Subject: [PATCH 34/59] MQE-1600: MFTF Vault integration --- composer.json | 4 +- composer.lock | 603 +++++++++++++++--- etc/config/.credentials.example | 150 ++--- etc/config/.env.example | 4 + .../Handlers/CredentialStore.php | 146 ++--- .../Handlers/SecretStorage/BaseStorage.php | 84 +++ .../Handlers/SecretStorage/FileStorage.php | 119 ++++ .../Handlers/SecretStorage/VaultStorage.php | 131 ++++ .../Test/Util/ActionMergeUtil.php | 2 +- .../Util/TestGenerator.php | 2 +- 10 files changed, 1002 insertions(+), 243 deletions(-) create mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php create mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php create mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php diff --git a/composer.json b/composer.json index 8af401526..ddfafee8c 100755 --- a/composer.json +++ b/composer.json @@ -10,10 +10,12 @@ }, "require": { "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", - "allure-framework/allure-codeception": "~1.3.0", "ext-curl": "*", + "allure-framework/allure-codeception": "~1.3.0", "codeception/codeception": "~2.3.4 || ~2.4.0 ", "consolidation/robo": "^1.0.0", + "csharpru/vault-php": "^3.6", + "csharpru/vault-php-guzzle6-transport": "^2.0", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", diff --git a/composer.lock b/composer.lock index ca4e287fc..767326d11 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": "d5879be29cb6bbe70ce7e4a42828303a", + "content-hash": "c6cf409cdb5004e30eff742b235a857a", "packages": [ { "name": "allure-framework/allure-codeception", @@ -168,6 +168,99 @@ ], "time": "2016-10-30T11:50:56+00:00" }, + { + "name": "cache/cache", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-cache/cache.git", + "reference": "902b2e5b54ea57e3a801437748652228c4c58604" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-cache/cache/zipball/902b2e5b54ea57e3a801437748652228c4c58604", + "reference": "902b2e5b54ea57e3a801437748652228c4c58604", + "shasum": "" + }, + "require": { + "doctrine/cache": "^1.3", + "league/flysystem": "^1.0", + "php": "^5.6 || ^7.0", + "psr/cache": "^1.0", + "psr/log": "^1.0", + "psr/simple-cache": "^1.0" + }, + "conflict": { + "cache/adapter-common": "*", + "cache/apc-adapter": "*", + "cache/apcu-adapter": "*", + "cache/array-adapter": "*", + "cache/chain-adapter": "*", + "cache/doctrine-adapter": "*", + "cache/filesystem-adapter": "*", + "cache/hierarchical-cache": "*", + "cache/illuminate-adapter": "*", + "cache/memcache-adapter": "*", + "cache/memcached-adapter": "*", + "cache/mongodb-adapter": "*", + "cache/predis-adapter": "*", + "cache/psr-6-doctrine-bridge": "*", + "cache/redis-adapter": "*", + "cache/session-handler": "*", + "cache/taggable-cache": "*", + "cache/void-adapter": "*" + }, + "require-dev": { + "cache/integration-tests": "^0.16", + "defuse/php-encryption": "^2.0", + "illuminate/cache": "^5.4", + "mockery/mockery": "^0.9", + "phpunit/phpunit": "^4.0 || ^5.1", + "predis/predis": "^1.0", + "symfony/cache": "dev-master" + }, + "suggest": { + "ext-apc": "APC extension is required to use the APC Adapter", + "ext-apcu": "APCu extension is required to use the APCu Adapter", + "ext-memcache": "Memcache extension is required to use the Memcache Adapter", + "ext-memcached": "Memcached extension is required to use the Memcached Adapter", + "ext-mongodb": "Mongodb extension required to use the Mongodb adapter", + "ext-redis": "Redis extension is required to use the Redis adapter", + "mongodb/mongodb": "Mongodb lib required to use the Mongodb adapter" + }, + "type": "library", + "autoload": { + "psr-4": { + "Cache\\": "src/" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Scherer", + "email": "aequasi@gmail.com", + "homepage": "https://github.com/aequasi" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/nyholm" + } + ], + "description": "Library of all the php-cache adapters", + "homepage": "http://www.php-cache.com/en/latest/", + "keywords": [ + "cache", + "psr6" + ], + "time": "2017-03-28T16:08:48+00:00" + }, { "name": "codeception/codeception", "version": "2.3.9", @@ -668,6 +761,92 @@ "homepage": "https://github.com/container-interop/container-interop", "time": "2017-02-14T19:40:03+00:00" }, + { + "name": "csharpru/vault-php", + "version": "3.6.0", + "source": { + "type": "git", + "url": "https://github.com/CSharpRU/vault-php.git", + "reference": "7a7376fe92ee33fe8ca15e728a6bbff1859bd789" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CSharpRU/vault-php/zipball/7a7376fe92ee33fe8ca15e728a6bbff1859bd789", + "reference": "7a7376fe92ee33fe8ca15e728a6bbff1859bd789", + "shasum": "" + }, + "require": { + "cache/cache": "^0.4.0", + "doctrine/inflector": "~1.1", + "guzzlehttp/promises": "^1.3", + "guzzlehttp/psr7": "^1.4", + "psr/cache": "^1.0", + "psr/log": "^1.0", + "weew/helpers-array": "^1.3" + }, + "require-dev": { + "codacy/coverage": "^1.1", + "codeception/codeception": "^2.2", + "csharpru/vault-php-guzzle6-transport": "~2.0", + "php-vcr/php-vcr": "^1.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Vault\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Yaroslav Lukyanov", + "email": "c_sharp@mail.ru" + } + ], + "description": "Best Vault client for PHP that you can find", + "time": "2018-05-21T07:05:32+00:00" + }, + { + "name": "csharpru/vault-php-guzzle6-transport", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/CSharpRU/vault-php-guzzle6-transport.git", + "reference": "33c392120ac9f253b62b034e0e8ffbbdb3513bd8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CSharpRU/vault-php-guzzle6-transport/zipball/33c392120ac9f253b62b034e0e8ffbbdb3513bd8", + "reference": "33c392120ac9f253b62b034e0e8ffbbdb3513bd8", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.2", + "guzzlehttp/promises": "^1.3", + "guzzlehttp/psr7": "^1.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "VaultTransports\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Yaroslav Lukyanov", + "email": "c_sharp@mail.ru" + } + ], + "description": "Guzzle6 transport for Vault PHP client", + "time": "2019-03-10T06:17:37+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v1.1.0", @@ -795,6 +974,143 @@ ], "time": "2017-02-24T16:22:25+00:00" }, + { + "name": "doctrine/cache", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", + "shasum": "" + }, + "require": { + "php": "~5.5|~7.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.8|~5.0", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2017-07-22T12:49:21+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" + }, { "name": "doctrine/instantiator", "version": "1.0.5", @@ -1608,6 +1924,90 @@ ], "time": "2017-05-10T09:20:27+00:00" }, + { + "name": "league/flysystem", + "version": "1.0.53", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "08e12b7628f035600634a5e76d95b5eb66cea674" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/08e12b7628f035600634a5e76d95b5eb66cea674", + "reference": "08e12b7628f035600634a5e76d95b5eb66cea674", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": ">=5.5.9" + }, + "conflict": { + "league/flysystem-sftp": "<1.0.6" + }, + "require-dev": { + "phpspec/phpspec": "^3.4", + "phpunit/phpunit": "^5.7.10" + }, + "suggest": { + "ext-fileinfo": "Required for MimeType", + "ext-ftp": "Allows you to use FTP server storage", + "ext-openssl": "Allows you to use FTPS server storage", + "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", + "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", + "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", + "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", + "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", + "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", + "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", + "league/flysystem-webdav": "Allows you to use WebDAV storage", + "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", + "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", + "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Filesystem abstraction: Many filesystems, one API.", + "keywords": [ + "Cloud Files", + "WebDAV", + "abstraction", + "aws", + "cloud", + "copy.com", + "dropbox", + "file systems", + "files", + "filesystem", + "filesystems", + "ftp", + "rackspace", + "remote", + "s3", + "sftp", + "storage" + ], + "time": "2019-06-18T20:09:29+00:00" + }, { "name": "monolog/monolog", "version": "1.24.0", @@ -2679,6 +3079,52 @@ "abandoned": true, "time": "2018-08-09T05:50:03+00:00" }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -2825,6 +3271,54 @@ ], "time": "2016-10-10T12:19:37+00:00" }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, { "name": "ramsey/uuid", "version": "3.8.0", @@ -4397,6 +4891,43 @@ "validate" ], "time": "2018-01-29T19:49:41+00:00" + }, + { + "name": "weew/helpers-array", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/weew/helpers-array.git", + "reference": "9bff63111f9765b4277750db8d276d92b3e16ed0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/weew/helpers-array/zipball/9bff63111f9765b4277750db8d276d92b3e16ed0", + "reference": "9bff63111f9765b4277750db8d276d92b3e16ed0", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^4.7", + "satooshi/php-coveralls": "^0.6.1" + }, + "type": "library", + "autoload": { + "files": [ + "src/array.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxim Kott", + "email": "maximkott@gmail.com" + } + ], + "description": "Useful collection of php array helpers.", + "time": "2016-07-21T11:18:01+00:00" } ], "packages-dev": [ @@ -4556,76 +5087,6 @@ "description": "Experimental Mocking Framework powered by Aspects", "time": "2018-10-07T16:21:11+00:00" }, - { - "name": "doctrine/cache", - "version": "v1.6.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", - "shasum": "" - }, - "require": { - "php": "~5.5|~7.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2017-07-22T12:49:21+00:00" - }, { "name": "gitonomy/gitlib", "version": "v1.0.4", diff --git a/etc/config/.credentials.example b/etc/config/.credentials.example index ea8b03480..d9c73ac66 100644 --- a/etc/config/.credentials.example +++ b/etc/config/.credentials.example @@ -1,75 +1,75 @@ -#carriers/fedex/account= -#carriers/fedex/meter_number= -#carriers/fedex/key= -#carriers/fedex/password= - -#carriers/ups/password= -#carriers/ups/username= -#carriers/ups/access_license_number= -#carriers/ups/shipper_number= - -#carriers/usps/userid= -#carriers/usps/password= - -#carriers_dhl_id_us= -#carriers_dhl_password_us= -#carriers_dhl_account_us= - -#carriers_dhl_id_eu= -#carriers_dhl_password_eu= -#carriers_dhl_account_eu= - - -#payment_authorizenet_login= -#payment_authorizenet_trans_key= -#payment_authorizenet_trans_md5= - -#authorizenet_fraud_review_login= -#authorizenet_fraud_review_trans_key= -#authorizenet_fraud_review_md5= - -#braintree_enabled_fraud_merchant_account_id= -#braintree_enabled_fraud_merchant_id= -#braintree_enabled_fraud_public_key= -#braintree_enabled_fraud_private_key= - -#braintree_disabled_fraud_merchant_account_id= -#braintree_disabled_fraud_merchant_id= -#braintree_disabled_fraud_public_key= -#braintree_disabled_fraud_private_key= - -#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account= -#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username= -#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_password= -#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_signature= -#payment/paypal_express/merchant_id= - -#payflow_pro_fraud_protection_enabled_business_account= -#payflow_pro_fraud_protection_enabled_partner= -#payflow_pro_fraud_protection_enabled_user= -#payflow_pro_fraud_protection_enabled_pwd= -#payflow_pro_fraud_protection_enabled_vendor= - -#payflow_pro_business_account= -#payflow_pro_partner= -#payflow_pro_user= -#payflow_pro_pwd= -#payflow_pro_vendor= - -#payflow_link_business_account_email= -#payflow_link_partner= -#payflow_link_user= -#payflow_link_password= -#payflow_link_vendor= - -#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/business_account= -#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_username= -#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_password= -#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_signature= - -#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/business_account= -#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_username= -#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_password= -#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_signature= - -#fraud_protection/signifyd/api_key= \ No newline at end of file +#magento/magento/carriers_fedex_account= +#magento/carriers_fedex_meter_number= +#magento/carriers_fedex_key= +#magento/carriers_fedex_password= + +#magento/carriers_ups_password= +#magento/carriers_ups_username= +#magento/carriers_ups_access_license_number= +#magento/carriers_ups_shipper_number= + +#magento/carriers_usps_userid= +#magento/carriers_usps_password= + +#magento/carriers_dhl_id_us= +#magento/carriers_dhl_password_us= +#magento/carriers_dhl_account_us= + +#magento/carriers_dhl_id_eu= +#magento/carriers_dhl_password_eu= +#magento/carriers_dhl_account_eu= + + +#magento/payment_authorizenet_login= +#magento/payment_authorizenet_trans_key= +#magento/payment_authorizenet_trans_md5= + +#magento/authorizenet_fraud_review_login= +#magento/authorizenet_fraud_review_trans_key= +#magento/authorizenet_fraud_review_md5= + +#magento/braintree_enabled_fraud_merchant_account_id= +#magento/braintree_enabled_fraud_merchant_id= +#magento/braintree_enabled_fraud_public_key= +#magento/braintree_enabled_fraud_private_key= + +#magento/braintree_disabled_fraud_merchant_account_id= +#magento/braintree_disabled_fraud_merchant_id= +#magento/braintree_disabled_fraud_public_key= +#magento/braintree_disabled_fraud_private_key= + +#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_business_account= +#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_username= +#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_password= +#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_signature= +#magento/payment_paypal_express_merchant_id= + +#magento/payflow_pro_fraud_protection_enabled_business_account= +#magento/payflow_pro_fraud_protection_enabled_partner= +#magento/payflow_pro_fraud_protection_enabled_user= +#magento/payflow_pro_fraud_protection_enabled_pwd= +#magento/payflow_pro_fraud_protection_enabled_vendor= + +#magento/payflow_pro_business_account= +#magento/payflow_pro_partner= +#magento/payflow_pro_user= +#magento/payflow_pro_pwd= +#magento/payflow_pro_vendor= + +#magento/payflow_link_business_account_email= +#magento/payflow_link_partner= +#magento/payflow_link_user= +#magento/payflow_link_password= +#magento/payflow_link_vendor= + +#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_business_account= +#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_username= +#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_password= +#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_signature= + +#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_business_account= +#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_username= +#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_password= +#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_signature= + +#magento/fraud_protection_signifyd_api_key= \ No newline at end of file diff --git a/etc/config/.env.example b/etc/config/.env.example index 5dc7168be..a220498d9 100644 --- a/etc/config/.env.example +++ b/etc/config/.env.example @@ -30,6 +30,10 @@ BROWSER=chrome #MAGENTO_RESTAPI_SERVER_PORT=8080 #MAGENTO_RESTAPI_SERVER_PROTOCOL=https +*** Uncomment and set vault base url and access token if you want to use vault to manage _CREDS secrets ***# +#CREDENTIAL_VAULT_BASE_URL= +#CREDENTIAL_VAULT_TOKEN= + #*** Uncomment these properties to set up a dev environment with symlinked projects ***# #TESTS_BP= #FW_BP= diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index a83540683..fd5158a7c 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -6,15 +6,12 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\Console\BuildProjectCommand; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\VaultStorage; class CredentialStore { - const ENCRYPTION_ALGO = "AES-256-CBC"; - /** * Singleton instance * @@ -23,25 +20,18 @@ class CredentialStore private static $INSTANCE = null; /** - * Initial vector for open_ssl encryption. - * - * @var string - */ - private $iv = null; - - /** - * Key for open_ssl encryption/decryption + * File storage for credentials * - * @var string + * @var FileStorage */ - private $encodedKey = null; + private $credFile = null; /** - * Key/Value paris of credential names and their corresponding values + * Vault storage for credentials * - * @var array + * @var VaultStorage */ - private $credentials = []; + private $credVault = null; /** * Static singleton getter for CredentialStore Instance @@ -62,116 +52,84 @@ public static function getInstance() */ private function __construct() { - $this->encodedKey = base64_encode(openssl_random_pseudo_bytes(16)); - $this->iv = substr(hash('sha256', $this->encodedKey), 0, 16); - $creds = $this->readInCredentialsFile(); - $this->credentials = $this->encryptCredFileContents($creds); - } - - /** - * Returns the value of a secret based on corresponding key - * - * @param string $key - * @return string|null - * @throws TestFrameworkException - */ - public function getSecret($key) - { - if (!array_key_exists($key, $this->credentials)) { - throw new TestFrameworkException( - "{$key} not defined in .credentials, please provide a value in order to use this secret in a test." - ); + // Initialize vault storage + $csBaseUrl = getenv('CREDENTIAL_VAULT_BASE_URL'); + $csToken = getenv('CREDENTIAL_VAULT_TOKEN'); + if ($csBaseUrl !== false && $csToken !== false) { + try { + $this->credVault = new VaultStorage(rtrim($csBaseUrl, '/'), $csToken); + } catch (TestFrameworkException $e) { + } } - // log here for verbose config - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(CredentialStore::class)->debug( - "retrieving secret for key name {$key}" - ); + // Initialize file storage + try { + $this->credFile = new FileStorage(); + } catch (TestFrameworkException $e) { } - - return $this->credentials[$key] ?? null; } /** - * Private function which reads in secret key/values from .credentials file and stores in memory as key/value pair. + * Get encrypted value by key * - * @return array + * @param string $key + * @return string|null * @throws TestFrameworkException */ - private function readInCredentialsFile() - { - $credsFilePath = str_replace( - '.credentials.example', - '.credentials', - BuildProjectCommand::CREDENTIALS_FILE_PATH - ); - - if (!file_exists($credsFilePath)) { - throw new TestFrameworkException( - "Cannot find .credentials file, please create in " - . TESTS_BP . " in order to reference sensitive information" - ); - } - - return file($credsFilePath, FILE_IGNORE_NEW_LINES); - } - - /** - * Function which takes the contents of the credentials file and encrypts the entries. - * - * @param array $credContents - * @return array - */ - private function encryptCredFileContents($credContents) + public function getSecret($key) { - $encryptedCreds = []; - foreach ($credContents as $credValue) { - if (substr($credValue, 0, 1) === '#' || empty($credValue)) { - continue; + // Get secret data from vault storage first + if (!is_null($this->credVault)) { + $value = $this->credVault->getEncryptedValue($key); + if (!empty($value)) { + return $value; } + } - list($key, $value) = explode("=", $credValue, 2); + // Get secret data from file when not found in vault + if (!is_null($this->credFile)) { + $value = $this->credFile->getEncryptedValue($key); if (!empty($value)) { - $encryptedCreds[$key] = openssl_encrypt( - $value, - self::ENCRYPTION_ALGO, - $this->encodedKey, - 0, - $this->iv - ); + return $value; } } - return $encryptedCreds; + throw new TestFrameworkException( + "value for key \"$key\" not found in credential storage." + ); } /** - * Takes a value encrypted at runtime and descrypts using the object's initial vector. + * Return decrypted input value * * @param string $value * @return string */ public function decryptSecretValue($value) { - return openssl_decrypt($value, self::ENCRYPTION_ALGO, $this->encodedKey, 0, $this->iv); + if (!is_null($this->credVault)) { + return $this->credVault->getDecryptedValue($value); + } + + if (!is_null($this->credFile)) { + return $this->credFile->getDecryptedValue($value); + } } /** - * Takes a string that contains encrypted data at runtime and decrypts each value. + * Return decrypted values for all occurrences from input string * * @param string $string * @return mixed */ public function decryptAllSecretsInString($string) { - $newString = $string; - foreach ($this->credentials as $name => $secretValue) { - if (strpos($newString, $secretValue) !== false) { - $decryptedValue = $this->decryptSecretValue($secretValue); - $newString = str_replace($secretValue, $decryptedValue, $newString); - } + if (!is_null($this->credVault)) { + return $this->credVault->getAllDecryptedValues($string); + } + + if (!is_null($this->credFile)) { + return $this->credFile->getAllDecryptedValues($string); } - return $newString; } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php new file mode 100644 index 000000000..95ab48d51 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php @@ -0,0 +1,84 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; + +abstract class BaseStorage +{ + const ENCRYPTION_ALGO = "AES-256-CBC"; + + /** + * Initial vector for open_ssl encryption + * + * @var string + */ + protected static $iv = null; + + /** + * Key for open_ssl encryption/decryption + * + * @var string + */ + protected static $encodedKey = null; + + /** + * Accessed key/value secret data pairs + * + * @var array + */ + protected static $cachedSecretData = []; + + public function __construct() + { + if (is_null(self::$encodedKey)) { + self::$encodedKey = base64_encode(openssl_random_pseudo_bytes(16)); + self::$iv = substr(hash('sha256', self::$encodedKey), 0, 16); + } + } + + /** + * Returns the encrypted value based on corresponding key + * + * @param string $key + * @return string|null + */ + public function getEncryptedValue($key) + { + if (!array_key_exists($key, self::$cachedSecretData)) { + return null; + } + return self::$cachedSecretData[$key] ?? null; + } + + /** + * Takes a value encrypted at runtime and decrypts it using the object's initial vector + * + * @param string $value + * @return string + */ + public 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 + * + * @param string $string + * @return mixed + */ + public function getAllDecryptedValues($string) + { + $newString = $string; + foreach (self::$cachedSecretData as $key => $secretValue) { + if (strpos($newString, $secretValue) !== false) { + $decryptedValue = self::getDecryptedValue($secretValue); + $newString = str_replace($secretValue, $decryptedValue, $newString); + } + } + return $newString; + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php new file mode 100644 index 000000000..cbff33813 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php @@ -0,0 +1,119 @@ +<?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\Console\BuildProjectCommand; +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; + +class FileStorage extends BaseStorage +{ + /** + * Key/value secret data pairs parsed from file + * + * @var array + */ + private $secretData = []; + + /** + * FileStorage constructor + * + * @throws TestFrameworkException + */ + public function __construct() + { + parent::__construct(); + $creds = $this->readInCredentialsFile(); + $this->secretData = $this->encryptCredFileContents($creds); + } + + /** + * Returns the value of a secret based on corresponding key + * + * @param string $key + * @return string|null + */ + public function getEncryptedValue($key) + { + // Check if secret is in cached array + if (!is_null($value = parent::getEncryptedValue($key))) { + return $value; + } + + try { + // log here for verbose config + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(FileStorage::class)->debug( + "retrieving secret for key name {$key} from file" + ); + } + + } catch (\Exception $e) { + } + + // Retrieve from file storage + if (!array_key_exists($key, $this->secretData) || empty($value = $this->secretData[$key])) { + return null; + } + + parent::$cachedSecretData[$key] = $value; + return $value; + } + + /** + * Private function which reads in secret key/values from .credentials file and stores in memory as key/value pair + * + * @return array + * @throws TestFrameworkException + */ + private function readInCredentialsFile() + { + $credsFilePath = str_replace( + '.credentials.example', + '.credentials', + BuildProjectCommand::CREDENTIALS_FILE_PATH + ); + + if (!file_exists($credsFilePath)) { + throw new TestFrameworkException( + "Cannot find .credentials file, please create in " + . TESTS_BP . " in order to reference sensitive information" + ); + } + + return file($credsFilePath, FILE_IGNORE_NEW_LINES); + } + + /** + * Function which takes the contents of the credentials file and encrypts the entries + * + * @param array $credContents + * @return array + */ + private function encryptCredFileContents($credContents) + { + $encryptedCreds = []; + foreach ($credContents as $credValue) { + if (substr($credValue, 0, 1) === '#' || empty($credValue)) { + continue; + } + + list($key, $value) = explode("=", $credValue, 2); + if (!empty($value)) { + $encryptedCreds[$key] = openssl_encrypt( + $value, + parent::ENCRYPTION_ALGO, + parent::$encodedKey, + 0, + parent::$iv + ); + } + } + return $encryptedCreds; + } +} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php new file mode 100644 index 000000000..72a67e3e3 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php @@ -0,0 +1,131 @@ +<?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\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; +use Vault\AuthenticationStrategies\TokenAuthenticationStrategy; +use Vault\Client; +use VaultTransports\Guzzle6Transport; + +class VaultStorage extends BaseStorage +{ + const MFTF_PATH = '/mftf'; + /** + * Adobe Vault + */ + //const BASE_PATH = '/dx_magento_qe'; + //const KV_DATA = '/data'; + /** + * Local Vault + */ + const BASE_PATH = '/secret'; + const KV_DATA = '/data'; + + /** + * Vault client + * + * @var Client + */ + private static $client = null; + + /** + * Vault token + * + * @var string + */ + private $token; + + /** + * CredentialVault constructor + * + * @param string $baseUrl + * @param string $token + * @throws TestFrameworkException + */ + public function __construct($baseUrl, $token) + { + parent::__construct(); + if (is_null(self::$client)) { + // Creating the client using Guzzle6 Transport and passing a custom url + self::$client = new Client(new Guzzle6Transport(['base_url' => $baseUrl . self::BASE_PATH])); + } + $this->token = $token; + if (!$this->authenticated()) { + throw new TestFrameworkException("Credential Vault: Cannot Authenticate"); + } + } + + /** + * Returns the value of a secret based on corresponding key + * + * @param string $key + * @return string|null + */ + public function getEncryptedValue($key) + { + // Check if secret is in cached array + if (!is_null($value = parent::getEncryptedValue($key))) { + return $value; + } + + try { + // Log here for verbose config + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug( + "retrieving secret for key name {$key} from vault" + ); + } + } catch (\Exception $e) { + } + + // Retrieve from vault storage + if (!$this->authenticated()) { + return null; + } + + // Read value by key from vault + list($vendor, $key) = explode('/', trim($key, '/'), 2); + $url = self::BASE_PATH + . (empty(self::KV_DATA) ? '' : self::KV_DATA) + . self::MFTF_PATH + . '/' + . $vendor + . '/' + . $key; + $value = self::$client->read($url)->getData()['data'][$key]; + + if (empty($value)) { + return null; + } + $eValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); + parent::$cachedSecretData[$key] = $eValue; + return $eValue; + } + + /** + * Check if vault token is still valid. + * + * @return boolean + */ + private function authenticated() + { + try { + // Authenticating using token auth backend. + $authenticated = self::$client + ->setAuthenticationStrategy(new TokenAuthenticationStrategy($this->token)) + ->authenticate(); + + if ($authenticated) { + return true; + } + } catch (\Psr\Cache\InvalidArgumentException $e) { + } + return false; + } +} diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index 2a939a8c7..73a461148 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -149,7 +149,7 @@ private function actionAttributeContainsSecretRef($actionAttributes) return $this->actionAttributeContainsSecretRef($actionAttribute); } - preg_match_all("/{{_CREDS\.([\w]+)}}/", $actionAttribute, $matches); + preg_match_all("/{{_CREDS\.([\w|\/]+)}}/", $actionAttribute, $matches); if (!empty($matches[0])) { return true; diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index d07c5e1e0..a43fedd5a 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1901,7 +1901,7 @@ private function resolveAllRuntimeReferences($args) { $runtimeReferenceRegex = [ "/{{_ENV\.([\w]+)}}/" => 'getenv', - "/{{_CREDS\.([\w]+)}}/" => 'CredentialStore::getInstance()->getSecret' + "/{{_CREDS\.([\w|\/]+)}}/" => 'CredentialStore::getInstance()->getSecret' ]; $argResult = $args; From 919fa05c36a08bdfe465b6bf3ff81c19c1ba4e52 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 17 Jul 2019 10:18:36 -0500 Subject: [PATCH 35/59] MQE-1623: Add selector best practices to devdocs - Fixed grammar --- docs/selectors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/selectors.md b/docs/selectors.md index ea904e3ea..0da718629 100644 --- a/docs/selectors.md +++ b/docs/selectors.md @@ -4,7 +4,7 @@ The tips and tricks below will help you to write high quality selectors. ### Selectors SHOULD be written in CSS instead of Xpath whenever possible. -### Xpath selectors SHOULD NOT use `@attribute="foo"` instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any attribute such as `@text` or `@class` for example. +### Xpath selectors SHOULD NOT use `@attribute="foo"`. Instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any valid attribute such as `@text` or `@class`. ### CSS and Xpath selectors SHOULD be implemented in their most simple form. From 9658e3d41eac78a5b84ccc7b3860053188db83bf Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@adobe.com> Date: Thu, 18 Jul 2019 09:41:03 -0500 Subject: [PATCH 36/59] Grammar and markdown --- docs/selectors.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/selectors.md b/docs/selectors.md index 0da718629..8de1b0687 100644 --- a/docs/selectors.md +++ b/docs/selectors.md @@ -1,17 +1,21 @@ -# Selectors +## Selectors -The tips and tricks below will help you to write high quality selectors. +The guidelines below will help you to write high quality selectors. -### Selectors SHOULD be written in CSS instead of Xpath whenever possible. +### Selectors SHOULD be written in CSS instead of Xpath whenever possible -### Xpath selectors SHOULD NOT use `@attribute="foo"`. Instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any valid attribute such as `@text` or `@class`. +### Xpath selectors SHOULD NOT use `@attribute="foo"`. -### CSS and Xpath selectors SHOULD be implemented in their most simple form. +Instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any valid attribute such as `@text` or `@class`. + +### CSS and Xpath selectors SHOULD be implemented in their most simple form * <span class="color:green">GOOD:</span> `#foo` * <span class="color:red">BAD:</span> `button[contains(@id, "foo")]` -### CSS and Xpath selectors SHOULD avoid making use of hardcoded indices. Instead you SHOULD parameterize the selector. +### CSS and Xpath selectors SHOULD avoid making use of hardcoded indices + +Instead you SHOULD parameterize the selector. * <span class="color:green">GOOD:</span> `.foo:nth-of-type({{index}})` * <span class="color:red">BAD:</span> `.foo:nth-of-type(1)` @@ -22,4 +26,4 @@ The tips and tricks below will help you to write high quality selectors. * <span class="color:green">GOOD:</span> `#actions__{{index}}__aggregator` * <span class="color:red">BAD:</span> `#actions__1__aggregator` -### CSS and XPath selectors MUST NOT reference the `@data-bind` attribute. \ No newline at end of file +### CSS and XPath selectors MUST NOT reference the `@data-bind` attribute From d305b4c44a87d433869ba804b3857b44bca054d7 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 18 Jul 2019 13:46:57 -0500 Subject: [PATCH 37/59] MQE-1606: Mftf static check script should return error exit code when check fails --- .../Console/StaticChecksCommand.php | 10 ++++++++ .../StaticCheck/StaticCheckInterface.php | 6 +++++ .../StaticCheck/TestDependencyCheck.php | 25 +++++++++++++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php index fde306791..6b8510695 100644 --- a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php @@ -47,10 +47,20 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $staticCheckObjects = $this->staticChecksList->getStaticChecks(); + + $errors = []; + foreach ($staticCheckObjects as $staticCheck) { $staticOutput = $staticCheck->execute($input); LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->info($staticOutput); $output->writeln($staticOutput); + $errors += $staticCheck->getErrors(); + } + + if (empty($errors)) { + return 0; + } else { + return 1; } } } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php index 45ebdea8d..da0bc42de 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php @@ -19,4 +19,10 @@ interface StaticCheckInterface * @return string */ public function execute(InputInterface $input); + + /** + * Return array containing all errors found after running the execute() function. + * @return array + */ + public function getErrors(); } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php index 1a149a657..e87773c05 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php @@ -62,6 +62,12 @@ class TestDependencyCheck implements StaticCheckInterface */ private $alreadyExtractedDependencies; + /** + * Array containing all errors found after running the execute() function. + * @var array + */ + private $errors; + /** * Checks test dependencies, determined by references in tests versus the dependencies listed in the Magento module * @@ -98,13 +104,22 @@ public function execute(InputInterface $input) $actionGroupXmlFiles = $this->buildFileList($allModules, $filePaths[1]); $dataXmlFiles= $this->buildFileList($allModules, $filePaths[2]); - $testErrors = []; - $testErrors += $this->findErrorsInFileSet($testXmlFiles); - $testErrors += $this->findErrorsInFileSet($actionGroupXmlFiles); - $testErrors += $this->findErrorsInFileSet($dataXmlFiles); + $this->errors = []; + $this->errors += $this->findErrorsInFileSet($testXmlFiles); + $this->errors += $this->findErrorsInFileSet($actionGroupXmlFiles); + $this->errors += $this->findErrorsInFileSet($dataXmlFiles); //print all errors to file - return $this->printErrorsToFile($testErrors); + return $this->printErrorsToFile($this->getErrors()); + } + + /** + * Return array containing all errors found after running the execute() function. + * @return array + */ + public function getErrors() + { + return $this->errors; } /** From dfc77135cd773f5b16d4ab872dc6a8a11324f576 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 18 Jul 2019 13:58:45 -0500 Subject: [PATCH 38/59] MQE-1606: Mftf static check script should return error exit code when check fails - Add to .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 63ea3d26e..d6ad9e81c 100755 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ dev/tests/functional/MFTF.suite.yml dev/tests/functional/_output dev/mftf.log dev/tests/mftf.log -dev/tests/docs/* \ No newline at end of file +dev/tests/docs/* +dev/tests/_output +dev/tests/functional.suite.yml From 3889f9a8a08a831ab9f1742e28182e31d78d054e Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Wed, 17 Jul 2019 09:19:56 -0500 Subject: [PATCH 39/59] MQE-1600: unit and static test fixes --- .travis.yml | 1 - .../FileStorageTest.php} | 17 +++++++++-------- etc/config/.env.example | 2 +- .../DataGenerator/Handlers/CredentialStore.php | 12 ++++++------ .../Handlers/SecretStorage/BaseStorage.php | 5 ++++- .../Handlers/SecretStorage/FileStorage.php | 3 +-- .../Handlers/SecretStorage/VaultStorage.php | 16 ++++++++-------- 7 files changed, 29 insertions(+), 27 deletions(-) rename dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/{CredentialStoreTest.php => SecretStorage/FileStorageTest.php} (59%) diff --git a/.travis.yml b/.travis.yml index 913c74f48..f807d7415 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: php php: - - 7.0 - 7.1 - 7.2 - 7.3 diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php similarity index 59% rename from dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php rename to dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php index a451f8dc9..7e5824c8e 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php @@ -4,33 +4,34 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers; +namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers\SecretStorage; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; use Magento\FunctionalTestingFramework\Util\MagentoTestCase; use AspectMock\Test as AspectMock; -class CredentialStoreTest extends MagentoTestCase +class FileStorageTest extends MagentoTestCase { /** - * Test basic encryption/decryption functionality in CredentialStore class. + * Test basic encryption/decryption functionality in FileStorage class. */ public function testBasicEncryptDecrypt() { - $testKey = 'myKey'; + $testKey = 'magento/myKey'; $testValue = 'myValue'; - AspectMock::double(CredentialStore::class, [ + AspectMock::double(FileStorage::class, [ 'readInCredentialsFile' => ["$testKey=$testValue"] ]); - $encryptedCred = CredentialStore::getInstance()->getSecret($testKey); + $fileStorage = new FileStorage(); + $encryptedCred = $fileStorage->getEncryptedValue($testKey); // assert the value we've gotten is in fact not identical to our test value $this->assertNotEquals($testValue, $encryptedCred); - $actualValue = CredentialStore::getInstance()->decryptSecretValue($encryptedCred); + $actualValue = $fileStorage->getDecryptedValue($encryptedCred); // assert that we are able to successfully decrypt our secret value $this->assertEquals($testValue, $actualValue); diff --git a/etc/config/.env.example b/etc/config/.env.example index a220498d9..cc82ae447 100644 --- a/etc/config/.env.example +++ b/etc/config/.env.example @@ -30,7 +30,7 @@ BROWSER=chrome #MAGENTO_RESTAPI_SERVER_PORT=8080 #MAGENTO_RESTAPI_SERVER_PROTOCOL=https -*** Uncomment and set vault base url and access token if you want to use vault to manage _CREDS secrets ***# +#*** Uncomment and set vault base url and access token if you want to use vault to manage _CREDS secrets ***# #CREDENTIAL_VAULT_BASE_URL= #CREDENTIAL_VAULT_TOKEN= diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index fd5158a7c..b8bf9876d 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -79,7 +79,7 @@ private function __construct() public function getSecret($key) { // Get secret data from vault storage first - if (!is_null($this->credVault)) { + if (null !== $this->credVault) { $value = $this->credVault->getEncryptedValue($key); if (!empty($value)) { return $value; @@ -87,7 +87,7 @@ public function getSecret($key) } // Get secret data from file when not found in vault - if (!is_null($this->credFile)) { + if (null !== $this->credFile) { $value = $this->credFile->getEncryptedValue($key); if (!empty($value)) { return $value; @@ -107,11 +107,11 @@ public function getSecret($key) */ public function decryptSecretValue($value) { - if (!is_null($this->credVault)) { + if (null !== $this->credVault) { return $this->credVault->getDecryptedValue($value); } - if (!is_null($this->credFile)) { + if (null !== $this->credFile) { return $this->credFile->getDecryptedValue($value); } } @@ -124,11 +124,11 @@ public function decryptSecretValue($value) */ public function decryptAllSecretsInString($string) { - if (!is_null($this->credVault)) { + if (null !== $this->credVault) { return $this->credVault->getAllDecryptedValues($string); } - if (!is_null($this->credFile)) { + if (null !== $this->credFile) { return $this->credFile->getAllDecryptedValues($string); } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php index 95ab48d51..22430e5b6 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php @@ -31,9 +31,12 @@ abstract class BaseStorage */ protected static $cachedSecretData = []; + /** + * BaseStorage constructor + */ public function __construct() { - if (is_null(self::$encodedKey)) { + if (null === self::$encodedKey) { self::$encodedKey = base64_encode(openssl_random_pseudo_bytes(16)); self::$iv = substr(hash('sha256', self::$encodedKey), 0, 16); } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php index cbff33813..1e0ee73d8 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php @@ -41,7 +41,7 @@ public function __construct() public function getEncryptedValue($key) { // Check if secret is in cached array - if (!is_null($value = parent::getEncryptedValue($key))) { + if (null !== ($value = parent::getEncryptedValue($key))) { return $value; } @@ -52,7 +52,6 @@ public function getEncryptedValue($key) "retrieving secret for key name {$key} from file" ); } - } catch (\Exception $e) { } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php index 72a67e3e3..ab23f2642 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php @@ -19,13 +19,13 @@ class VaultStorage extends BaseStorage /** * Adobe Vault */ - //const BASE_PATH = '/dx_magento_qe'; - //const KV_DATA = '/data'; + const BASE_PATH = '/dx_magento_qe'; + const KV_DATA = '/data'; /** * Local Vault */ - const BASE_PATH = '/secret'; - const KV_DATA = '/data'; + //const BASE_PATH = '/secret'; + //const KV_DATA = '/data'; /** * Vault client @@ -51,9 +51,9 @@ class VaultStorage extends BaseStorage public function __construct($baseUrl, $token) { parent::__construct(); - if (is_null(self::$client)) { + if (null === self::$client) { // Creating the client using Guzzle6 Transport and passing a custom url - self::$client = new Client(new Guzzle6Transport(['base_url' => $baseUrl . self::BASE_PATH])); + self::$client = new Client(new Guzzle6Transport(['base_uri' => $baseUrl])); } $this->token = $token; if (!$this->authenticated()) { @@ -70,7 +70,7 @@ public function __construct($baseUrl, $token) public function getEncryptedValue($key) { // Check if secret is in cached array - if (!is_null($value = parent::getEncryptedValue($key))) { + if (null !== ($value = parent::getEncryptedValue($key))) { return $value; } @@ -124,7 +124,7 @@ private function authenticated() if ($authenticated) { return true; } - } catch (\Psr\Cache\InvalidArgumentException $e) { + } catch (\Exception $e) { } return false; } From c3f67ea3fb5c21f6d53484561a42bc010f31dcc9 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Fri, 19 Jul 2019 13:46:12 -0500 Subject: [PATCH 40/59] MQE-1600: MQE-1600: MFTF Vault integration - prefer credentials from local file over vault - address review comments --- .../Handlers/CredentialStore.php | 88 +++++++++++-------- .../Handlers/SecretStorage/FileStorage.php | 25 +++--- .../Handlers/SecretStorage/VaultStorage.php | 71 +++++++-------- .../Test/Util/ActionMergeUtil.php | 3 +- .../Util/TestGenerator.php | 3 +- 5 files changed, 96 insertions(+), 94 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index b8bf9876d..c122788cb 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -12,31 +12,35 @@ class CredentialStore { + const ARRAY_KEY_FOR_VAULT = 'vault'; + const ARRAY_KEY_FOR_FILE = 'file'; + /** - * Singleton instance + * Numeric indexed array that defines the access precedence of credential storage * - * @var CredentialStore + * @var array */ - private static $INSTANCE = null; + private static $credStoragePrecedence = [self::ARRAY_KEY_FOR_FILE, self::ARRAY_KEY_FOR_VAULT]; /** - * File storage for credentials + * Credential storage array * - * @var FileStorage + * @var array */ - private $credFile = null; + private $credStorage = []; /** - * Vault storage for credentials + * Singleton instance * - * @var VaultStorage + * @var CredentialStore */ - private $credVault = null; + private static $INSTANCE = null; /** * Static singleton getter for CredentialStore Instance * * @return CredentialStore + * @throws TestFrameworkException */ public static function getInstance() { @@ -48,7 +52,9 @@ public static function getInstance() } /** - * CredentialStore constructor. + * CredentialStore constructor + * + * @throws TestFrameworkException */ private function __construct() { @@ -57,16 +63,28 @@ private function __construct() $csToken = getenv('CREDENTIAL_VAULT_TOKEN'); if ($csBaseUrl !== false && $csToken !== false) { try { - $this->credVault = new VaultStorage(rtrim($csBaseUrl, '/'), $csToken); + $this->credStorage[self::ARRAY_KEY_FOR_VAULT] = new VaultStorage( + rtrim($csBaseUrl, '/'), + $csToken + ); } catch (TestFrameworkException $e) { } } // Initialize file storage try { - $this->credFile = new FileStorage(); + $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); } catch (TestFrameworkException $e) { } + + foreach ($this->credStorage as $cred) { + if (null !== $cred) { + return; + } + } + throw new TestFrameworkException( + "No credential storage is properly configured. Please configure vault or .credentials file." + ); } /** @@ -78,24 +96,20 @@ private function __construct() */ public function getSecret($key) { - // Get secret data from vault storage first - if (null !== $this->credVault) { - $value = $this->credVault->getEncryptedValue($key); - if (!empty($value)) { - return $value; - } - } - - // Get secret data from file when not found in vault - if (null !== $this->credFile) { - $value = $this->credFile->getEncryptedValue($key); - if (!empty($value)) { - return $value; + // Get secret data from storage according to defined precedence + // File storage is preferred over vault storage to allow local secret value overriding remote secret value + foreach (self::$credStoragePrecedence as $credType) { + if (null !== $this->credStorage[$credType]) { + $value = $this->credStorage[$credType]->getEncryptedValue($key); + if (null !== $value) { + return $value; + } } } throw new TestFrameworkException( - "value for key \"$key\" not found in credential storage." + "{$key} not defined in vault or .credentials file, " + . "please provide a value in order to use this secret in a test.\"." ); } @@ -107,12 +121,11 @@ public function getSecret($key) */ public function decryptSecretValue($value) { - if (null !== $this->credVault) { - return $this->credVault->getDecryptedValue($value); - } - - if (null !== $this->credFile) { - return $this->credFile->getDecryptedValue($value); + // Loop through storage to decrypt value + foreach (self::$credStoragePrecedence as $credType) { + if (null !== $this->credStorage[$credType]) { + return $this->credStorage[$credType]->getDecryptedValue($value); + } } } @@ -124,12 +137,11 @@ public function decryptSecretValue($value) */ public function decryptAllSecretsInString($string) { - if (null !== $this->credVault) { - return $this->credVault->getAllDecryptedValues($string); - } - - if (null !== $this->credFile) { - return $this->credFile->getAllDecryptedValues($string); + // Loop through storage to decrypt all occurrences from input string + foreach (self::$credStoragePrecedence as $credType) { + if (null !== $this->credStorage[$credType]) { + return $this->credStorage[$credType]->getAllDecryptedValues($string); + } } } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php index 1e0ee73d8..064610c79 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php @@ -6,9 +6,9 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Magento\FunctionalTestingFramework\Console\BuildProjectCommand; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; class FileStorage extends BaseStorage @@ -22,7 +22,6 @@ class FileStorage extends BaseStorage /** * FileStorage constructor - * * @throws TestFrameworkException */ public function __construct() @@ -40,27 +39,24 @@ public function __construct() */ public function getEncryptedValue($key) { + $value = null; // Check if secret is in cached array if (null !== ($value = parent::getEncryptedValue($key))) { return $value; } - try { - // log here for verbose config - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(FileStorage::class)->debug( - "retrieving secret for key name {$key} from file" - ); - } - } catch (\Exception $e) { + // log here for verbose config + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(FileStorage::class)->debug( + "retrieving secret for key name {$key} from file" + ); } // Retrieve from file storage - if (!array_key_exists($key, $this->secretData) || empty($value = $this->secretData[$key])) { - return null; + if (array_key_exists($key, $this->secretData) && (null !== ($value = $this->secretData[$key]))) { + parent::$cachedSecretData[$key] = $value; } - parent::$cachedSecretData[$key] = $value; return $value; } @@ -80,8 +76,7 @@ private function readInCredentialsFile() if (!file_exists($credsFilePath)) { throw new TestFrameworkException( - "Cannot find .credentials file, please create in " - . TESTS_BP . " in order to reference sensitive information" + "Credential file is not used: .credentials file not found in " . TESTS_BP ); } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php index ab23f2642..316875b31 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php @@ -20,19 +20,14 @@ class VaultStorage extends BaseStorage * Adobe Vault */ const BASE_PATH = '/dx_magento_qe'; - const KV_DATA = '/data'; - /** - * Local Vault - */ - //const BASE_PATH = '/secret'; - //const KV_DATA = '/data'; + const KV_DATA = 'data'; /** * Vault client * * @var Client */ - private static $client = null; + private $client = null; /** * Vault token @@ -51,13 +46,13 @@ class VaultStorage extends BaseStorage public function __construct($baseUrl, $token) { parent::__construct(); - if (null === self::$client) { + if (null === $this->client) { // Creating the client using Guzzle6 Transport and passing a custom url - self::$client = new Client(new Guzzle6Transport(['base_uri' => $baseUrl])); + $this->client = new Client(new Guzzle6Transport(['base_uri' => $baseUrl])); } $this->token = $token; if (!$this->authenticated()) { - throw new TestFrameworkException("Credential Vault: Cannot Authenticate"); + throw new TestFrameworkException("Credential vault is not used: cannot authenticate"); } } @@ -74,50 +69,48 @@ public function getEncryptedValue($key) return $value; } + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug( + "Retrieving secret for key name {$key} from vault" + ); + } + + $reValue = null; try { - // Log here for verbose config + // Split vendor/key to construct secret path + list($vendor, $key) = explode('/', trim($key, '/'), 2); + $url = self::BASE_PATH + . (empty(self::KV_DATA) ? '' : '/' . self::KV_DATA) + . self::MFTF_PATH + . '/' + . $vendor + . '/' + . $key; + // Read value by key from vault + $value = $this->client->read($url)->getData()[self::KV_DATA][$key]; + // Encrypt value for return + $reValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); + parent::$cachedSecretData[$key] = $reValue; + } catch (\Exception $e) { if (MftfApplicationConfig::getConfig()->verboseEnabled()) { LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug( - "retrieving secret for key name {$key} from vault" + "Unable to read secret for key name {$key} from vault" ); } - } catch (\Exception $e) { - } - - // Retrieve from vault storage - if (!$this->authenticated()) { - return null; - } - - // Read value by key from vault - list($vendor, $key) = explode('/', trim($key, '/'), 2); - $url = self::BASE_PATH - . (empty(self::KV_DATA) ? '' : self::KV_DATA) - . self::MFTF_PATH - . '/' - . $vendor - . '/' - . $key; - $value = self::$client->read($url)->getData()['data'][$key]; - - if (empty($value)) { - return null; } - $eValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); - parent::$cachedSecretData[$key] = $eValue; - return $eValue; + return $reValue; } /** - * Check if vault token is still valid. + * Check if vault token is valid * * @return boolean */ private function authenticated() { try { - // Authenticating using token auth backend. - $authenticated = self::$client + // Authenticating using token auth backend + $authenticated = $this->client ->setAuthenticationStrategy(new TokenAuthenticationStrategy($this->token)) ->authenticate(); diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index 73a461148..cd81ade24 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -31,6 +31,7 @@ class ActionMergeUtil const DEFAULT_WAIT_ORDER = 'after'; const APPROVED_ACTIONS = ['fillField', 'magentoCLI', 'field']; const SECRET_MAPPING = ['fillField' => 'fillSecretField', 'magentoCLI' => 'magentoCLISecret']; + const CREDS_REGEX = "/{{_CREDS\.([\w|\/]+)}}/"; /** * Array holding final resulting steps @@ -149,7 +150,7 @@ private function actionAttributeContainsSecretRef($actionAttributes) return $this->actionAttributeContainsSecretRef($actionAttribute); } - preg_match_all("/{{_CREDS\.([\w|\/]+)}}/", $actionAttribute, $matches); + preg_match_all(self::CREDS_REGEX, $actionAttribute, $matches); if (!empty($matches[0])) { return true; diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index a43fedd5a..beff2bd9f 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -24,6 +24,7 @@ use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil; +use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; /** * Class TestGenerator @@ -1901,7 +1902,7 @@ private function resolveAllRuntimeReferences($args) { $runtimeReferenceRegex = [ "/{{_ENV\.([\w]+)}}/" => 'getenv', - "/{{_CREDS\.([\w|\/]+)}}/" => 'CredentialStore::getInstance()->getSecret' + ActionMergeUtil::CREDS_REGEX => 'CredentialStore::getInstance()->getSecret' ]; $argResult = $args; From 4c10d1c75cb662a38f60c1eeef40be95a47b5145 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Fri, 19 Jul 2019 14:19:40 -0500 Subject: [PATCH 41/59] MQE-1600: MFTF Vault integration - prefer credentials from local file over vault - address review comments --- .../DataGenerator/Handlers/CredentialStore.php | 6 +++--- .../DataGenerator/Handlers/SecretStorage/BaseStorage.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index c122788cb..8385c2ec6 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -108,8 +108,8 @@ public function getSecret($key) } 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 defined in vault or .credentials file, " + . "please provide a value in order to use this secret in a test." ); } @@ -140,7 +140,7 @@ public function decryptAllSecretsInString($string) // Loop through storage to decrypt all occurrences from input string foreach (self::$credStoragePrecedence as $credType) { if (null !== $this->credStorage[$credType]) { - return $this->credStorage[$credType]->getAllDecryptedValues($string); + return $this->credStorage[$credType]->getAllDecryptedValuesInString($string); } } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php index 22430e5b6..cb892a545 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php @@ -73,7 +73,7 @@ public function getDecryptedValue($value) * @param string $string * @return mixed */ - public function getAllDecryptedValues($string) + public function getAllDecryptedValuesInString($string) { $newString = $string; foreach (self::$cachedSecretData as $key => $secretValue) { From 36c5865f39690f53df5fd7b031bcdedca0a65c62 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Fri, 19 Jul 2019 14:29:43 -0500 Subject: [PATCH 42/59] MQE-1600: MFTF Vault integration - prefer credentials from local file over vault - address review comments --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f807d7415..913c74f48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: php php: + - 7.0 - 7.1 - 7.2 - 7.3 From 3f7fe8286054aa78bcfceb799e31c4fb08f504e3 Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Fri, 19 Jul 2019 17:28:07 -0500 Subject: [PATCH 43/59] MQE-1600: MFTF Vault integration - Downgrade vault php version to be compatible to php 7.0 --- composer.json | 2 +- composer.lock | 34 +++++++------- .../Handlers/SecretStorage/VaultStorage.php | 3 +- .../SecretStorage/VaultTokenAuthStrategy.php | 47 +++++++++++++++++++ 4 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php diff --git a/composer.json b/composer.json index ddfafee8c..24fb91c92 100755 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "allure-framework/allure-codeception": "~1.3.0", "codeception/codeception": "~2.3.4 || ~2.4.0 ", "consolidation/robo": "^1.0.0", - "csharpru/vault-php": "^3.6", + "csharpru/vault-php": "~3.5.3", "csharpru/vault-php-guzzle6-transport": "^2.0", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", diff --git a/composer.lock b/composer.lock index 767326d11..95f08abcd 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": "c6cf409cdb5004e30eff742b235a857a", + "content-hash": "fb0f9a5c731e02404fb78c95aa647e46", "packages": [ { "name": "allure-framework/allure-codeception", @@ -763,21 +763,21 @@ }, { "name": "csharpru/vault-php", - "version": "3.6.0", + "version": "3.5.3", "source": { "type": "git", "url": "https://github.com/CSharpRU/vault-php.git", - "reference": "7a7376fe92ee33fe8ca15e728a6bbff1859bd789" + "reference": "04be9776310fe7d1afb97795645f95c21e6b4fcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CSharpRU/vault-php/zipball/7a7376fe92ee33fe8ca15e728a6bbff1859bd789", - "reference": "7a7376fe92ee33fe8ca15e728a6bbff1859bd789", + "url": "https://api.github.com/repos/CSharpRU/vault-php/zipball/04be9776310fe7d1afb97795645f95c21e6b4fcf", + "reference": "04be9776310fe7d1afb97795645f95c21e6b4fcf", "shasum": "" }, "require": { "cache/cache": "^0.4.0", - "doctrine/inflector": "~1.1", + "doctrine/inflector": "~1.1.0", "guzzlehttp/promises": "^1.3", "guzzlehttp/psr7": "^1.4", "psr/cache": "^1.0", @@ -807,7 +807,7 @@ } ], "description": "Best Vault client for PHP that you can find", - "time": "2018-05-21T07:05:32+00:00" + "time": "2018-04-28T04:52:17+00:00" }, { "name": "csharpru/vault-php-guzzle6-transport", @@ -1046,33 +1046,33 @@ }, { "name": "doctrine/inflector", - "version": "v1.3.0", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", - "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", "shasum": "" }, "require": { - "php": "^7.1" + "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "4.*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { - "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "psr-0": { + "Doctrine\\Common\\Inflector\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1109,7 +1109,7 @@ "singularize", "string" ], - "time": "2018-01-09T20:05:19+00:00" + "time": "2015-11-06T14:35:42+00:00" }, { "name": "doctrine/instantiator", diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php index 316875b31..de80b83e3 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php @@ -9,7 +9,6 @@ use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; -use Vault\AuthenticationStrategies\TokenAuthenticationStrategy; use Vault\Client; use VaultTransports\Guzzle6Transport; @@ -111,7 +110,7 @@ private function authenticated() try { // Authenticating using token auth backend $authenticated = $this->client - ->setAuthenticationStrategy(new TokenAuthenticationStrategy($this->token)) + ->setAuthenticationStrategy(new VaultTokenAuthStrategy($this->token)) ->authenticate(); if ($authenticated) { diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php new file mode 100644 index 000000000..716344ca1 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; + +use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; +use Vault\AuthenticationStrategies\AbstractAuthenticationStrategy; +use Vault\ResponseModels\Auth; + +/** + * Class VaultTokenAuthStrategy + */ +class VaultTokenAuthStrategy extends AbstractAuthenticationStrategy +{ + /** + * @var string + */ + protected $token; + + /** + * VaultTokenAuthStrategy constructor + * + * @param string $token + */ + public function __construct($token) + { + $this->token = $token; + } + + /** + * Returns auth for further interactions with Vault + * + * @return Auth + * @throws TestFrameworkException + */ + public function authenticate() + { + try { + return new Auth(['clientToken' => $this->token]); + } catch (\Exception $e) { + throw new TestFrameworkException("Cannot authenticate Vault token."); + } + } +} From 367b7153787613fbb162362e9efbcd393e7967bc Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@adobe.com> Date: Mon, 22 Jul 2019 09:49:08 -0500 Subject: [PATCH 44/59] Updated Selenium/WebDriver versions. (#381) --- docs/troubleshooting.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 6ad300428..d546c4e15 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -41,7 +41,7 @@ Chrome v62 is in the process of being rolled out, and it causes an error with Ch #### Solution -Use [ChromeDriver v2.33+][]{:target="\_blank"} and [Selenium Server Standalone v3.6.0+][]{:target="\_blank"} in order to execute tests in Google Chrome v62+. +Use [ChromeDriver 74.0.3729.6+][]{:target="\_blank"} and [Selenium Server Standalone v3.9+][]{:target="\_blank"} in order to execute tests in Google Chrome v62+. ### Firefox @@ -57,5 +57,5 @@ None yet. Solving this problem is dependent on a GeckoDriver fix. <!-- Link Definitions --> [Headless Chrome]: https://developers.google.com/web/updates/2017/04/headless-chrome -[ChromeDriver v2.33+]: https://chromedriver.storage.googleapis.com/index.html?path=2.33/ -[Selenium Server Standalone v3.6.0+]: http://www.seleniumhq.org/download/ \ No newline at end of file +[ChromeDriver 74.0.3729.6+]: https://chromedriver.storage.googleapis.com/index.html?path=2.33/ +[Selenium Server Standalone v3.9+]: http://www.seleniumhq.org/download/ From b5e1939debe6ef98e62b37319b0f9662ba3527e0 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Mon, 22 Jul 2019 10:03:50 -0500 Subject: [PATCH 45/59] MQE-1623: Add selector best practices to devdocs - Add two descriptions - Changed all Xpath to XPath --- docs/selectors.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/selectors.md b/docs/selectors.md index 8de1b0687..93178e2df 100644 --- a/docs/selectors.md +++ b/docs/selectors.md @@ -2,18 +2,20 @@ The guidelines below will help you to write high quality selectors. -### Selectors SHOULD be written in CSS instead of Xpath whenever possible +### Selectors SHOULD be written in CSS instead of XPath whenever possible -### Xpath selectors SHOULD NOT use `@attribute="foo"`. +CSS is often more succinct and natural to read. For example, `//*[@id="foo"]` in XPath can be expressed as simply as `#foo` in CSS. See this [XPath Cheatsheet](https://devhints.io/xpath) for more examples. + +### XPath selectors SHOULD NOT use `@attribute="foo"`. Instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any valid attribute such as `@text` or `@class`. -### CSS and Xpath selectors SHOULD be implemented in their most simple form +### CSS and XPath selectors SHOULD be implemented in their most simple form * <span class="color:green">GOOD:</span> `#foo` * <span class="color:red">BAD:</span> `button[contains(@id, "foo")]` -### CSS and Xpath selectors SHOULD avoid making use of hardcoded indices +### CSS and XPath selectors SHOULD avoid making use of hardcoded indices Instead you SHOULD parameterize the selector. @@ -27,3 +29,5 @@ Instead you SHOULD parameterize the selector. * <span class="color:red">BAD:</span> `#actions__1__aggregator` ### CSS and XPath selectors MUST NOT reference the `@data-bind` attribute + +The `@data-bind` attribute is used by KnockoutJS, a framework Magento uses to create dynamic Javascript pages. Since this `@data-bind` attribute is tied to a specific framework it should not be used for selectors. If Magento decides to use a different framework then these `@data-bind` selectors would break. From 386e7258a2d52d9c774b49b06100d79adc3faae2 Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@adobe.com> Date: Mon, 22 Jul 2019 10:09:05 -0500 Subject: [PATCH 46/59] MInor fixes. --- docs/selectors.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/selectors.md b/docs/selectors.md index 93178e2df..870072e15 100644 --- a/docs/selectors.md +++ b/docs/selectors.md @@ -1,13 +1,15 @@ ## Selectors -The guidelines below will help you to write high quality selectors. +These guidelines should help you to write high quality selectors. ### Selectors SHOULD be written in CSS instead of XPath whenever possible -CSS is often more succinct and natural to read. For example, `//*[@id="foo"]` in XPath can be expressed as simply as `#foo` in CSS. See this [XPath Cheatsheet](https://devhints.io/xpath) for more examples. +CSS is generally easier to read than XPath. For example, `//*[@id="foo"]` in XPath can be expressed as simply as `#foo` in CSS. +See this [XPath Cheatsheet](https://devhints.io/xpath) for more examples. ### XPath selectors SHOULD NOT use `@attribute="foo"`. +This would fail if the attribute was `attribute="foo bar"`. Instead you SHOULD use `contains(@attribute, "foo")` where `@attribute` is any valid attribute such as `@text` or `@class`. ### CSS and XPath selectors SHOULD be implemented in their most simple form @@ -30,4 +32,4 @@ Instead you SHOULD parameterize the selector. ### CSS and XPath selectors MUST NOT reference the `@data-bind` attribute -The `@data-bind` attribute is used by KnockoutJS, a framework Magento uses to create dynamic Javascript pages. Since this `@data-bind` attribute is tied to a specific framework it should not be used for selectors. If Magento decides to use a different framework then these `@data-bind` selectors would break. +The `@data-bind` attribute is used by KnockoutJS, a framework Magento uses to create dynamic Javascript pages. Since this `@data-bind` attribute is tied to a specific framework, it should not be used for selectors. If Magento decides to use a different framework then these `@data-bind` selectors would break. From c598015e35f603aab9c1adbb7873561512ee9bbc Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Mon, 22 Jul 2019 13:28:01 -0500 Subject: [PATCH 47/59] MQE-1606: Mftf static check script should return error exit code when check fails - Refactoring from code review --- .../Console/StaticChecksCommand.php | 13 ++++--- .../StaticCheck/StaticCheckInterface.php | 8 +++- .../StaticCheck/StaticCheckListInterface.php | 2 +- .../StaticCheck/StaticChecksList.php | 4 +- .../StaticCheck/TestDependencyCheck.php | 38 +++++++++++++------ 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php index 6b8510695..9757f494e 100644 --- a/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php +++ b/src/Magento/FunctionalTestingFramework/Console/StaticChecksCommand.php @@ -9,18 +9,19 @@ namespace Magento\FunctionalTestingFramework\Console; 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\Input\InputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; +use Exception; class StaticChecksCommand extends Command { /** * Pool of static check scripts to run * - * @var \Magento\FunctionalTestingFramework\StaticCheck\StaticCheckListInterface + * @var StaticCheckListInterface */ private $staticChecksList; @@ -41,8 +42,8 @@ protected function configure() * * @param InputInterface $input * @param OutputInterface $output - * @return int|null|void - * @throws \Exception + * @return int + * @throws Exception */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -51,7 +52,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $errors = []; foreach ($staticCheckObjects as $staticCheck) { - $staticOutput = $staticCheck->execute($input); + $staticCheck->execute($input); + + $staticOutput = $staticCheck->getOutput(); LoggingUtil::getInstance()->getLogger(get_class($staticCheck))->info($staticOutput); $output->writeln($staticOutput); $errors += $staticCheck->getErrors(); diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php index da0bc42de..54bdd3baf 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckInterface.php @@ -16,7 +16,7 @@ interface StaticCheckInterface /** * Executes static check script, returns output. * @param InputInterface $input - * @return string + * @return void */ public function execute(InputInterface $input); @@ -25,4 +25,10 @@ public function execute(InputInterface $input); * @return array */ public function getErrors(); + + /** + * Return string of a short human readable result of the check. For example: "No Dependency errors found." + * @return string + */ + public function getOutput(); } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckListInterface.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckListInterface.php index a8f1a0f6c..867c29e71 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckListInterface.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticCheckListInterface.php @@ -14,7 +14,7 @@ interface StaticCheckListInterface /** * Gets list of static check script instances * - * @return \Magento\FunctionalTestingFramework\StaticCheck\StaticCheckListInterface[] + * @return StaticCheckInterface[] */ public function getStaticChecks(); } diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php index d66d941c6..f3cf20739 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/StaticChecksList.php @@ -16,14 +16,14 @@ class StaticChecksList implements StaticCheckListInterface /** * Property contains all static check scripts. * - * @var \Magento\FunctionalTestingFramework\StaticCheck\StaticCheckListInterface[] + * @var StaticCheckInterface[] */ private $checks; /** * Constructor * - * @param array $scripts + * @param array $checks */ public function __construct(array $checks = []) { diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php index e87773c05..35f4a5ccf 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php @@ -6,20 +6,20 @@ namespace Magento\FunctionalTestingFramework\StaticCheck; -use Magento\FunctionalTestingFramework\Config\Data; use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; +use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; +use Magento\FunctionalTestingFramework\Exceptions\XmlException; use Magento\FunctionalTestingFramework\Page\Handlers\PageObjectHandler; use Magento\FunctionalTestingFramework\Page\Handlers\SectionObjectHandler; -use Magento\FunctionalTestingFramework\Page\Objects\SectionObject; use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; use Magento\FunctionalTestingFramework\Test\Handlers\TestObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionObject; use Magento\FunctionalTestingFramework\Util\ModuleResolver; use Magento\FunctionalTestingFramework\Util\TestGenerator; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; +use Exception; /** * Class TestDependencyCheck @@ -68,11 +68,18 @@ class TestDependencyCheck implements StaticCheckInterface */ private $errors; + /** + * String representing the output summary found after running the execute() function. + * @var string + */ + private $output; + /** * Checks test dependencies, determined by references in tests versus the dependencies listed in the Magento module * * @param InputInterface $input * @return string + * @throws Exception; * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function execute(InputInterface $input) @@ -109,8 +116,8 @@ public function execute(InputInterface $input) $this->errors += $this->findErrorsInFileSet($actionGroupXmlFiles); $this->errors += $this->findErrorsInFileSet($dataXmlFiles); - //print all errors to file - return $this->printErrorsToFile($this->getErrors()); + // hold on to the output and print any errors to a file + $this->output = $this->printErrorsToFile(); } /** @@ -122,12 +129,17 @@ public function getErrors() return $this->errors; } + public function getOutput() + { + return $this->output; + } + /** * Finds all reference errors in given set of files * @param Finder $files * @return array - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException - * @throws \Magento\FunctionalTestingFramework\Exceptions\XmlException + * @throws TestReferenceException + * @throws XmlException */ private function findErrorsInFileSet($files) { @@ -348,8 +360,7 @@ private function buildFileList($modulePaths, $path) * Attempts to find any MFTF entity by its name. Returns null if none are found. * @param string $name * @return mixed - * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException - * @throws \Magento\FunctionalTestingFramework\Exceptions\XmlException + * @throws XmlException */ private function findEntity($name) { @@ -378,24 +389,29 @@ private function findEntity($name) /** * Prints out given errors to file, and returns summary result string - * @param array $errors * @return string */ - private function printErrorsToFile($errors) + 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; } } From 15ea947d517b315edc14ef7b5418f19b4c6f8741 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Mon, 22 Jul 2019 13:42:52 -0500 Subject: [PATCH 48/59] MQE-1606: Mftf static check script should return error exit code when check fails - Add missing phpdoc --- .../StaticCheck/TestDependencyCheck.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php index 35f4a5ccf..a891d42e1 100644 --- a/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php +++ b/src/Magento/FunctionalTestingFramework/StaticCheck/TestDependencyCheck.php @@ -129,6 +129,10 @@ public function getErrors() return $this->errors; } + /** + * Return string of a short human readable result of the check. For example: "No Dependency errors found." + * @return string + */ public function getOutput() { return $this->output; From 6313da3a6a4ad92a805a4b985a72b519a72e5b6f Mon Sep 17 00:00:00 2001 From: Ji Lu <jilu1@adobe.com> Date: Tue, 23 Jul 2019 09:52:38 -0500 Subject: [PATCH 49/59] MQE-1600: MFTF Vault integration - Simplify the logic to handle the storage array --- .../Handlers/CredentialStore.php | 54 +++++++------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index 8385c2ec6..016360752 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -15,13 +15,6 @@ class CredentialStore const ARRAY_KEY_FOR_VAULT = 'vault'; const ARRAY_KEY_FOR_FILE = 'file'; - /** - * Numeric indexed array that defines the access precedence of credential storage - * - * @var array - */ - private static $credStoragePrecedence = [self::ARRAY_KEY_FOR_FILE, self::ARRAY_KEY_FOR_VAULT]; - /** * Credential storage array * @@ -58,6 +51,12 @@ public static function getInstance() */ private function __construct() { + // Initialize file storage + try { + $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); + } catch (TestFrameworkException $e) { + } + // Initialize vault storage $csBaseUrl = getenv('CREDENTIAL_VAULT_BASE_URL'); $csToken = getenv('CREDENTIAL_VAULT_TOKEN'); @@ -71,20 +70,11 @@ private function __construct() } } - // Initialize file storage - try { - $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); - } catch (TestFrameworkException $e) { + if (empty($this->credStorage)) { + throw new TestFrameworkException( + "No credential storage is properly configured. Please configure vault or .credentials file." + ); } - - foreach ($this->credStorage as $cred) { - if (null !== $cred) { - return; - } - } - throw new TestFrameworkException( - "No credential storage is properly configured. Please configure vault or .credentials file." - ); } /** @@ -96,14 +86,12 @@ private function __construct() */ public function getSecret($key) { - // Get secret data from storage according to defined precedence + // 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 - foreach (self::$credStoragePrecedence as $credType) { - if (null !== $this->credStorage[$credType]) { - $value = $this->credStorage[$credType]->getEncryptedValue($key); - if (null !== $value) { - return $value; - } + foreach ($this->credStorage as $storage) { + $value = $storage->getEncryptedValue($key); + if (null !== $value) { + return $value; } } @@ -122,10 +110,8 @@ public function getSecret($key) public function decryptSecretValue($value) { // Loop through storage to decrypt value - foreach (self::$credStoragePrecedence as $credType) { - if (null !== $this->credStorage[$credType]) { - return $this->credStorage[$credType]->getDecryptedValue($value); - } + foreach ($this->credStorage as $storage) { + return $storage->getDecryptedValue($value); } } @@ -138,10 +124,8 @@ public function decryptSecretValue($value) public function decryptAllSecretsInString($string) { // Loop through storage to decrypt all occurrences from input string - foreach (self::$credStoragePrecedence as $credType) { - if (null !== $this->credStorage[$credType]) { - return $this->credStorage[$credType]->getAllDecryptedValuesInString($string); - } + foreach ($this->credStorage as $storage) { + return $storage->getAllDecryptedValuesInString($string); } } } From b8b4d25aedcacf55feb33160aa2652a43feb9ed6 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Tue, 23 Jul 2019 13:53:21 -0500 Subject: [PATCH 50/59] MQE-1639: [DEVDOCS] Best Practices for including HTML Source in Tests - Add content about encoding HTML for use in tests --- docs/test/actions.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/test/actions.md b/docs/test/actions.md index 4a6c3f48e..cbda1f689 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -179,6 +179,18 @@ The following test actions handle data entities using [metadata](../metadata.md) Learn more in [Handling a REST API response](../metadata.md#rest-response). +## Actions specifying HTML values + +To use HTML in actions you must encode the HTML string using a tool. We recommend [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). Using CyberChef or a similar tool is easy. You just need to enter in your HTML string, copy the encoded result, and paste that value into your MFTF test. + +For example, we want to ensure we don't see this HTML: `<h1 class="login-header">` + +After passing `<h1 class="login-header">` through CyberChef we get `<h1 class="login-header">` which can be used in a test like: + +```xml +<dontSeeInSource html="<h1 class="login-header">" stepKey="dontSeeInSource"/> +``` + ## Reference The following list contains reference documentation about all action elements available in the MFTF. @@ -868,7 +880,7 @@ See [dontSeeInSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to search for within the source code. +`html`|string|optional| HTML code to search for within the source code. The value must be encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -876,9 +888,11 @@ Attribute|Type|Use|Description #### Example +You must encode the `html` using a tool such as [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). + ```xml -<!-- Verify that the page does not contain the raw source code `<h1>Sample text</h1>`. --> -<dontSeeInSource userInput="<h1>Sample text</h1>" stepKey="dontSeeInSource"/> +<!-- Verify that the page does not contain the raw source code `<h1 class="login-header">`. --> +<dontSeeInSource html="<h1 class="login-header">" stepKey="dontSeeInSource"/> ``` ### dontSeeInTitle @@ -1922,7 +1936,7 @@ See [seeInPageSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the document. +`html`|string|optional| HTML code to be searched for within the document. The value must be encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1930,9 +1944,11 @@ Attribute|Type|Use|Description #### Example +You must encode the `html` using a tool such as [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). + ```xml -<!-- Verify that the page source contains the string "Sample text". --> -<seeInPageSource userInput="Sample text" stepKey="seeInPageSource"/> +<!-- Verify that the page source contains the raw source code `<h1 class="login-header">`. --> +<seeInPageSource html="<h1 class="login-header">" stepKey="seeInPageSource"/> ``` ### seeInPopup @@ -1960,7 +1976,7 @@ See [seeInSource docs on codeception.com](http://codeception.com/docs/modules/We Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. +`html`|string|optional| HTML code to be searched for within the page source. The value must be encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1968,9 +1984,11 @@ Attribute|Type|Use|Description #### Example +You must encode the `html` using a tool such as [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). + ```xml -<!-- Verify that the page does contains the raw source code `<h1>Sample text</h1>`. --> -<seeInSource userInput="<h1>Sample text</h1>" stepKey="seeInSource"/> +<!-- Verify that the page does contains the raw source code `<h1 class="login-header">`. --> +<seeInSource html="<h1 class="login-header">" stepKey="seeInSource"/> ``` ### seeInTitle From 7925287e2fb966b00336af7934460b3284e00e09 Mon Sep 17 00:00:00 2001 From: Donald Booth <dobooth@adobe.com> Date: Tue, 23 Jul 2019 14:43:41 -0500 Subject: [PATCH 51/59] Small edits. --- docs/test/actions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/test/actions.md b/docs/test/actions.md index cbda1f689..1e2005594 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -181,9 +181,9 @@ Learn more in [Handling a REST API response](../metadata.md#rest-response). ## Actions specifying HTML values -To use HTML in actions you must encode the HTML string using a tool. We recommend [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). Using CyberChef or a similar tool is easy. You just need to enter in your HTML string, copy the encoded result, and paste that value into your MFTF test. +To use HTML in actions you must encode the HTML string. We recommend using [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). Using CyberChef or a similar tool is straightforward: enter in your HTML string, copy the encoded result, and paste that value into your MFTF test. -For example, we want to ensure we don't see this HTML: `<h1 class="login-header">` +For example, we want to ensure that this value is presented as a string and not rendered as a H1 tag: `<h1 class="login-header">` After passing `<h1 class="login-header">` through CyberChef we get `<h1 class="login-header">` which can be used in a test like: @@ -880,7 +880,7 @@ See [dontSeeInSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to search for within the source code. The value must be encoded. See example. +`html`|string|optional| HTML code to search for within the source code. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1976,7 +1976,7 @@ See [seeInSource docs on codeception.com](http://codeception.com/docs/modules/We Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. The value must be encoded. See example. +`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. From da75a64496b93ce7a909349d60f779e4490f16ca Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 24 Jul 2019 11:17:30 -0500 Subject: [PATCH 52/59] MQE-1639: [DEVDOCS] Best Practices for including HTML Source in Tests - Make sure all 4 actions are consistently worded --- docs/test/actions.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/test/actions.md b/docs/test/actions.md index 1e2005594..0179ec70d 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -861,7 +861,7 @@ See [dontSeeInPageSource docs on codeception.com](http://codeception.com/docs/mo Attribute|Type|Use|Description ---|---|---|--- -`userInput`|string|optional| Value for the form field. +`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -870,8 +870,8 @@ Attribute|Type|Use|Description #### Example ```xml -<!-- Verify that the page source does not contain the string "Sample text". --> -<dontSeeInPageSource userInput="Sample text" stepKey="dontSeeInPageSource"/> +<!-- Verify that the page source does not contain the raw source code `<h1 class="login-header">`. --> +<dontSeeInPageSource userInput="<h1 class="login-header">" stepKey="dontSeeInPageSource"/> ``` ### dontSeeInSource @@ -880,7 +880,7 @@ See [dontSeeInSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to search for within the source code. The value must be entity-encoded. See example. +`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -891,7 +891,7 @@ Attribute|Type|Use|Description You must encode the `html` using a tool such as [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). ```xml -<!-- Verify that the page does not contain the raw source code `<h1 class="login-header">`. --> +<!-- Verify that the page source does not contain the raw source code `<h1 class="login-header">`. --> <dontSeeInSource html="<h1 class="login-header">" stepKey="dontSeeInSource"/> ``` @@ -1936,7 +1936,7 @@ See [seeInPageSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the document. The value must be encoded. See example. +`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1987,7 +1987,7 @@ Attribute|Type|Use|Description You must encode the `html` using a tool such as [CyberChef](https://gchq.github.io/CyberChef/#recipe=To_HTML_Entity(false,'Numeric%20entities')). ```xml -<!-- Verify that the page does contains the raw source code `<h1 class="login-header">`. --> +<!-- Verify that the page source contains the raw source code `<h1 class="login-header">`. --> <seeInSource html="<h1 class="login-header">" stepKey="seeInSource"/> ``` From 0c6bd9a1043556c3a556bf687852bb3eaa7add94 Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Wed, 24 Jul 2019 14:14:35 -0500 Subject: [PATCH 53/59] MQE-1639: [DEVDOCS] Best Practices for including HTML Source in Tests #390 - Mark html attribute as required --- docs/test/actions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/test/actions.md b/docs/test/actions.md index 0179ec70d..c3c6f8367 100644 --- a/docs/test/actions.md +++ b/docs/test/actions.md @@ -861,7 +861,7 @@ See [dontSeeInPageSource docs on codeception.com](http://codeception.com/docs/mo Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. +`html`|string|required| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -880,7 +880,7 @@ See [dontSeeInSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. +`html`|string|required| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1936,7 +1936,7 @@ See [seeInPageSource docs on codeception.com](http://codeception.com/docs/module Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. +`html`|string|required| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. @@ -1976,7 +1976,7 @@ See [seeInSource docs on codeception.com](http://codeception.com/docs/modules/We Attribute|Type|Use|Description ---|---|---|--- -`html`|string|optional| HTML code to be searched for within the page source. The value must be entity-encoded. See example. +`html`|string|required| HTML code to be searched for within the page source. The value must be entity-encoded. See example. `stepKey`|string|required| A unique identifier of the action. `skipReadiness`|boolean|optional| A flag to skip the readiness check. `before`|string|optional| `stepKey` of action that must be executed next. From 1359e26b7b432891f365e1cc04b2ff298ab2780d Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Thu, 25 Jul 2019 09:53:28 -0500 Subject: [PATCH 54/59] Revert "Merge pull request #382 from magento/MQE-1600" This reverts commit 4212ad6d0612e14ce2b322787d7c1e20cbf52fed, reversing changes made to fa56508bf05808fbc79bf77917ad4bd5369ae036. --- composer.json | 4 +- composer.lock | 603 +++--------------- ...torageTest.php => CredentialStoreTest.php} | 17 +- etc/config/.credentials.example | 150 ++--- etc/config/.env.example | 4 - .../Handlers/CredentialStore.php | 154 +++-- .../Handlers/SecretStorage/BaseStorage.php | 87 --- .../Handlers/SecretStorage/FileStorage.php | 113 ---- .../Handlers/SecretStorage/VaultStorage.php | 123 ---- .../SecretStorage/VaultTokenAuthStrategy.php | 47 -- .../Test/Util/ActionMergeUtil.php | 3 +- .../Util/TestGenerator.php | 3 +- 12 files changed, 257 insertions(+), 1051 deletions(-) rename dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/{SecretStorage/FileStorageTest.php => CredentialStoreTest.php} (59%) delete mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php delete mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php delete mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php delete mode 100644 src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php diff --git a/composer.json b/composer.json index 24fb91c92..8af401526 100755 --- a/composer.json +++ b/composer.json @@ -10,12 +10,10 @@ }, "require": { "php": "7.0.2||7.0.4||~7.0.6||~7.1.0||~7.2.0||~7.3.0", - "ext-curl": "*", "allure-framework/allure-codeception": "~1.3.0", + "ext-curl": "*", "codeception/codeception": "~2.3.4 || ~2.4.0 ", "consolidation/robo": "^1.0.0", - "csharpru/vault-php": "~3.5.3", - "csharpru/vault-php-guzzle6-transport": "^2.0", "flow/jsonpath": ">0.2", "fzaninotto/faker": "^1.6", "monolog/monolog": "^1.0", diff --git a/composer.lock b/composer.lock index 95f08abcd..ca4e287fc 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": "fb0f9a5c731e02404fb78c95aa647e46", + "content-hash": "d5879be29cb6bbe70ce7e4a42828303a", "packages": [ { "name": "allure-framework/allure-codeception", @@ -168,99 +168,6 @@ ], "time": "2016-10-30T11:50:56+00:00" }, - { - "name": "cache/cache", - "version": "0.4.0", - "source": { - "type": "git", - "url": "https://github.com/php-cache/cache.git", - "reference": "902b2e5b54ea57e3a801437748652228c4c58604" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-cache/cache/zipball/902b2e5b54ea57e3a801437748652228c4c58604", - "reference": "902b2e5b54ea57e3a801437748652228c4c58604", - "shasum": "" - }, - "require": { - "doctrine/cache": "^1.3", - "league/flysystem": "^1.0", - "php": "^5.6 || ^7.0", - "psr/cache": "^1.0", - "psr/log": "^1.0", - "psr/simple-cache": "^1.0" - }, - "conflict": { - "cache/adapter-common": "*", - "cache/apc-adapter": "*", - "cache/apcu-adapter": "*", - "cache/array-adapter": "*", - "cache/chain-adapter": "*", - "cache/doctrine-adapter": "*", - "cache/filesystem-adapter": "*", - "cache/hierarchical-cache": "*", - "cache/illuminate-adapter": "*", - "cache/memcache-adapter": "*", - "cache/memcached-adapter": "*", - "cache/mongodb-adapter": "*", - "cache/predis-adapter": "*", - "cache/psr-6-doctrine-bridge": "*", - "cache/redis-adapter": "*", - "cache/session-handler": "*", - "cache/taggable-cache": "*", - "cache/void-adapter": "*" - }, - "require-dev": { - "cache/integration-tests": "^0.16", - "defuse/php-encryption": "^2.0", - "illuminate/cache": "^5.4", - "mockery/mockery": "^0.9", - "phpunit/phpunit": "^4.0 || ^5.1", - "predis/predis": "^1.0", - "symfony/cache": "dev-master" - }, - "suggest": { - "ext-apc": "APC extension is required to use the APC Adapter", - "ext-apcu": "APCu extension is required to use the APCu Adapter", - "ext-memcache": "Memcache extension is required to use the Memcache Adapter", - "ext-memcached": "Memcached extension is required to use the Memcached Adapter", - "ext-mongodb": "Mongodb extension required to use the Mongodb adapter", - "ext-redis": "Redis extension is required to use the Redis adapter", - "mongodb/mongodb": "Mongodb lib required to use the Mongodb adapter" - }, - "type": "library", - "autoload": { - "psr-4": { - "Cache\\": "src/" - }, - "exclude-from-classmap": [ - "**/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Scherer", - "email": "aequasi@gmail.com", - "homepage": "https://github.com/aequasi" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/nyholm" - } - ], - "description": "Library of all the php-cache adapters", - "homepage": "http://www.php-cache.com/en/latest/", - "keywords": [ - "cache", - "psr6" - ], - "time": "2017-03-28T16:08:48+00:00" - }, { "name": "codeception/codeception", "version": "2.3.9", @@ -761,92 +668,6 @@ "homepage": "https://github.com/container-interop/container-interop", "time": "2017-02-14T19:40:03+00:00" }, - { - "name": "csharpru/vault-php", - "version": "3.5.3", - "source": { - "type": "git", - "url": "https://github.com/CSharpRU/vault-php.git", - "reference": "04be9776310fe7d1afb97795645f95c21e6b4fcf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/CSharpRU/vault-php/zipball/04be9776310fe7d1afb97795645f95c21e6b4fcf", - "reference": "04be9776310fe7d1afb97795645f95c21e6b4fcf", - "shasum": "" - }, - "require": { - "cache/cache": "^0.4.0", - "doctrine/inflector": "~1.1.0", - "guzzlehttp/promises": "^1.3", - "guzzlehttp/psr7": "^1.4", - "psr/cache": "^1.0", - "psr/log": "^1.0", - "weew/helpers-array": "^1.3" - }, - "require-dev": { - "codacy/coverage": "^1.1", - "codeception/codeception": "^2.2", - "csharpru/vault-php-guzzle6-transport": "~2.0", - "php-vcr/php-vcr": "^1.3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Vault\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yaroslav Lukyanov", - "email": "c_sharp@mail.ru" - } - ], - "description": "Best Vault client for PHP that you can find", - "time": "2018-04-28T04:52:17+00:00" - }, - { - "name": "csharpru/vault-php-guzzle6-transport", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/CSharpRU/vault-php-guzzle6-transport.git", - "reference": "33c392120ac9f253b62b034e0e8ffbbdb3513bd8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/CSharpRU/vault-php-guzzle6-transport/zipball/33c392120ac9f253b62b034e0e8ffbbdb3513bd8", - "reference": "33c392120ac9f253b62b034e0e8ffbbdb3513bd8", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "~6.2", - "guzzlehttp/promises": "^1.3", - "guzzlehttp/psr7": "^1.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "VaultTransports\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Yaroslav Lukyanov", - "email": "c_sharp@mail.ru" - } - ], - "description": "Guzzle6 transport for Vault PHP client", - "time": "2019-03-10T06:17:37+00:00" - }, { "name": "dflydev/dot-access-data", "version": "v1.1.0", @@ -974,143 +795,6 @@ ], "time": "2017-02-24T16:22:25+00:00" }, - { - "name": "doctrine/cache", - "version": "v1.6.2", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", - "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", - "shasum": "" - }, - "require": { - "php": "~5.5|~7.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "phpunit/phpunit": "~4.8|~5.0", - "predis/predis": "~1.0", - "satooshi/php-coveralls": "~0.6" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Caching library offering an object-oriented API for many cache backends", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "cache", - "caching" - ], - "time": "2017-07-22T12:49:21+00:00" - }, - { - "name": "doctrine/inflector", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/inflector.git", - "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", - "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", - "shasum": "" - }, - "require": { - "php": ">=5.3.2" - }, - "require-dev": { - "phpunit/phpunit": "4.*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Inflector\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "inflection", - "pluralize", - "singularize", - "string" - ], - "time": "2015-11-06T14:35:42+00:00" - }, { "name": "doctrine/instantiator", "version": "1.0.5", @@ -1924,90 +1608,6 @@ ], "time": "2017-05-10T09:20:27+00:00" }, - { - "name": "league/flysystem", - "version": "1.0.53", - "source": { - "type": "git", - "url": "https://github.com/thephpleague/flysystem.git", - "reference": "08e12b7628f035600634a5e76d95b5eb66cea674" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/08e12b7628f035600634a5e76d95b5eb66cea674", - "reference": "08e12b7628f035600634a5e76d95b5eb66cea674", - "shasum": "" - }, - "require": { - "ext-fileinfo": "*", - "php": ">=5.5.9" - }, - "conflict": { - "league/flysystem-sftp": "<1.0.6" - }, - "require-dev": { - "phpspec/phpspec": "^3.4", - "phpunit/phpunit": "^5.7.10" - }, - "suggest": { - "ext-fileinfo": "Required for MimeType", - "ext-ftp": "Allows you to use FTP server storage", - "ext-openssl": "Allows you to use FTPS server storage", - "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", - "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", - "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", - "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", - "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", - "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", - "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", - "league/flysystem-webdav": "Allows you to use WebDAV storage", - "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", - "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", - "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "League\\Flysystem\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Frank de Jonge", - "email": "info@frenky.net" - } - ], - "description": "Filesystem abstraction: Many filesystems, one API.", - "keywords": [ - "Cloud Files", - "WebDAV", - "abstraction", - "aws", - "cloud", - "copy.com", - "dropbox", - "file systems", - "files", - "filesystem", - "filesystems", - "ftp", - "rackspace", - "remote", - "s3", - "sftp", - "storage" - ], - "time": "2019-06-18T20:09:29+00:00" - }, { "name": "monolog/monolog", "version": "1.24.0", @@ -3079,52 +2679,6 @@ "abandoned": true, "time": "2018-08-09T05:50:03+00:00" }, - { - "name": "psr/cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "time": "2016-08-06T20:24:11+00:00" - }, { "name": "psr/container", "version": "1.0.0", @@ -3271,54 +2825,6 @@ ], "time": "2016-10-10T12:19:37+00:00" }, - { - "name": "psr/simple-cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\SimpleCache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interfaces for simple caching", - "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" - ], - "time": "2017-10-23T01:57:42+00:00" - }, { "name": "ramsey/uuid", "version": "3.8.0", @@ -4891,43 +4397,6 @@ "validate" ], "time": "2018-01-29T19:49:41+00:00" - }, - { - "name": "weew/helpers-array", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/weew/helpers-array.git", - "reference": "9bff63111f9765b4277750db8d276d92b3e16ed0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/weew/helpers-array/zipball/9bff63111f9765b4277750db8d276d92b3e16ed0", - "reference": "9bff63111f9765b4277750db8d276d92b3e16ed0", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "^4.7", - "satooshi/php-coveralls": "^0.6.1" - }, - "type": "library", - "autoload": { - "files": [ - "src/array.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Maxim Kott", - "email": "maximkott@gmail.com" - } - ], - "description": "Useful collection of php array helpers.", - "time": "2016-07-21T11:18:01+00:00" } ], "packages-dev": [ @@ -5087,6 +4556,76 @@ "description": "Experimental Mocking Framework powered by Aspects", "time": "2018-10-07T16:21:11+00:00" }, + { + "name": "doctrine/cache", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "reference": "eb152c5100571c7a45470ff2a35095ab3f3b900b", + "shasum": "" + }, + "require": { + "php": "~5.5|~7.0" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.8|~5.0", + "predis/predis": "~1.0", + "satooshi/php-coveralls": "~0.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2017-07-22T12:49:21+00:00" + }, { "name": "gitonomy/gitlib", "version": "v1.0.4", diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php similarity index 59% rename from dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php rename to dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php index 7e5824c8e..a451f8dc9 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/SecretStorage/FileStorageTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Handlers/CredentialStoreTest.php @@ -4,34 +4,33 @@ * See COPYING.txt for license details. */ -namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers\SecretStorage; +namespace tests\unit\Magento\FunctionalTestFramework\DataGenerator\Handlers; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; +use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore; use Magento\FunctionalTestingFramework\Util\MagentoTestCase; use AspectMock\Test as AspectMock; -class FileStorageTest extends MagentoTestCase +class CredentialStoreTest extends MagentoTestCase { /** - * Test basic encryption/decryption functionality in FileStorage class. + * Test basic encryption/decryption functionality in CredentialStore class. */ public function testBasicEncryptDecrypt() { - $testKey = 'magento/myKey'; + $testKey = 'myKey'; $testValue = 'myValue'; - AspectMock::double(FileStorage::class, [ + AspectMock::double(CredentialStore::class, [ 'readInCredentialsFile' => ["$testKey=$testValue"] ]); - $fileStorage = new FileStorage(); - $encryptedCred = $fileStorage->getEncryptedValue($testKey); + $encryptedCred = CredentialStore::getInstance()->getSecret($testKey); // assert the value we've gotten is in fact not identical to our test value $this->assertNotEquals($testValue, $encryptedCred); - $actualValue = $fileStorage->getDecryptedValue($encryptedCred); + $actualValue = CredentialStore::getInstance()->decryptSecretValue($encryptedCred); // assert that we are able to successfully decrypt our secret value $this->assertEquals($testValue, $actualValue); diff --git a/etc/config/.credentials.example b/etc/config/.credentials.example index d9c73ac66..ea8b03480 100644 --- a/etc/config/.credentials.example +++ b/etc/config/.credentials.example @@ -1,75 +1,75 @@ -#magento/magento/carriers_fedex_account= -#magento/carriers_fedex_meter_number= -#magento/carriers_fedex_key= -#magento/carriers_fedex_password= - -#magento/carriers_ups_password= -#magento/carriers_ups_username= -#magento/carriers_ups_access_license_number= -#magento/carriers_ups_shipper_number= - -#magento/carriers_usps_userid= -#magento/carriers_usps_password= - -#magento/carriers_dhl_id_us= -#magento/carriers_dhl_password_us= -#magento/carriers_dhl_account_us= - -#magento/carriers_dhl_id_eu= -#magento/carriers_dhl_password_eu= -#magento/carriers_dhl_account_eu= - - -#magento/payment_authorizenet_login= -#magento/payment_authorizenet_trans_key= -#magento/payment_authorizenet_trans_md5= - -#magento/authorizenet_fraud_review_login= -#magento/authorizenet_fraud_review_trans_key= -#magento/authorizenet_fraud_review_md5= - -#magento/braintree_enabled_fraud_merchant_account_id= -#magento/braintree_enabled_fraud_merchant_id= -#magento/braintree_enabled_fraud_public_key= -#magento/braintree_enabled_fraud_private_key= - -#magento/braintree_disabled_fraud_merchant_account_id= -#magento/braintree_disabled_fraud_merchant_id= -#magento/braintree_disabled_fraud_public_key= -#magento/braintree_disabled_fraud_private_key= - -#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_business_account= -#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_username= -#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_password= -#magento/payment_paypal_group_all_in_one_wpp_usuk_wpp_required_settings_wpp_and_express_checkout_api_signature= -#magento/payment_paypal_express_merchant_id= - -#magento/payflow_pro_fraud_protection_enabled_business_account= -#magento/payflow_pro_fraud_protection_enabled_partner= -#magento/payflow_pro_fraud_protection_enabled_user= -#magento/payflow_pro_fraud_protection_enabled_pwd= -#magento/payflow_pro_fraud_protection_enabled_vendor= - -#magento/payflow_pro_business_account= -#magento/payflow_pro_partner= -#magento/payflow_pro_user= -#magento/payflow_pro_pwd= -#magento/payflow_pro_vendor= - -#magento/payflow_link_business_account_email= -#magento/payflow_link_partner= -#magento/payflow_link_user= -#magento/payflow_link_password= -#magento/payflow_link_vendor= - -#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_business_account= -#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_username= -#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_password= -#magento/payment_paypal_group_all_in_one_payments_pro_hosted_solution_with_express_checkout_pphs_required_settings_pphs_required_settings_pphs_api_signature= - -#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_business_account= -#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_username= -#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_password= -#magento/payment_paypal_alternative_payment_methods_express_checkout_us_express_checkout_required_express_checkout_required_express_checkout_api_signature= - -#magento/fraud_protection_signifyd_api_key= \ No newline at end of file +#carriers/fedex/account= +#carriers/fedex/meter_number= +#carriers/fedex/key= +#carriers/fedex/password= + +#carriers/ups/password= +#carriers/ups/username= +#carriers/ups/access_license_number= +#carriers/ups/shipper_number= + +#carriers/usps/userid= +#carriers/usps/password= + +#carriers_dhl_id_us= +#carriers_dhl_password_us= +#carriers_dhl_account_us= + +#carriers_dhl_id_eu= +#carriers_dhl_password_eu= +#carriers_dhl_account_eu= + + +#payment_authorizenet_login= +#payment_authorizenet_trans_key= +#payment_authorizenet_trans_md5= + +#authorizenet_fraud_review_login= +#authorizenet_fraud_review_trans_key= +#authorizenet_fraud_review_md5= + +#braintree_enabled_fraud_merchant_account_id= +#braintree_enabled_fraud_merchant_id= +#braintree_enabled_fraud_public_key= +#braintree_enabled_fraud_private_key= + +#braintree_disabled_fraud_merchant_account_id= +#braintree_disabled_fraud_merchant_id= +#braintree_disabled_fraud_public_key= +#braintree_disabled_fraud_private_key= + +#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/business_account= +#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_username= +#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_password= +#payment/paypal_group_all_in_one/wpp_usuk/wpp_required_settings/wpp_and_express_checkout/api_signature= +#payment/paypal_express/merchant_id= + +#payflow_pro_fraud_protection_enabled_business_account= +#payflow_pro_fraud_protection_enabled_partner= +#payflow_pro_fraud_protection_enabled_user= +#payflow_pro_fraud_protection_enabled_pwd= +#payflow_pro_fraud_protection_enabled_vendor= + +#payflow_pro_business_account= +#payflow_pro_partner= +#payflow_pro_user= +#payflow_pro_pwd= +#payflow_pro_vendor= + +#payflow_link_business_account_email= +#payflow_link_partner= +#payflow_link_user= +#payflow_link_password= +#payflow_link_vendor= + +#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/business_account= +#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_username= +#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_password= +#payment/paypal_group_all_in_one/payments_pro_hosted_solution_with_express_checkout/pphs_required_settings/pphs_required_settings_pphs/api_signature= + +#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/business_account= +#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_username= +#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_password= +#payment/paypal_alternative_payment_methods/express_checkout_us/express_checkout_required/express_checkout_required_express_checkout/api_signature= + +#fraud_protection/signifyd/api_key= \ No newline at end of file diff --git a/etc/config/.env.example b/etc/config/.env.example index cc82ae447..5dc7168be 100644 --- a/etc/config/.env.example +++ b/etc/config/.env.example @@ -30,10 +30,6 @@ BROWSER=chrome #MAGENTO_RESTAPI_SERVER_PORT=8080 #MAGENTO_RESTAPI_SERVER_PROTOCOL=https -#*** Uncomment and set vault base url and access token if you want to use vault to manage _CREDS secrets ***# -#CREDENTIAL_VAULT_BASE_URL= -#CREDENTIAL_VAULT_TOKEN= - #*** Uncomment these properties to set up a dev environment with symlinked projects ***# #TESTS_BP= #FW_BP= diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php index 016360752..a83540683 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/CredentialStore.php @@ -6,34 +6,47 @@ namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers; +use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; +use Magento\FunctionalTestingFramework\Console\BuildProjectCommand; use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\FileStorage; -use Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage\VaultStorage; +use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; class CredentialStore { - const ARRAY_KEY_FOR_VAULT = 'vault'; - const ARRAY_KEY_FOR_FILE = 'file'; + const ENCRYPTION_ALGO = "AES-256-CBC"; /** - * Credential storage array + * Singleton instance * - * @var array + * @var CredentialStore */ - private $credStorage = []; + private static $INSTANCE = null; /** - * Singleton instance + * Initial vector for open_ssl encryption. * - * @var CredentialStore + * @var string */ - private static $INSTANCE = null; + private $iv = null; + + /** + * Key for open_ssl encryption/decryption + * + * @var string + */ + private $encodedKey = null; + + /** + * Key/Value paris of credential names and their corresponding values + * + * @var array + */ + private $credentials = []; /** * Static singleton getter for CredentialStore Instance * * @return CredentialStore - * @throws TestFrameworkException */ public static function getInstance() { @@ -45,87 +58,120 @@ public static function getInstance() } /** - * CredentialStore constructor + * CredentialStore constructor. + */ + private function __construct() + { + $this->encodedKey = base64_encode(openssl_random_pseudo_bytes(16)); + $this->iv = substr(hash('sha256', $this->encodedKey), 0, 16); + $creds = $this->readInCredentialsFile(); + $this->credentials = $this->encryptCredFileContents($creds); + } + + /** + * Returns the value of a secret based on corresponding key * + * @param string $key + * @return string|null * @throws TestFrameworkException */ - private function __construct() + public function getSecret($key) { - // Initialize file storage - try { - $this->credStorage[self::ARRAY_KEY_FOR_FILE] = new FileStorage(); - } catch (TestFrameworkException $e) { + if (!array_key_exists($key, $this->credentials)) { + throw new TestFrameworkException( + "{$key} not defined in .credentials, please provide a value in order to use this secret in a test." + ); } - // Initialize vault storage - $csBaseUrl = getenv('CREDENTIAL_VAULT_BASE_URL'); - $csToken = getenv('CREDENTIAL_VAULT_TOKEN'); - if ($csBaseUrl !== false && $csToken !== false) { - try { - $this->credStorage[self::ARRAY_KEY_FOR_VAULT] = new VaultStorage( - rtrim($csBaseUrl, '/'), - $csToken - ); - } catch (TestFrameworkException $e) { - } + // log here for verbose config + if (MftfApplicationConfig::getConfig()->verboseEnabled()) { + LoggingUtil::getInstance()->getLogger(CredentialStore::class)->debug( + "retrieving secret for key name {$key}" + ); } - if (empty($this->credStorage)) { + return $this->credentials[$key] ?? null; + } + + /** + * Private function which reads in secret key/values from .credentials file and stores in memory as key/value pair. + * + * @return array + * @throws TestFrameworkException + */ + private function readInCredentialsFile() + { + $credsFilePath = str_replace( + '.credentials.example', + '.credentials', + BuildProjectCommand::CREDENTIALS_FILE_PATH + ); + + if (!file_exists($credsFilePath)) { throw new TestFrameworkException( - "No credential storage is properly configured. Please configure vault or .credentials file." + "Cannot find .credentials file, please create in " + . TESTS_BP . " in order to reference sensitive information" ); } + + return file($credsFilePath, FILE_IGNORE_NEW_LINES); } /** - * Get encrypted value by key + * Function which takes the contents of the credentials file and encrypts the entries. * - * @param string $key - * @return string|null - * @throws TestFrameworkException + * @param array $credContents + * @return array */ - public function getSecret($key) + private function encryptCredFileContents($credContents) { - // 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 - foreach ($this->credStorage as $storage) { - $value = $storage->getEncryptedValue($key); - if (null !== $value) { - return $value; + $encryptedCreds = []; + foreach ($credContents as $credValue) { + if (substr($credValue, 0, 1) === '#' || empty($credValue)) { + continue; + } + + list($key, $value) = explode("=", $credValue, 2); + if (!empty($value)) { + $encryptedCreds[$key] = openssl_encrypt( + $value, + self::ENCRYPTION_ALGO, + $this->encodedKey, + 0, + $this->iv + ); } } - throw new TestFrameworkException( - "\"{$key}\" not defined in vault or .credentials file, " - . "please provide a value in order to use this secret in a test." - ); + return $encryptedCreds; } /** - * Return decrypted input value + * Takes a value encrypted at runtime and descrypts using the object's initial vector. * * @param string $value * @return string */ public function decryptSecretValue($value) { - // Loop through storage to decrypt value - foreach ($this->credStorage as $storage) { - return $storage->getDecryptedValue($value); - } + return openssl_decrypt($value, self::ENCRYPTION_ALGO, $this->encodedKey, 0, $this->iv); } /** - * Return decrypted values for all occurrences from input string + * Takes a string that contains encrypted data at runtime and decrypts each value. * * @param string $string * @return mixed */ public function decryptAllSecretsInString($string) { - // Loop through storage to decrypt all occurrences from input string - foreach ($this->credStorage as $storage) { - return $storage->getAllDecryptedValuesInString($string); + $newString = $string; + foreach ($this->credentials as $name => $secretValue) { + if (strpos($newString, $secretValue) !== false) { + $decryptedValue = $this->decryptSecretValue($secretValue); + $newString = str_replace($secretValue, $decryptedValue, $newString); + } } + return $newString; } } diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php deleted file mode 100644 index cb892a545..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/BaseStorage.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; - -abstract class BaseStorage -{ - const ENCRYPTION_ALGO = "AES-256-CBC"; - - /** - * Initial vector for open_ssl encryption - * - * @var string - */ - protected static $iv = null; - - /** - * Key for open_ssl encryption/decryption - * - * @var string - */ - protected static $encodedKey = null; - - /** - * Accessed key/value secret data pairs - * - * @var array - */ - protected static $cachedSecretData = []; - - /** - * BaseStorage constructor - */ - public function __construct() - { - if (null === self::$encodedKey) { - self::$encodedKey = base64_encode(openssl_random_pseudo_bytes(16)); - self::$iv = substr(hash('sha256', self::$encodedKey), 0, 16); - } - } - - /** - * Returns the encrypted value based on corresponding key - * - * @param string $key - * @return string|null - */ - public function getEncryptedValue($key) - { - if (!array_key_exists($key, self::$cachedSecretData)) { - return null; - } - return self::$cachedSecretData[$key] ?? null; - } - - /** - * Takes a value encrypted at runtime and decrypts it using the object's initial vector - * - * @param string $value - * @return string - */ - public 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 - * - * @param string $string - * @return mixed - */ - public function getAllDecryptedValuesInString($string) - { - $newString = $string; - foreach (self::$cachedSecretData as $key => $secretValue) { - if (strpos($newString, $secretValue) !== false) { - $decryptedValue = self::getDecryptedValue($secretValue); - $newString = str_replace($secretValue, $decryptedValue, $newString); - } - } - return $newString; - } -} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php deleted file mode 100644 index 064610c79..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/FileStorage.php +++ /dev/null @@ -1,113 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; - -use Magento\FunctionalTestingFramework\Console\BuildProjectCommand; -use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; - -class FileStorage extends BaseStorage -{ - /** - * Key/value secret data pairs parsed from file - * - * @var array - */ - private $secretData = []; - - /** - * FileStorage constructor - * @throws TestFrameworkException - */ - public function __construct() - { - parent::__construct(); - $creds = $this->readInCredentialsFile(); - $this->secretData = $this->encryptCredFileContents($creds); - } - - /** - * Returns the value of a secret based on corresponding key - * - * @param string $key - * @return string|null - */ - public function getEncryptedValue($key) - { - $value = null; - // Check if secret is in cached array - if (null !== ($value = parent::getEncryptedValue($key))) { - return $value; - } - - // log here for verbose config - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(FileStorage::class)->debug( - "retrieving secret for key name {$key} from file" - ); - } - - // Retrieve from file storage - if (array_key_exists($key, $this->secretData) && (null !== ($value = $this->secretData[$key]))) { - parent::$cachedSecretData[$key] = $value; - } - - return $value; - } - - /** - * Private function which reads in secret key/values from .credentials file and stores in memory as key/value pair - * - * @return array - * @throws TestFrameworkException - */ - private function readInCredentialsFile() - { - $credsFilePath = str_replace( - '.credentials.example', - '.credentials', - BuildProjectCommand::CREDENTIALS_FILE_PATH - ); - - if (!file_exists($credsFilePath)) { - throw new TestFrameworkException( - "Credential file is not used: .credentials file not found in " . TESTS_BP - ); - } - - return file($credsFilePath, FILE_IGNORE_NEW_LINES); - } - - /** - * Function which takes the contents of the credentials file and encrypts the entries - * - * @param array $credContents - * @return array - */ - private function encryptCredFileContents($credContents) - { - $encryptedCreds = []; - foreach ($credContents as $credValue) { - if (substr($credValue, 0, 1) === '#' || empty($credValue)) { - continue; - } - - list($key, $value) = explode("=", $credValue, 2); - if (!empty($value)) { - $encryptedCreds[$key] = openssl_encrypt( - $value, - parent::ENCRYPTION_ALGO, - parent::$encodedKey, - 0, - parent::$iv - ); - } - } - return $encryptedCreds; - } -} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php deleted file mode 100644 index de80b83e3..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultStorage.php +++ /dev/null @@ -1,123 +0,0 @@ -<?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\Exceptions\TestFrameworkException; -use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; -use Vault\Client; -use VaultTransports\Guzzle6Transport; - -class VaultStorage extends BaseStorage -{ - const MFTF_PATH = '/mftf'; - /** - * Adobe Vault - */ - const BASE_PATH = '/dx_magento_qe'; - const KV_DATA = 'data'; - - /** - * Vault client - * - * @var Client - */ - private $client = null; - - /** - * Vault token - * - * @var string - */ - private $token; - - /** - * CredentialVault constructor - * - * @param string $baseUrl - * @param string $token - * @throws TestFrameworkException - */ - public function __construct($baseUrl, $token) - { - parent::__construct(); - if (null === $this->client) { - // Creating the client using Guzzle6 Transport and passing a custom url - $this->client = new Client(new Guzzle6Transport(['base_uri' => $baseUrl])); - } - $this->token = $token; - if (!$this->authenticated()) { - throw new TestFrameworkException("Credential vault is not used: cannot authenticate"); - } - } - - /** - * Returns the value of a secret based on corresponding key - * - * @param string $key - * @return string|null - */ - 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(VaultStorage::class)->debug( - "Retrieving secret for key name {$key} from vault" - ); - } - - $reValue = null; - try { - // Split vendor/key to construct secret path - list($vendor, $key) = explode('/', trim($key, '/'), 2); - $url = self::BASE_PATH - . (empty(self::KV_DATA) ? '' : '/' . self::KV_DATA) - . self::MFTF_PATH - . '/' - . $vendor - . '/' - . $key; - // Read value by key from vault - $value = $this->client->read($url)->getData()[self::KV_DATA][$key]; - // Encrypt value for return - $reValue = openssl_encrypt($value, parent::ENCRYPTION_ALGO, parent::$encodedKey, 0, parent::$iv); - parent::$cachedSecretData[$key] = $reValue; - } catch (\Exception $e) { - if (MftfApplicationConfig::getConfig()->verboseEnabled()) { - LoggingUtil::getInstance()->getLogger(VaultStorage::class)->debug( - "Unable to read secret for key name {$key} from vault" - ); - } - } - return $reValue; - } - - /** - * Check if vault token is valid - * - * @return boolean - */ - private function authenticated() - { - try { - // Authenticating using token auth backend - $authenticated = $this->client - ->setAuthenticationStrategy(new VaultTokenAuthStrategy($this->token)) - ->authenticate(); - - if ($authenticated) { - return true; - } - } catch (\Exception $e) { - } - return false; - } -} diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php deleted file mode 100644 index 716344ca1..000000000 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Handlers/SecretStorage/VaultTokenAuthStrategy.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\FunctionalTestingFramework\DataGenerator\Handlers\SecretStorage; - -use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException; -use Vault\AuthenticationStrategies\AbstractAuthenticationStrategy; -use Vault\ResponseModels\Auth; - -/** - * Class VaultTokenAuthStrategy - */ -class VaultTokenAuthStrategy extends AbstractAuthenticationStrategy -{ - /** - * @var string - */ - protected $token; - - /** - * VaultTokenAuthStrategy constructor - * - * @param string $token - */ - public function __construct($token) - { - $this->token = $token; - } - - /** - * Returns auth for further interactions with Vault - * - * @return Auth - * @throws TestFrameworkException - */ - public function authenticate() - { - try { - return new Auth(['clientToken' => $this->token]); - } catch (\Exception $e) { - throw new TestFrameworkException("Cannot authenticate Vault token."); - } - } -} diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php index cd81ade24..2a939a8c7 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionMergeUtil.php @@ -31,7 +31,6 @@ class ActionMergeUtil const DEFAULT_WAIT_ORDER = 'after'; const APPROVED_ACTIONS = ['fillField', 'magentoCLI', 'field']; const SECRET_MAPPING = ['fillField' => 'fillSecretField', 'magentoCLI' => 'magentoCLISecret']; - const CREDS_REGEX = "/{{_CREDS\.([\w|\/]+)}}/"; /** * Array holding final resulting steps @@ -150,7 +149,7 @@ private function actionAttributeContainsSecretRef($actionAttributes) return $this->actionAttributeContainsSecretRef($actionAttribute); } - preg_match_all(self::CREDS_REGEX, $actionAttribute, $matches); + preg_match_all("/{{_CREDS\.([\w]+)}}/", $actionAttribute, $matches); if (!empty($matches[0])) { return true; diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index beff2bd9f..d07c5e1e0 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -24,7 +24,6 @@ use Magento\FunctionalTestingFramework\Test\Util\ActionObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\TestObjectExtractor; use Magento\FunctionalTestingFramework\Util\Filesystem\DirSetupUtil; -use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; /** * Class TestGenerator @@ -1902,7 +1901,7 @@ private function resolveAllRuntimeReferences($args) { $runtimeReferenceRegex = [ "/{{_ENV\.([\w]+)}}/" => 'getenv', - ActionMergeUtil::CREDS_REGEX => 'CredentialStore::getInstance()->getSecret' + "/{{_CREDS\.([\w]+)}}/" => 'CredentialStore::getInstance()->getSecret' ]; $argResult = $args; From ee039513e4c12528899f1c8e05f9c7777c4f569e Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Thu, 25 Jul 2019 11:20:37 -0500 Subject: [PATCH 55/59] MQE-1636: [GENERATOR] Page Source Actions are not quoted properly --- .../Resources/BasicFunctionalTest.txt | 12 ++++-- .../Resources/DataReplacementTest.txt | 36 +++++++++++++++++ .../Resources/PersistedReplacementTest.txt | 12 ++++++ .../TestModule/Test/BasicFunctionalTest.xml | 12 ++++-- .../TestModule/Test/DataReplacementTest.xml | 40 +++++++++++++++++++ .../Test/PersistedReplacementTest.xml | 16 ++++++++ .../TestModule/Test/XmlDuplicateTest.xml | 12 +++--- .../Test/Objects/ActionObject.php | 3 +- .../Test/etc/Actions/dontSeeActions.xsd | 2 +- .../Util/TestGenerator.php | 5 +-- 10 files changed, 131 insertions(+), 19 deletions(-) diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index fc4284005..940ec9f3e 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -92,8 +92,10 @@ class BasicFunctionalTestCest $I->dontSeeElementInDOM(".functionalTestSelector"); // stepKey: dontSeeElementInDOMKey1 $I->dontSeeInCurrentUrl("/functionalUrl"); // stepKey: dontSeeInCurrentUrlKey1 $I->dontSeeInField(".functionalTestSelector"); // stepKey: dontSeeInFieldKey1 - $I->dontSeeInPageSource("someInput"); // stepKey: dontSeeInPageSourceKey1 - $I->dontSeeInSource("<myHtmlHere>"); // stepKey: dontSeeInSourceKey1 + $I->dontSeeInPageSource("Cosmo Kramer"); // stepKey: dontSeeInPageSourceKey1 + $I->dontSeeInPageSource("<p>Jerry Seinfeld</p>"); // stepKey: dontSeeInPageSourceKey2 + $I->dontSeeInSource("Cosmo Kramer"); // stepKey: dontSeeInSourceKey1 + $I->dontSeeInSource("<p>Jerry Seinfeld</p>"); // stepKey: dontSeeInSourceKey2 $I->dontSeeInTitle("someInput"); // stepKey: dontSeeInTitleKey1 $I->dontSeeLink("someInput", "/functionalUrl"); // stepKey: dontSeeLinkKey1 $I->dontSeeOptionIsSelected(".functionalTestSelector", "someInput"); // stepKey: dontSeeOptionIsSelectedKey1 @@ -146,9 +148,11 @@ class BasicFunctionalTestCest $I->seeElementInDOM(".functionalTestSelector"); // stepKey: seeElementInDOMKey1 $I->seeInCurrentUrl("/functionalUrl"); // stepKey: seeInCurrentUrlKey1 $I->seeInField(".functionalTestSelector", "someInput"); // stepKey: seeInFieldKey1 - $I->seeInPageSource("<myHtmlHere>"); // stepKey: seeInPageSourceKey1 + $I->seeInPageSource("Home Page"); // stepKey: seeInPageSourceKey1 + $I->seeInPageSource("<h1 class=\"page-title\">"); // stepKey: seeInPageSourceKey2 $I->seeInPopup("someInput"); // stepKey: seeInPopupKey1 - $I->seeInSource("<myHtmlHere>"); // stepKey: seeInSourceKey1 + $I->seeInSource("Home Page"); // stepKey: seeInSourceKey1 + $I->seeInSource("<h1 class=\"page-title\">"); // stepKey: seeInSourceKey2 $I->seeInTitle("someInput"); // stepKey: seeInTitleKey1 $I->seeLink("someInput", "/functionalUrl"); // stepKey: seeLinkKey1 $I->seeNumberOfElements(".functionalTestSelector"); // stepKey: seeNumberOfElementsKey1 diff --git a/dev/tests/verification/Resources/DataReplacementTest.txt b/dev/tests/verification/Resources/DataReplacementTest.txt index 4eb305e32..8e8eb70a6 100644 --- a/dev/tests/verification/Resources/DataReplacementTest.txt +++ b/dev/tests/verification/Resources/DataReplacementTest.txt @@ -53,5 +53,41 @@ class DataReplacementTestCest $I->fillField(".selector", "0"); // stepKey: insertZero $insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness"); // stepKey: insertCommand $I->comment($insertCommand); + $I->seeInPageSource("StringBefore John StringAfter"); // stepKey: htmlReplace1 + $I->seeInPageSource("#John"); // stepKey: htmlReplace2 + $I->seeInPageSource("StringBefore " . msq("uniqueData") . "John StringAfter"); // stepKey: htmlReplace3 + $I->seeInPageSource("#" . msq("uniqueData") . "John"); // stepKey: htmlReplace4 + $I->seeInPageSource("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); // stepKey: htmlReplace5 + $I->seeInPageSource("StringBefore Doe" . msq("uniqueData") . " StringAfter"); // stepKey: htmlReplace6 + $I->seeInPageSource("#Doe" . msq("uniqueData")); // stepKey: htmlReplace7 + $I->seeInPageSource("#element"); // stepKey: htmlReplace8 + $I->seeInPageSource("StringBefore #element StringAfter"); // stepKey: htmlReplace9 + $I->dontSeeInPageSource("StringBefore John StringAfter"); // stepKey: htmlReplace10 + $I->dontSeeInPageSource("#John"); // stepKey: htmlReplace11 + $I->dontSeeInPageSource("StringBefore " . msq("uniqueData") . "John StringAfter"); // stepKey: htmlReplace12 + $I->dontSeeInPageSource("#" . msq("uniqueData") . "John"); // stepKey: htmlReplace13 + $I->dontSeeInPageSource("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); // stepKey: htmlReplace14 + $I->dontSeeInPageSource("StringBefore Doe" . msq("uniqueData") . " StringAfter"); // stepKey: htmlReplace15 + $I->dontSeeInPageSource("#Doe" . msq("uniqueData")); // stepKey: htmlReplace16 + $I->dontSeeInPageSource("#element"); // stepKey: htmlReplace17 + $I->dontSeeInPageSource("StringBefore #element StringAfter"); // stepKey: htmlReplace18 + $I->seeInSource("StringBefore John StringAfter"); // stepKey: htmlReplace19 + $I->seeInSource("#John"); // stepKey: htmlReplace20 + $I->seeInSource("StringBefore " . msq("uniqueData") . "John StringAfter"); // stepKey: htmlReplace21 + $I->seeInSource("#" . msq("uniqueData") . "John"); // stepKey: htmlReplace22 + $I->seeInSource("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); // stepKey: htmlReplace23 + $I->seeInSource("StringBefore Doe" . msq("uniqueData") . " StringAfter"); // stepKey: htmlReplace24 + $I->seeInSource("#Doe" . msq("uniqueData")); // stepKey: htmlReplace25 + $I->seeInSource("#element"); // stepKey: htmlReplace26 + $I->seeInSource("StringBefore #element StringAfter"); // stepKey: htmlReplace27 + $I->dontSeeInSource("StringBefore John StringAfter"); // stepKey: htmlReplace28 + $I->dontSeeInSource("#John"); // stepKey: htmlReplace29 + $I->dontSeeInSource("StringBefore " . msq("uniqueData") . "John StringAfter"); // stepKey: htmlReplace30 + $I->dontSeeInSource("#" . msq("uniqueData") . "John"); // stepKey: htmlReplace31 + $I->dontSeeInSource("#" . msq("uniqueData") . "John#" . msq("uniqueData") . "John"); // stepKey: htmlReplace32 + $I->dontSeeInSource("StringBefore Doe" . msq("uniqueData") . " StringAfter"); // stepKey: htmlReplace33 + $I->dontSeeInSource("#Doe" . msq("uniqueData")); // stepKey: htmlReplace34 + $I->dontSeeInSource("#element"); // stepKey: htmlReplace35 + $I->dontSeeInSource("StringBefore #element StringAfter"); // stepKey: htmlReplace36 } } diff --git a/dev/tests/verification/Resources/PersistedReplacementTest.txt b/dev/tests/verification/Resources/PersistedReplacementTest.txt index 6058e34f5..c7ef3291a 100644 --- a/dev/tests/verification/Resources/PersistedReplacementTest.txt +++ b/dev/tests/verification/Resources/PersistedReplacementTest.txt @@ -63,5 +63,17 @@ class PersistedReplacementTestCest $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 } } diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml index bdeb4e0c6..9c99ffa11 100644 --- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest.xml @@ -50,8 +50,10 @@ <dontSeeElementInDOM selector=".functionalTestSelector" stepKey="dontSeeElementInDOMKey1"/> <dontSeeInCurrentUrl url="/functionalUrl" stepKey="dontSeeInCurrentUrlKey1"/> <dontSeeInField selector=".functionalTestSelector" stepKey="dontSeeInFieldKey1" /> - <dontSeeInPageSource userInput="someInput" stepKey="dontSeeInPageSourceKey1"/> - <dontSeeInSource html=""<myHtmlHere>"" stepKey="dontSeeInSourceKey1"/> + <dontSeeInPageSource html="Cosmo Kramer" stepKey="dontSeeInPageSourceKey1"/> + <dontSeeInPageSource html="<p>Jerry Seinfeld</p>" stepKey="dontSeeInPageSourceKey2"/> + <dontSeeInSource html="Cosmo Kramer" stepKey="dontSeeInSourceKey1"/> + <dontSeeInSource html="<p>Jerry Seinfeld</p>" stepKey="dontSeeInSourceKey2"/> <dontSeeInTitle userInput="someInput" stepKey="dontSeeInTitleKey1"/> <dontSeeLink userInput="someInput" url="/functionalUrl" stepKey="dontSeeLinkKey1" /> <dontSeeOptionIsSelected selector=".functionalTestSelector" userInput="someInput" stepKey="dontSeeOptionIsSelectedKey1" /> @@ -95,9 +97,11 @@ <seeElementInDOM selector=".functionalTestSelector" stepKey="seeElementInDOMKey1"/> <seeInCurrentUrl url="/functionalUrl" stepKey="seeInCurrentUrlKey1"/> <seeInField selector=".functionalTestSelector" userInput="someInput" stepKey="seeInFieldKey1" /> - <seeInPageSource html=""<myHtmlHere>"" stepKey="seeInPageSourceKey1"/> + <seeInPageSource html="Home Page" stepKey="seeInPageSourceKey1"/> + <seeInPageSource html="<h1 class="page-title">" stepKey="seeInPageSourceKey2"/> <seeInPopup userInput="someInput" stepKey="seeInPopupKey1"/> - <seeInSource html=""<myHtmlHere>"" stepKey="seeInSourceKey1"/> + <seeInSource html="Home Page" stepKey="seeInSourceKey1"/> + <seeInSource html="<h1 class="page-title">" stepKey="seeInSourceKey2"/> <seeInTitle userInput="someInput" stepKey="seeInTitleKey1"/> <seeLink userInput="someInput" url="/functionalUrl" stepKey="seeLinkKey1" /> <seeNumberOfElements selector=".functionalTestSelector" stepKey="seeNumberOfElementsKey1"/> diff --git a/dev/tests/verification/TestModule/Test/DataReplacementTest.xml b/dev/tests/verification/TestModule/Test/DataReplacementTest.xml index ca3577373..ae11b6fdc 100644 --- a/dev/tests/verification/TestModule/Test/DataReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/DataReplacementTest.xml @@ -39,5 +39,45 @@ <fillField stepKey="insertZero" selector=".selector" userInput="{{simpleData.favoriteIndex}}"/> <magentoCLI stepKey="insertCommand" command="do something {{uniqueData.lastname}} with uniqueness"/> + + <seeInPageSource html="StringBefore {{simpleData.firstname}} StringAfter" stepKey="htmlReplace1"/> + <seeInPageSource html="#{{simpleData.firstname}}" stepKey="htmlReplace2"/> + <seeInPageSource html="StringBefore {{uniqueData.firstname}} StringAfter" stepKey="htmlReplace3"/> + <seeInPageSource html="#{{uniqueData.firstname}}" stepKey="htmlReplace4"/> + <seeInPageSource html="#{{uniqueData.firstname}}#{{uniqueData.firstname}}" stepKey="htmlReplace5"/> + <seeInPageSource html="StringBefore {{uniqueData.lastname}} StringAfter" stepKey="htmlReplace6"/> + <seeInPageSource html="#{{uniqueData.lastname}}" stepKey="htmlReplace7"/> + <seeInPageSource html="{{SampleSection.simpleElement}}" stepKey="htmlReplace8"/> + <seeInPageSource html="StringBefore {{SampleSection.simpleElement}} StringAfter" stepKey="htmlReplace9"/> + + <dontSeeInPageSource html="StringBefore {{simpleData.firstname}} StringAfter" stepKey="htmlReplace10"/> + <dontSeeInPageSource html="#{{simpleData.firstname}}" stepKey="htmlReplace11"/> + <dontSeeInPageSource html="StringBefore {{uniqueData.firstname}} StringAfter" stepKey="htmlReplace12"/> + <dontSeeInPageSource html="#{{uniqueData.firstname}}" stepKey="htmlReplace13"/> + <dontSeeInPageSource html="#{{uniqueData.firstname}}#{{uniqueData.firstname}}" stepKey="htmlReplace14"/> + <dontSeeInPageSource html="StringBefore {{uniqueData.lastname}} StringAfter" stepKey="htmlReplace15"/> + <dontSeeInPageSource html="#{{uniqueData.lastname}}" stepKey="htmlReplace16"/> + <dontSeeInPageSource html="{{SampleSection.simpleElement}}" stepKey="htmlReplace17"/> + <dontSeeInPageSource html="StringBefore {{SampleSection.simpleElement}} StringAfter" stepKey="htmlReplace18"/> + + <seeInSource html="StringBefore {{simpleData.firstname}} StringAfter" stepKey="htmlReplace19"/> + <seeInSource html="#{{simpleData.firstname}}" stepKey="htmlReplace20"/> + <seeInSource html="StringBefore {{uniqueData.firstname}} StringAfter" stepKey="htmlReplace21"/> + <seeInSource html="#{{uniqueData.firstname}}" stepKey="htmlReplace22"/> + <seeInSource html="#{{uniqueData.firstname}}#{{uniqueData.firstname}}" stepKey="htmlReplace23"/> + <seeInSource html="StringBefore {{uniqueData.lastname}} StringAfter" stepKey="htmlReplace24"/> + <seeInSource html="#{{uniqueData.lastname}}" stepKey="htmlReplace25"/> + <seeInSource html="{{SampleSection.simpleElement}}" stepKey="htmlReplace26"/> + <seeInSource html="StringBefore {{SampleSection.simpleElement}} StringAfter" stepKey="htmlReplace27"/> + + <dontSeeInSource html="StringBefore {{simpleData.firstname}} StringAfter" stepKey="htmlReplace28"/> + <dontSeeInSource html="#{{simpleData.firstname}}" stepKey="htmlReplace29"/> + <dontSeeInSource html="StringBefore {{uniqueData.firstname}} StringAfter" stepKey="htmlReplace30"/> + <dontSeeInSource html="#{{uniqueData.firstname}}" stepKey="htmlReplace31"/> + <dontSeeInSource html="#{{uniqueData.firstname}}#{{uniqueData.firstname}}" stepKey="htmlReplace32"/> + <dontSeeInSource html="StringBefore {{uniqueData.lastname}} StringAfter" stepKey="htmlReplace33"/> + <dontSeeInSource html="#{{uniqueData.lastname}}" stepKey="htmlReplace34"/> + <dontSeeInSource html="{{SampleSection.simpleElement}}" stepKey="htmlReplace35"/> + <dontSeeInSource html="StringBefore {{SampleSection.simpleElement}} StringAfter" stepKey="htmlReplace36"/> </test> </tests> \ No newline at end of file diff --git a/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml b/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml index 8fc8fd19a..4b0f3c902 100644 --- a/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml +++ b/dev/tests/verification/TestModule/Test/PersistedReplacementTest.xml @@ -24,5 +24,21 @@ <searchAndMultiSelectOption stepKey="parameterArrayReplacement" selector="#selector" parameterArray="[$createdData.firstname$, $createdData.lastname$]"/> <fillField stepKey="allTypesMixed" selector="#selector" userInput="{{simpleData.firstname}} $createdData.firstname$ stringLiteral"/> <searchAndMultiSelectOption stepKey="parameterArrayMixed" selector="#selector" parameterArray="[$createdData.firstname$, {{simpleData.firstname}}, stringLiteral]"/> + + <seeInPageSource html="StringBefore $createdData.firstname$ StringAfter" stepKey="htmlReplace1"/> + <seeInPageSource html="StringBefore $$createData1.firstname$$ StringAfter" stepKey="htmlReplace2"/> + <seeInPageSource html="#{{_ENV.MAGENTO_BASE_URL}}#$createdData.firstname$" stepKey="htmlReplace3"/> + + <dontSeeInPageSource html="StringBefore $createdData.firstname$ StringAfter" stepKey="htmlReplace4"/> + <dontSeeInPageSource html="StringBefore $$createData1.firstname$$ StringAfter" stepKey="htmlReplace5"/> + <dontSeeInPageSource html="#{{_ENV.MAGENTO_BASE_URL}}#$createdData.firstname$" stepKey="htmlReplace6"/> + + <seeInSource html="StringBefore $createdData.firstname$ StringAfter" stepKey="htmlReplace7"/> + <seeInSource html="StringBefore $$createData1.firstname$$ StringAfter" stepKey="htmlReplace8"/> + <seeInSource html="#{{_ENV.MAGENTO_BASE_URL}}#$createdData.firstname$" stepKey="htmlReplace9"/> + + <dontSeeInSource html="StringBefore $createdData.firstname$ StringAfter" stepKey="htmlReplace10"/> + <dontSeeInSource html="StringBefore $$createData1.firstname$$ StringAfter" stepKey="htmlReplace11"/> + <dontSeeInSource html="#{{_ENV.MAGENTO_BASE_URL}}#$createdData.firstname$" stepKey="htmlReplace12"/> </test> </tests> diff --git a/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml b/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml index d3e8ee7b1..937c6edba 100644 --- a/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml +++ b/dev/tests/verification/TestModule/Test/XmlDuplicateTest.xml @@ -66,8 +66,8 @@ <dontSeeInField stepKey="dntsinfld2"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld1"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld2"/> - <dontSeeInPageSource stepKey="dntsinpgs1"/> - <dontSeeInPageSource stepKey="dntsinpgs2"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs1"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs2"/> <dontSeeInSource html="1" stepKey="dntsinsource1"/> <dontSeeInSource html="1" stepKey="dntsinsource2"/> <dontSeeInTitle stepKey="dntsintitle1"/> @@ -282,8 +282,8 @@ <dontSeeInField stepKey="dntsinfld2"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld1"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld2"/> - <dontSeeInPageSource stepKey="dntsinpgs1"/> - <dontSeeInPageSource stepKey="dntsinpgs2"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs1"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs2"/> <dontSeeInSource html="1" stepKey="dntsinsource1"/> <dontSeeInSource html="1" stepKey="dntsinsource2"/> <dontSeeInTitle stepKey="dntsintitle1"/> @@ -497,8 +497,8 @@ <dontSeeInField stepKey="dntsinfld2"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld1"/> <dontSeeInFormFields selector="1" stepKey="dntsinffld2"/> - <dontSeeInPageSource stepKey="dntsinpgs1"/> - <dontSeeInPageSource stepKey="dntsinpgs2"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs1"/> + <dontSeeInPageSource html="1" stepKey="dntsinpgs2"/> <dontSeeInSource html="1" stepKey="dntsinsource1"/> <dontSeeInSource html="1" stepKey="dntsinsource2"/> <dontSeeInTitle stepKey="dntsintitle1"/> diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php index dd7c20b18..9b1cdf1af 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php @@ -53,7 +53,8 @@ class ActionObject "function", 'filterSelector', 'optionSelector', - "command" + "command", + "html" ]; const OLD_ASSERTION_ATTRIBUTES = ["expected", "expectedType", "actual", "actualType"]; const ASSERTION_ATTRIBUTES = ["expectedResult" => "expected", "actualResult" => "actual"]; diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/dontSeeActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/dontSeeActions.xsd index 3fda54071..dc7cb8d8a 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/dontSeeActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/dontSeeActions.xsd @@ -172,7 +172,7 @@ </xs:annotation> <xs:simpleContent> <xs:extension base="xs:string"> - <xs:attribute ref="userInput"/> + <xs:attribute ref="html" use="required"/> <xs:attributeGroup ref="commonActionAttributes"/> </xs:extension> </xs:simpleContent> diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index d07c5e1e0..08fc6051c 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -664,7 +664,7 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato } if (isset($customActionAttributes['html'])) { - $html = $customActionAttributes['html']; + $html = $this->addUniquenessFunctionCall($customActionAttributes['html']); } if (isset($customActionAttributes['locale'])) { @@ -1154,7 +1154,6 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato case "dontSeeInField": case "dontSeeInCurrentUrl": case "dontSeeInTitle": - case "dontSeeInPageSource": case "dontSeeOptionIsSelected": case "fillField": case "loadSessionSnapshot": @@ -1172,9 +1171,9 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato ); break; case "seeInPageSource": + case "dontSeeInPageSource": case "seeInSource": case "dontSeeInSource": - // TODO: Need to fix xml parser to allow parsing html. $testSteps .= $this->wrapFunctionCall($actor, $actionObject, $html); break; case "conditionalClick": From ca8a901844afdb80c233a790c8a09b930841aa69 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Fri, 26 Jul 2019 10:29:33 -0500 Subject: [PATCH 56/59] MQE-1672: AllureAdapter does not output BROKEN test steps - Fixed broken steps not showing up at all - Fixed ActionGroup nesting issues when the test abruptly ends --- .../Allure/Adapter/MagentoAllureAdapter.php | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index 68dbe09ae..e266e76c5 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -9,6 +9,7 @@ use Magento\FunctionalTestingFramework\Suite\Handlers\SuiteObjectHandler; use Magento\FunctionalTestingFramework\Test\Objects\ActionGroupObject; use \Magento\FunctionalTestingFramework\Util\TestGenerator; +use Yandex\Allure\Adapter\Model\Status; use Yandex\Allure\Adapter\Model\Step; use Yandex\Allure\Codeception\AllureCodeception; use Yandex\Allure\Adapter\Event\StepStartedEvent; @@ -16,6 +17,7 @@ use Yandex\Allure\Adapter\Event\StepFailedEvent; use Yandex\Allure\Adapter\Event\TestCaseFailedEvent; use Yandex\Allure\Adapter\Event\TestCaseFinishedEvent; +use Yandex\Allure\Adapter\Event\TestCaseBrokenEvent; use Codeception\Event\FailEvent; use Codeception\Event\SuiteEvent; use Codeception\Event\StepEvent; @@ -187,6 +189,32 @@ public function testIncomplete(FailEvent $failEvent) $this->getLifecycle()->fire($event->withException($e)->withMessage($message)); } + /** + * Override of parent method. Adds in steps for hard PHP Errors if they arrise. + * + * @param FailEvent $failEvent + * @return void + */ + public function testError(FailEvent $failEvent) + { + $event = new TestCaseBrokenEvent(); + $e = $failEvent->getFail(); + $message = $e->getMessage(); + + // Create new step with an error for Allure + $failStep = new Step(); + $failStep->setName("ERROR"); + $failStep->setTitle($message); + $failStep->setStatus(Status::BROKEN); + + // Retrieve Allure Steps and add in the new BROKEN step + $rootStep = $this->getLifecycle()->getStepStorage()->pollLast(); + $rootStep->addStep($failStep); + $this->getLifecycle()->getStepStorage()->put($rootStep); + + $this->getLifecycle()->fire($event->withException($e)->withMessage($message)); + } + /** * Override of parent method, polls stepStorage for testcase and formats it according to actionGroup nesting. * @@ -207,6 +235,13 @@ public function testEnd() } // if actionGroup flag, start nesting if (strpos($step->getName(), ActionGroupObject::ACTION_GROUP_CONTEXT_START) !== false) { + if ($actionGroupStepContainer !== null) { + //actionGroup still being nested, need to close out and finish it. + $formattedSteps[] = $actionGroupStepContainer; + $actionGroupStepContainer = null; + $actionGroupStepKey = null; + } + $step->setName(str_replace(ActionGroupObject::ACTION_GROUP_CONTEXT_START, '', $step->getName())); $actionGroupStepContainer = $step; From 95b1eec6d225d9dfef988df6f190237f66cfcfc9 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Fri, 26 Jul 2019 10:30:23 -0500 Subject: [PATCH 57/59] MQE-1669: XML Comments outside of Test and AG - Added check for node parent when converting XML comment to action --- .../Test/Config/Converter/Dom/Flat.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php index 6d08c367c..f888518aa 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php +++ b/src/Magento/FunctionalTestingFramework/Test/Config/Converter/Dom/Flat.php @@ -18,6 +18,7 @@ class Flat implements ConverterInterface const REMOVE_KEY_ATTRIBUTE = 'keyForRemoval'; const EXTENDS_ATTRIBUTE = 'extends'; const TEST_HOOKS = ['before', 'after']; + const VALID_COMMENT_PARENT = ['test', 'before', 'after', 'actionGroup']; /** * Array node configuration. @@ -124,7 +125,8 @@ public function convertXml(\DOMNode $source, $basePath = '') ) { $value = $node->nodeValue; break; - } elseif ($node->nodeType == XML_COMMENT_NODE) { + } elseif ($node->nodeType == XML_COMMENT_NODE && + in_array($node->parentNode->nodeName, self::VALID_COMMENT_PARENT)) { $uniqid = uniqid($node->nodeName); $value[$uniqid] = [ 'value' => trim($node->nodeValue), From 5507c906a66de27e1140e9459479cb119fc4d018 Mon Sep 17 00:00:00 2001 From: Kevin Kozan <kkozan@magento.com> Date: Fri, 26 Jul 2019 10:43:35 -0500 Subject: [PATCH 58/59] MQE-1672: AllureAdapter does not output BROKEN test steps ca8a901 - PHPMD Suppression --- .../Allure/Adapter/MagentoAllureAdapter.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php index e266e76c5..3bcbf0b26 100644 --- a/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php +++ b/src/Magento/FunctionalTestingFramework/Allure/Adapter/MagentoAllureAdapter.php @@ -219,6 +219,7 @@ public function testError(FailEvent $failEvent) * Override of parent method, polls stepStorage for testcase and formats it according to actionGroup nesting. * * @return void + * @SuppressWarnings(PHPMD) */ public function testEnd() { From 62bdb2c867b66a2db56dd20d03ed4119e2ae89ef Mon Sep 17 00:00:00 2001 From: Tom Reece <treece@adobe.com> Date: Mon, 29 Jul 2019 10:55:03 -0500 Subject: [PATCH 59/59] MQE-1675: Remove 'Build selectors with appropriate specificity' from devdocs --- docs/tips-tricks.md | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/docs/tips-tricks.md b/docs/tips-tricks.md index edc1d57bd..4f7539c6d 100644 --- a/docs/tips-tricks.md +++ b/docs/tips-tricks.md @@ -345,33 +345,6 @@ BAD: <element name="productName" type="input" selector=".admin__field[data-index=name] input"/> ``` -### Build selectors with appropriate specificity - -Selectors that are too general might sweep up unexpected elements. -When possible, select the first parent tag and then specify the desired element within that selection. - -**Why?** Elements that are overly specific are less flexible and may fail if unexpected DOM changes occur. It also reduces the amount of the DOM it needs to parse. - - <span style="color:green"> -GOOD: -</span> - -```html - form[name='myform'] > input[name='firstname'] - - //*[@id='container'][@class='dashboard-title'] - ``` - - <span style="color:red"> -BAD: -</span> - -```html - input[name='firstname'] - - //*[@id='container']/*[@class='dashboard-advanced-reports']/*[@class='dashboard-advanced- reports-description']/*[@class='dashboard-title'] - ``` - ## General tips ### Use data references to avoid hardcoded values