diff --git a/.gitignore b/.gitignore index d39929c6f..63ea3d26e 100755 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ codeception.yml dev/tests/functional/MFTF.suite.yml dev/tests/functional/_output dev/mftf.log -dev/tests/mftf.log \ No newline at end of file +dev/tests/mftf.log +dev/tests/docs/* \ No newline at end of file diff --git a/dev/tests/_bootstrap.php b/dev/tests/_bootstrap.php index 4b9d04442..31b4462f6 100644 --- a/dev/tests/_bootstrap.php +++ b/dev/tests/_bootstrap.php @@ -60,6 +60,28 @@ defined('TESTS_BP') || define('TESTS_BP', __DIR__); defined('TESTS_MODULE_PATH') || define('TESTS_MODULE_PATH', TESTS_BP . $RELATIVE_TESTS_MODULE_PATH); defined('MAGENTO_BP') || define('MAGENTO_BP', __DIR__); +define('DOCS_OUTPUT_DIR', + FW_BP . + DIRECTORY_SEPARATOR . + "dev" . + DIRECTORY_SEPARATOR . + "tests" . + DIRECTORY_SEPARATOR . + "unit" . + DIRECTORY_SEPARATOR . + "_output" +); +define('RESOURCE_DIR', + FW_BP . + DIRECTORY_SEPARATOR . + "dev" . + DIRECTORY_SEPARATOR . + "tests" . + DIRECTORY_SEPARATOR . + "unit" . + DIRECTORY_SEPARATOR . + "Resources" +); $utilDir = DIRECTORY_SEPARATOR . 'Util'. DIRECTORY_SEPARATOR . '*.php'; diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php new file mode 100644 index 000000000..d56608894 --- /dev/null +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Test/Util/ActionGroupAnnotationExtractorTest.php @@ -0,0 +1,104 @@ +setMockLoggingUtil(); + } + + /** + * Annotation extractor takes in raw array and condenses it to expected format + * + * @throws \Exception + */ + public function testActionGroupExtractAnnotations() + { + // Test Data + $actionGroupAnnotations = [ + "nodeName" => "annotations", + "description" => [ + "nodeName" => "description", + "value" => "someDescription" + ], + "page" => [ + "nodeName" => "page", + "value" => "somePage" + ] + ]; + // Perform Test + $extractor = new ActionGroupAnnotationExtractor(); + $returnedAnnotations = $extractor->extractAnnotations($actionGroupAnnotations, "fileName"); + + // Asserts + + $this->assertEquals("somePage", $returnedAnnotations['page']); + $this->assertEquals("someDescription", $returnedAnnotations['description']); + } + + /** + * Annotation extractor should throw warning when required annotations are missing + * + * @throws \Exception + */ + public function testActionGroupMissingAnnotations() + { + // Action Group Data, missing page and description + $testAnnotations = []; + // Perform Test + $extractor = new ActionGroupAnnotationExtractor(); + AspectMock::double($extractor, ['isCommandDefined' => true]); + $extractor->extractAnnotations($testAnnotations, "fileName"); + + // Asserts + TestLoggingUtil::getInstance()->validateMockLogStatement( + 'warning', + 'DEPRECATION: Action Group File fileName is missing required annotations.', + [ + 'actionGroup' => 'fileName', + 'missingAnnotations' => "description, page" + ] + ); + } + + /** + * Annotation extractor should not throw warning when required + * annotations are missing if command is not generate:docs + * + * @throws \Exception + */ + public function testActionGroupMissingAnnotationsNoWarning() + { + // Action Group Data, missing page and description + $testAnnotations = []; + // Perform Test + $extractor = new ActionGroupAnnotationExtractor(); + $extractor->extractAnnotations($testAnnotations, "fileName"); + + // Asserts + TestLoggingUtil::getInstance()->validateMockLogEmpty(); + } + + /** + * After class functionality + * @return void + */ + public static function tearDownAfterClass() + { + TestLoggingUtil::getInstance()->clearMockLoggingUtil(); + } +} diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php new file mode 100644 index 000000000..ae61f37af --- /dev/null +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Util/DocGeneratorTest.php @@ -0,0 +1,131 @@ + "somePage", + "description" => "someDescription" + ]; + $actionGroupUnderTest = (new ActionGroupObjectBuilder()) + ->withAnnotations($annotations) + ->withFilename("filename") + ->build(); + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation( + [$actionGroupUnderTest->getName() => $actionGroupUnderTest], + DOCS_OUTPUT_DIR, + true + ); + + $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; + + $this->assertTrue(file_exists($docFile)); + + $this->assertFileEquals( + RESOURCE_DIR . DIRECTORY_SEPARATOR . "basicDocumentation.txt", + $docFile + ); + } + + /** + * Test to check creation of documentation when overwriting previous + * + * @throws \Exception + */ + public function testCreateDocumentationWithOverwrite() + { + $annotations = [ + "page" => "somePage", + "description" => "someDescription" + ]; + $actionGroupUnderTest = (new ActionGroupObjectBuilder()) + ->withAnnotations($annotations) + ->withFilename("filename") + ->build(); + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation( + [$actionGroupUnderTest->getName() => $actionGroupUnderTest], + DOCS_OUTPUT_DIR, + true + ); + + $annotations = [ + "page" => "alteredPage", + "description" => "alteredDescription" + ]; + $actionGroupUnderTest = (new ActionGroupObjectBuilder()) + ->withAnnotations($annotations) + ->withFilename("filename") + ->build(); + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation( + [$actionGroupUnderTest->getName() => $actionGroupUnderTest], + DOCS_OUTPUT_DIR, + true + ); + + $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; + + $this->assertTrue(file_exists($docFile)); + + $this->assertFileEquals( + RESOURCE_DIR . DIRECTORY_SEPARATOR . "alteredDocumentation.txt", + $docFile + ); + } + + /** + * Test for existing documentation without clean + * + * @throws \Exception + */ + public function testCreateDocumentationNotCleanException() + { + $annotations = [ + "page" => "somePage", + "description" => "someDescription" + ]; + $actionGroupUnderTest = (new ActionGroupObjectBuilder()) + ->withAnnotations($annotations) + ->withFilename("filename") + ->build(); + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation( + [$actionGroupUnderTest->getName() => $actionGroupUnderTest], + DOCS_OUTPUT_DIR, + true + ); + + $docFile = DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . self::DOC_FILENAME . ".md"; + + $this->expectException(TestFrameworkException::class); + $this->expectExceptionMessage("$docFile already exists, please add --clean if you want to overwrite it."); + + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation( + [$actionGroupUnderTest->getName() => $actionGroupUnderTest], + DOCS_OUTPUT_DIR, + false + ); + } +} diff --git a/dev/tests/unit/Resources/alteredDocumentation.txt b/dev/tests/unit/Resources/alteredDocumentation.txt new file mode 100644 index 000000000..b55c30d6b --- /dev/null +++ b/dev/tests/unit/Resources/alteredDocumentation.txt @@ -0,0 +1,16 @@ +#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 + +###testActionGroupObject +alteredDescription + +Located in: + +- filename +*** diff --git a/dev/tests/unit/Resources/basicDocumentation.txt b/dev/tests/unit/Resources/basicDocumentation.txt new file mode 100644 index 000000000..26a7fe719 --- /dev/null +++ b/dev/tests/unit/Resources/basicDocumentation.txt @@ -0,0 +1,16 @@ +#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 + +###testActionGroupObject +someDescription + +Located in: + +- filename +*** diff --git a/dev/tests/unit/Util/ActionGroupObjectBuilder.php b/dev/tests/unit/Util/ActionGroupObjectBuilder.php index f97d0465d..83537ab78 100644 --- a/dev/tests/unit/Util/ActionGroupObjectBuilder.php +++ b/dev/tests/unit/Util/ActionGroupObjectBuilder.php @@ -27,6 +27,13 @@ class ActionGroupObjectBuilder */ private $actionObjects = []; + /** + * Action Group Object Builder default entity annotations. + * + * @var array + */ + private $annotations = []; + /** * Action Group Object Builder default entity arguments. * @@ -41,6 +48,13 @@ class ActionGroupObjectBuilder */ private $extends = null; + /** + * Action Group Object Builder default filenames + * + * @var string + */ + private $filename = []; + /** * Setter for the Action Group Object name * @@ -53,6 +67,18 @@ public function withName($name) return $this; } + /** + * Setter for the Action Group Object annotations + * + * @param array $annotations + * @return ActionGroupObjectBuilder + */ + public function withAnnotations($annotations) + { + $this->annotations = $annotations; + return $this; + } + /** * Setter for the Action Group Object arguments * @@ -89,6 +115,18 @@ public function withExtendedAction($extendedActionGroup) return $this; } + /** + * Setter for the Action Group Object filename + * + * @param string $filename + * @return ActionGroupObjectBuilder + */ + public function withFilename($filename) + { + $this->filename = $filename; + return $this; + } + /** * ActionGroupObjectBuilder constructor. */ @@ -108,9 +146,11 @@ public function build() { return new ActionGroupObject( $this->name, + $this->annotations, $this->arguments, $this->actionObjects, - $this->extends + $this->extends, + $this->filename ); } } diff --git a/dev/tests/unit/Util/MagentoTestCase.php b/dev/tests/unit/Util/MagentoTestCase.php index 0aa153106..6a4e5d35b 100644 --- a/dev/tests/unit/Util/MagentoTestCase.php +++ b/dev/tests/unit/Util/MagentoTestCase.php @@ -14,6 +14,14 @@ */ class MagentoTestCase extends TestCase { + public static function setUpBeforeClass() + { + if (!self::fileExists(DOCS_OUTPUT_DIR)) { + mkdir(DOCS_OUTPUT_DIR, 0755, true); + } + parent::setUpBeforeClass(); + } + /** * Teardown for removing AspectMock Double References * @return void @@ -21,5 +29,9 @@ class MagentoTestCase extends TestCase public static function tearDownAfterClass() { AspectMock::clean(); + array_map('unlink', glob(DOCS_OUTPUT_DIR . DIRECTORY_SEPARATOR . "*")); + if (file_exists(DOCS_OUTPUT_DIR)) { + rmdir(DOCS_OUTPUT_DIR); + } } } diff --git a/dev/tests/unit/Util/TestLoggingUtil.php b/dev/tests/unit/Util/TestLoggingUtil.php index 6d2e4b964..7becc609a 100644 --- a/dev/tests/unit/Util/TestLoggingUtil.php +++ b/dev/tests/unit/Util/TestLoggingUtil.php @@ -10,7 +10,6 @@ use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil; use Magento\FunctionalTestingFramework\Util\Logger\MftfLogger; use Monolog\Handler\TestHandler; -use Monolog\Logger; use PHPUnit\Framework\Assert; class TestLoggingUtil extends Assert @@ -66,6 +65,12 @@ public function setMockLoggingUtil() $property->setValue($mockLoggingUtil); } + public function validateMockLogEmpty() + { + $records = $this->testLogHandler->getRecords(); + $this->assertTrue(empty($records)); + } + /** * Function which validates messages have been logged as intended during test execution. * diff --git a/docs/commands/mftf.md b/docs/commands/mftf.md index e418f7970..998426564 100644 --- a/docs/commands/mftf.md +++ b/docs/commands/mftf.md @@ -67,6 +67,13 @@ vendor/bin/mftf run:failed This command cleans up the previously generated tests; generates and runs the tests listed in `dev/tests/acceptance/tests/_output/failed`. For more details about `failed`, refer to [Reporting][]. +### Generate documentation for action groups +```bash +vendor/bin/mftf generate:docs +``` + +This command generates documentation for action groups. + ## Reference ### `build:project` @@ -220,6 +227,33 @@ vendor/bin/mftf generate:urn-catalog [--force] [/dev/tests/docs/documentation.md`. + +#### Usage + +```bash +vendor/bin/mftf generate:docs [--clean] [--output=/path/to/alternate/dir] +``` + +#### Options + +| Option | Description | +| ------------- | --------------------------------------------------------------------- | +| `-c, --clean` | Overwrites previously existing documentation | +| `-o, --output` | Changes the default output directory to a user specified directory | + +#### Example + +```bash +vendor/bin/mftf generate:docs --clean +``` + + ### `reset` #### Description diff --git a/src/Magento/FunctionalTestingFramework/Console/CommandList.php b/src/Magento/FunctionalTestingFramework/Console/CommandList.php index 7623bea66..5bcf1ed31 100644 --- a/src/Magento/FunctionalTestingFramework/Console/CommandList.php +++ b/src/Magento/FunctionalTestingFramework/Console/CommandList.php @@ -11,6 +11,7 @@ /** * Class CommandList has a list of commands. * @codingStandardsIgnoreFile + * @SuppressWarnings(PHPMD) */ class CommandList implements CommandListInterface { @@ -38,7 +39,8 @@ public function __construct(array $commands = []) 'run:failed' => new RunTestFailedCommand(), 'setup:env' => new SetupEnvCommand(), 'upgrade:tests' => new UpgradeTestsCommand(), - 'static-checks' => new StaticChecksCommand(), + 'generate:docs' => new GenerateDocsCommand(), + 'static-checks' => new StaticChecksCommand() ] + $commands; } diff --git a/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php b/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php new file mode 100644 index 000000000..db77bc74f --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Console/GenerateDocsCommand.php @@ -0,0 +1,85 @@ +setName('generate:docs') + ->setDescription('This command generates documentation for created MFTF files.') + ->addOption( + "output", + 'o', + InputOption::VALUE_REQUIRED, + 'Output Directory' + )->addOption( + "clean", + 'c', + InputOption::VALUE_NONE, + 'Clean Output Directory' + )->addOption( + "force", + 'f', + InputOption::VALUE_NONE, + 'Force Document Generation For All Action Groups' + ); + } + + /** + * Executes the current command. + * + * @param InputInterface $input + * @param OutputInterface $output + * @return void + * @throws TestFrameworkException + * @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException + * @throws \Magento\FunctionalTestingFramework\Exceptions\XmlException + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + defined('COMMAND') || define('COMMAND', 'generate:docs'); + $config = $input->getOption('output'); + $clean = $input->getOption('clean'); + $force = $input->getOption('force'); + + MftfApplicationConfig::create( + $force, + MftfApplicationConfig::GENERATION_PHASE, + false, + false + ); + + $allActionGroups = ActionGroupObjectHandler::getInstance()->getAllObjects(); + $docGenerator = new DocGenerator(); + $docGenerator->createDocumentation($allActionGroups, $config, $clean); + + $output->writeln("Generate Docs Command Run"); + + if (empty($config)) { + $output->writeln("Output to ". DocGenerator::DEFAULT_OUTPUT_DIR); + } else { + $output->writeln("Output to ". $config); + } + } +} diff --git a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php index eec6d74b7..ef2e11c03 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php +++ b/src/Magento/FunctionalTestingFramework/Test/Objects/ActionGroupObject.php @@ -7,8 +7,6 @@ namespace Magento\FunctionalTestingFramework\Test\Objects; use Magento\FunctionalTestingFramework\Exceptions\TestReferenceException; -use Magento\FunctionalTestingFramework\Test\Handlers\ActionGroupObjectHandler; -use Magento\FunctionalTestingFramework\Test\Util\ActionGroupObjectExtractor; use Magento\FunctionalTestingFramework\Test\Util\ActionMergeUtil; use Magento\FunctionalTestingFramework\Test\Util\ObjectExtension; @@ -19,6 +17,8 @@ class ActionGroupObject { const ACTION_GROUP_ORIGIN_NAME = "actionGroupName"; const ACTION_GROUP_ORIGIN_TEST_REF = "testInvocationRef"; + const ACTION_GROUP_DESCRIPTION = "description"; + const ACTION_GROUP_PAGE = "page"; const ACTION_GROUP_CONTEXT_START = "Entering Action Group "; const ACTION_GROUP_CONTEXT_END = "Exiting Action Group "; const STEPKEY_REPLACEMENT_ENABLED_TYPES = [ @@ -66,6 +66,13 @@ class ActionGroupObject */ private $arguments; + /** + * An array used to store annotation information to values + * + * @var array + */ + private $annotations; + /** * String of parent Action Group * @@ -84,12 +91,13 @@ class ActionGroupObject * ActionGroupObject constructor. * * @param string $name + * @param array $annotations * @param ArgumentObject[] $arguments * @param array $actions * @param string $parentActionGroup * @param string $filename */ - public function __construct($name, $arguments, $actions, $parentActionGroup, $filename = null) + public function __construct($name, $annotations, $arguments, $actions, $parentActionGroup, $filename = null) { $this->varAttributes = array_merge( ActionObject::SELECTOR_ENABLED_ATTRIBUTES, @@ -97,6 +105,7 @@ public function __construct($name, $arguments, $actions, $parentActionGroup, $fi ); $this->varAttributes[] = ActionObject::ACTION_ATTRIBUTE_URL; $this->name = $name; + $this->annotations = $annotations; $this->arguments = $arguments; $this->parsedActions = $actions; $this->parentActionGroup = $parentActionGroup; @@ -462,6 +471,16 @@ public function getArguments() return $this->arguments; } + /** + * Getter for the Action Group Annotations + * + * @return array + */ + public function getAnnotations() + { + return $this->annotations; + } + /** * Searches through ActionGroupObject's arguments and returns first argument wi * @param string $name diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php new file mode 100644 index 000000000..b6e89fd44 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupAnnotationExtractor.php @@ -0,0 +1,86 @@ +stripDescriptorTags($testAnnotations, parent::NODE_NAME); + + foreach ($annotations as $annotationKey => $annotationData) { + $annotationObjects[$annotationKey] = $annotationData[parent::ANNOTATION_VALUE]; + } + // TODO: Remove this when all action groups have annotations + if ($this->isCommandDefined()) { + $this->validateMissingAnnotations($annotationObjects, $filename); + } + + return $annotationObjects; + } + + /** + * Validates given annotations against list of required annotations. + * + * @param array $annotationObjects + * @return void + * @throws \Exception + */ + private function validateMissingAnnotations($annotationObjects, $filename) + { + $missingAnnotations = []; + + foreach (self::ACTION_GROUP_REQUIRED_ANNOTATIONS as $REQUIRED_ANNOTATION) { + if (!array_key_exists($REQUIRED_ANNOTATION, $annotationObjects)) { + $missingAnnotations[] = $REQUIRED_ANNOTATION; + } + } + + if (!empty($missingAnnotations)) { + $message = "Action Group File {$filename} is missing required annotations."; + LoggingUtil::getInstance()->getLogger(ActionObject::class)->deprecation( + $message, + ["actionGroup" => $filename, "missingAnnotations" => implode(", ", $missingAnnotations)] + ); + } + } + + /** + * Checks if command is defined as generate:docs + * + * @return boolean + */ + private function isCommandDefined() + { + if (defined('COMMAND') and COMMAND == self::GENERATE_DOCS_COMMAND) { + return true; + } else { + return false; + } + } +} diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php index 6d7e67b38..74665cf75 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ActionGroupObjectExtractor.php @@ -18,6 +18,7 @@ class ActionGroupObjectExtractor extends BaseObjectExtractor { const DEFAULT_VALUE = 'defaultValue'; const ACTION_GROUP_ARGUMENTS = 'arguments'; + const ACTION_GROUP_ANNOTATIONS = 'annotations'; const FILENAME = 'filename'; const ACTION_GROUP_INSERT_BEFORE = "insertBefore"; const ACTION_GROUP_INSERT_AFTER = "insertAfter"; @@ -30,12 +31,20 @@ class ActionGroupObjectExtractor extends BaseObjectExtractor */ private $actionObjectExtractor; + /** + * Annotation Extractor object + * + * @var AnnotationExtractor + */ + private $annotationExtractor; + /** * ActionGroupObjectExtractor constructor. */ public function __construct() { $this->actionObjectExtractor = new ActionObjectExtractor(); + $this->annotationExtractor = new ActionGroupAnnotationExtractor(); } /** @@ -55,6 +64,7 @@ public function extractActionGroup($actionGroupData) self::NODE_NAME, self::ACTION_GROUP_ARGUMENTS, self::NAME, + self::ACTION_GROUP_ANNOTATIONS, self::FILENAME, self::ACTION_GROUP_INSERT_BEFORE, self::ACTION_GROUP_INSERT_AFTER, @@ -62,6 +72,16 @@ public function extractActionGroup($actionGroupData) ); // TODO filename is now available to the ActionGroupObject, integrate this into debug and error statements + + try { + $annotations = $this->annotationExtractor->extractAnnotations( + $actionGroupData[self::ACTION_GROUP_ANNOTATIONS] ?? [], + $actionGroupData[self::FILENAME] + ); + } catch (\Exception $error) { + throw new XmlException($error->getMessage() . " in Action Group " . $actionGroupData[self::FILENAME]); + } + try { $actions = $this->actionObjectExtractor->extractActions($actionData); } catch (\Exception $error) { @@ -74,6 +94,7 @@ public function extractActionGroup($actionGroupData) return new ActionGroupObject( $actionGroupData[self::NAME], + $annotations, $arguments, $actions, $actionGroupReference, diff --git a/src/Magento/FunctionalTestingFramework/Test/Util/ObjectExtensionUtil.php b/src/Magento/FunctionalTestingFramework/Test/Util/ObjectExtensionUtil.php index 4c3949ef3..91617b1e2 100644 --- a/src/Magento/FunctionalTestingFramework/Test/Util/ObjectExtensionUtil.php +++ b/src/Magento/FunctionalTestingFramework/Test/Util/ObjectExtensionUtil.php @@ -129,6 +129,7 @@ public function extendActionGroup($actionGroupObject) // Create new Action Group object to return $extendedActionGroup = new ActionGroupObject( $actionGroupObject->getName(), + $actionGroupObject->getAnnotations(), $extendedArguments, $newActions, $actionGroupObject->getParentName(), diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd index 619d21e9f..616995531 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/actionGroupSchema.xsd @@ -30,6 +30,14 @@ + + + + + + + + diff --git a/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php new file mode 100644 index 000000000..9846cded5 --- /dev/null +++ b/src/Magento/FunctionalTestingFramework/Util/DocGenerator.php @@ -0,0 +1,143 @@ + $object) { + $annotations = $object->getAnnotations(); + $filenames = explode(',', $object->getFilename()); + $arguments = $object->getArguments(); + + $info = [ + actionGroupObject::ACTION_GROUP_DESCRIPTION => $annotations[actionGroupObject::ACTION_GROUP_DESCRIPTION] + ?? 'NO_DESCRIPTION_SPECIFIED', + self::FILENAMES => $filenames, + ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS => $arguments + ]; + $pageGroups = array_merge_recursive( + $pageGroups, + [$annotations[ActionGroupObject::ACTION_GROUP_PAGE] ?? 'NO_PAGE_SPECIFIED' => [$name => $info]] + ); + } + + ksort($pageGroups); + foreach ($pageGroups as $page => $groups) { + ksort($groups); + $pageGroups[$page] = $groups; + } + + $markdown = $this->transformToMarkdown($pageGroups); + + file_put_contents($filePath, $markdown); + } + + /** + * This creates html documentation for objects passed in + * + * @param array $annotationList + * @return string + */ + private function transformToMarkdown($annotationList) + { + $markdown = "#Action Group Information" . PHP_EOL; + $markdown .= "This documentation contains a list of all" . + " action groups on the pages on which they start" . + 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; + if (!empty($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS])) { + $markdown .= "Action Group Arguments:" . PHP_EOL . PHP_EOL; + $markdown .= "| Name | Type |" . PHP_EOL; + $markdown .= "| --- | --- |" . PHP_EOL; + foreach ($annotations[ActionGroupObjectExtractor::ACTION_GROUP_ARGUMENTS] as $argument) { + $argumentName = $argument->getName(); + $argumentType = $argument->getDataType(); + $markdown .= "| $argumentName | $argumentType |" . PHP_EOL; + } + $markdown .= PHP_EOL; + } + $markdown .= "Located in:" . PHP_EOL; + foreach ($annotations[self::FILENAMES] as $filename) { + $relativeFilename = str_replace(MAGENTO_BP . DIRECTORY_SEPARATOR, "", $filename); + $markdown .= PHP_EOL . "- $relativeFilename"; + } + $markdown .= PHP_EOL . "***" . PHP_EOL; + } + } + return $markdown; + } +}