diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php index 9e425e020..fb6dcd865 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/DataGenerator/Persist/OperationDataArrayResolverTest.php @@ -9,6 +9,7 @@ use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Persist\OperationDataArrayResolver; +use Magento\FunctionalTestingFramework\Util\Iterator\AbstractIterator; use Magento\FunctionalTestingFramework\Util\MagentoTestCase; use tests\unit\Util\EntityDataObjectBuilder; use tests\unit\Util\OperationDefinitionBuilder; @@ -355,6 +356,127 @@ public function testNestedMetadataArrayOfValue() $this->assertEquals(self::NESTED_METADATA_ARRAY_RESULT, $result); } + public function testNestedMetadataArrayOfDiverseObjects() + { + + $entityDataObjBuilder = new EntityDataObjectBuilder(); + $parentDataObject = $entityDataObjBuilder + ->withName("parentObject") + ->withType("parentType") + ->withLinkedEntities(['child1Object' => 'childType1','child2Object' => 'childType2']) + ->build(); + + $child1DataObject = $entityDataObjBuilder + ->withName('child1Object') + ->withType('childType1') + ->withDataFields(['city' => 'Testcity','zip' => 12345]) + ->build(); + + $child2DataObject = $entityDataObjBuilder + ->withName('child2Object') + ->withType('childType2') + ->withDataFields(['city' => 'Testcity 2','zip' => 54321,'state' => 'Teststate']) + ->build(); + + $mockDOHInstance = AspectMock::double( + DataObjectHandler::class, + [ + 'getObject' => function ($name) use ($child1DataObject, $child2DataObject) { + switch ($name) { + case 'child1Object': + return $child1DataObject; + case 'child2Object': + return $child2DataObject; + } + } + ] + )->make(); + AspectMock::double(DataObjectHandler::class, [ + 'getInstance' => $mockDOHInstance + ]); + + $operationDefinitionBuilder = new OperationDefinitionBuilder(); + $child1OperationDefinition = $operationDefinitionBuilder + ->withName('createchildType1') + ->withOperation('create') + ->withType('childType1') + ->withMetadata([ + 'city' => 'string', + 'zip' => 'integer' + ])->build(); + + $child2OperationDefinition = $operationDefinitionBuilder + ->withName('createchildType2') + ->withOperation('create') + ->withType('childType2') + ->withMetadata([ + 'city' => 'string', + 'zip' => 'integer', + 'state' => 'string' + ])->build(); + + $mockODOHInstance = AspectMock::double( + OperationDefinitionObjectHandler::class, + [ + 'getObject' => function ($name) use ($child1OperationDefinition, $child2OperationDefinition) { + switch ($name) { + case 'createchildType1': + return $child1OperationDefinition; + case 'createchildType2': + return $child2OperationDefinition; + } + } + ] + )->make(); + AspectMock::double( + OperationDefinitionObjectHandler::class, + [ + 'getInstance' => $mockODOHInstance + ] + ); + + $arrayObElementBuilder = new OperationElementBuilder(); + $arrayElement = $arrayObElementBuilder + ->withKey('address') + ->withType(['childType1','childType2']) + ->withFields([]) + ->withElementType(OperationDefinitionObjectHandler::ENTITY_OPERATION_ARRAY) + //->withNestedElements(['childType1' => $child1Element, 'childType2' => $child2Element]) + ->build(); + + $parentOpElementBuilder = new OperationElementBuilder(); + $parentElement = $parentOpElementBuilder + ->withKey('parentType') + ->withType('parentType') + ->addElements(['address' => $arrayElement]) + ->build(); + + $operationResolver = new OperationDataArrayResolver(); + $result = $operationResolver->resolveOperationDataArray($parentDataObject, [$parentElement], 'create', false); + + $expectedResult = [ + 'parentType' => [ + 'address' => [ + [ + 'city' => 'Testcity', + 'zip' => '12345' + ], + [ + 'city' => 'Testcity 2', + 'zip' => '54321', + 'state' => 'Teststate' + ] + ], + 'name' => 'Hopper', + 'gpa' => '3.5678', + 'phone' => '5555555', + 'isPrimary' => '1' + ] + ]; + + $this->assertEquals($expectedResult, $result); + } + /** * After class functionality * @return void diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/OperationDataArrayResolver.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/OperationDataArrayResolver.php index b2b4fb0e4..60b6e73c2 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/OperationDataArrayResolver.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Persist/OperationDataArrayResolver.php @@ -67,6 +67,10 @@ public function __construct($dependentEntities = null) * @param boolean $fromArray * @return array * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * I suppressed this warning because I was in a hurry to deliver a community PR. That PR modified this function and + * introduced a new conditional, bumping the complexity to 11. */ public function resolveOperationDataArray($entityObject, $operationMetadata, $operation, $fromArray = false) { @@ -109,6 +113,26 @@ public function resolveOperationDataArray($entityObject, $operationMetadata, $op $operationElementType, $operationDataArray ); + } elseif (is_array($operationElementType)) { + foreach ($operationElementType as $currentElementType) { + if (in_array($currentElementType, self::PRIMITIVE_TYPES)) { + $this->resolvePrimitiveReferenceElement( + $entityObject, + $operationElement, + $currentElementType, + $operationDataArray + ); + } else { + $this->resolveNonPrimitiveReferenceElement( + $entityObject, + $operation, + $fromArray, + $currentElementType, + $operationElement, + $operationDataArray + ); + } + } } else { $this->resolveNonPrimitiveReferenceElement( $entityObject, @@ -248,7 +272,8 @@ private function resolveNonPrimitiveElement($entityName, $operationElement, $ope $linkedEntityObj = $this->resolveLinkedEntityObject($entityName); // in array case - if (!empty($operationElement->getNestedOperationElement($operationElement->getValue())) + if (!is_array($operationElement->getValue()) + && !empty($operationElement->getNestedOperationElement($operationElement->getValue())) && $operationElement->getType() == OperationDefinitionObjectHandler::ENTITY_OPERATION_ARRAY ) { $operationSubArray = $this->resolveOperationDataArray( diff --git a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/OperationElementExtractor.php b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/OperationElementExtractor.php index 35d188f5b..c86e27972 100644 --- a/src/Magento/FunctionalTestingFramework/DataGenerator/Util/OperationElementExtractor.php +++ b/src/Magento/FunctionalTestingFramework/DataGenerator/Util/OperationElementExtractor.php @@ -112,9 +112,18 @@ private function extractOperationField(&$operationElements, $operationFieldArray private function extractOperationArray(&$operationArrayData, $operationArrayArray) { foreach ($operationArrayArray as $operationFieldType) { - $operationElementValue = - $operationFieldType[OperationDefinitionObjectHandler::ENTITY_OPERATION_ARRAY_VALUE][0] - [OperationElementExtractor::OPERATION_OBJECT_ARRAY_VALUE] ?? null; + $operationElementValue = []; + if (isset($operationFieldType[OperationDefinitionObjectHandler::ENTITY_OPERATION_ARRAY_VALUE])) { + foreach ($operationFieldType[OperationDefinitionObjectHandler::ENTITY_OPERATION_ARRAY_VALUE] as + $operationFieldValue) { + $operationElementValue[] = + $operationFieldValue[OperationElementExtractor::OPERATION_OBJECT_ARRAY_VALUE] ?? null; + } + } + + if (count($operationElementValue) === 1) { + $operationElementValue = array_pop($operationElementValue); + } $nestedOperationElements = []; if (array_key_exists(OperationElementExtractor::OPERATION_OBJECT_OBJ_NAME, $operationFieldType)) {