Skip to content

Commit bca1b3a

Browse files
authored
Merge branch 'develop' into MQE-1021
2 parents 3525758 + c66df37 commit bca1b3a

File tree

17 files changed

+253
-41
lines changed

17 files changed

+253
-41
lines changed

dev/tests/unit/Magento/FunctionalTestFramework/Util/ModuleResolverTest.php

Lines changed: 100 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use AspectMock\Proxy\Verifier;
1010
use AspectMock\Test as AspectMock;
1111

12+
use Magento\FunctionalTestingFramework\Config\MftfApplicationConfig;
13+
use Magento\FunctionalTestingFramework\Exceptions\TestFrameworkException;
1214
use Magento\FunctionalTestingFramework\ObjectManager;
1315
use Magento\FunctionalTestingFramework\ObjectManagerFactory;
1416
use Magento\FunctionalTestingFramework\Util\Logger\LoggingUtil;
@@ -54,9 +56,10 @@ public function testGetModulePathsAlreadySet()
5456
*/
5557
public function testGetModulePathsAggregate()
5658
{
57-
$this->setMockResolverClass(false, null, null, null, ["example" . DIRECTORY_SEPARATOR . "paths"]);
59+
$this->mockForceGenerate(false);
60+
$this->setMockResolverClass(false, null, null, null, ["example" => "example" . DIRECTORY_SEPARATOR . "paths"]);
5861
$resolver = ModuleResolver::getInstance();
59-
$this->setMockResolverProperties($resolver, null, null);
62+
$this->setMockResolverProperties($resolver, null, [0 => "Magento_example"]);
6063
$this->assertEquals(
6164
[
6265
"example" . DIRECTORY_SEPARATOR . "paths",
@@ -73,12 +76,13 @@ public function testGetModulePathsAggregate()
7376
*/
7477
public function testGetModulePathsLocations()
7578
{
79+
$this->mockForceGenerate(false);
7680
$mockResolver = $this->setMockResolverClass(
77-
false,
78-
null,
81+
true,
82+
[0 => "magento_example"],
7983
null,
8084
null,
81-
["example" . DIRECTORY_SEPARATOR . "paths"]
85+
["example" => "example" . DIRECTORY_SEPARATOR . "paths"]
8286
);
8387
$resolver = ModuleResolver::getInstance();
8488
$this->setMockResolverProperties($resolver, null, null);
@@ -166,15 +170,78 @@ function ($arg1, $arg2) {
166170
}
167171

168172
/**
169-
* Validate that getEnabledModules returns correctly with no admin token
173+
* Validate that getEnabledModules errors out when no Admin Token is returned and --force is false
170174
* @throws \Exception
171175
*/
172176
public function testGetModulePathsNoAdminToken()
173177
{
178+
// Set --force to false
179+
$this->mockForceGenerate(false);
180+
181+
// Mock ModuleResolver and $enabledModulesPath
174182
$this->setMockResolverClass(false, null, ["example" . DIRECTORY_SEPARATOR . "paths"], []);
175183
$resolver = ModuleResolver::getInstance();
176184
$this->setMockResolverProperties($resolver, null, null);
177-
$this->assertEquals(["example" . DIRECTORY_SEPARATOR . "paths"], $resolver->getModulesPath());
185+
186+
// Cannot Generate if no --force was passed in and no Admin Token is returned succesfully
187+
$this->expectException(TestFrameworkException::class);
188+
$resolver->getModulesPath();
189+
}
190+
191+
/**
192+
* Validates that getAdminToken is not called when --force is enabled
193+
*/
194+
public function testGetAdminTokenNotCalledWhenForce()
195+
{
196+
// Set --force to true
197+
$this->mockForceGenerate(true);
198+
199+
// Mock ModuleResolver and applyCustomModuleMethods()
200+
$mockResolver = $this->setMockResolverClass();
201+
$resolver = ModuleResolver::getInstance();
202+
$this->setMockResolverProperties($resolver, null, null);
203+
$resolver->getModulesPath();
204+
$mockResolver->verifyNeverInvoked("getAdminToken");
205+
206+
// verifyNeverInvoked does not add to assertion count
207+
$this->addToAssertionCount(1);
208+
}
209+
210+
/**
211+
* Verify the getAdminToken method returns throws an exception if ENV is not fully loaded.
212+
*/
213+
public function testGetAdminTokenWithMissingEnv()
214+
{
215+
// Set --force to true
216+
$this->mockForceGenerate(false);
217+
218+
// Unset env
219+
unset($_ENV['MAGENTO_ADMIN_USERNAME']);
220+
221+
// Mock ModuleResolver and applyCustomModuleMethods()
222+
$mockResolver = $this->setMockResolverClass();
223+
$resolver = ModuleResolver::getInstance();
224+
225+
// Expect exception
226+
$this->expectException(TestFrameworkException::class);
227+
$resolver->getModulesPath();
228+
}
229+
230+
/**
231+
* Verify the getAdminToken method returns throws an exception if Token was bad.
232+
*/
233+
public function testGetAdminTokenWithBadResponse()
234+
{
235+
// Set --force to true
236+
$this->mockForceGenerate(false);
237+
238+
// Mock ModuleResolver and applyCustomModuleMethods()
239+
$mockResolver = $this->setMockResolverClass();
240+
$resolver = ModuleResolver::getInstance();
241+
242+
// Expect exception
243+
$this->expectException(TestFrameworkException::class);
244+
$resolver->getModulesPath();
178245
}
179246

180247
/**
@@ -205,7 +272,7 @@ private function setMockResolverClass(
205272
if (isset($mockToken)) {
206273
$mockMethods['getAdminToken'] = $mockToken;
207274
}
208-
if (isset($mockModules)) {
275+
if (isset($mockGetModules)) {
209276
$mockMethods['getEnabledModules'] = $mockGetModules;
210277
}
211278
if (isset($mockCustomMethods)) {
@@ -220,7 +287,7 @@ private function setMockResolverClass(
220287
if (isset($mockCustomModules)) {
221288
$mockMethods['getCustomModulePaths'] = $mockCustomModules;
222289
}
223-
$mockMethods['printMagentoVersionInfo'] = null;
290+
// $mockMethods['printMagentoVersionInfo'] = null;
224291

225292
$mockResolver = AspectMock::double(
226293
ModuleResolver::class,
@@ -260,12 +327,36 @@ private function setMockResolverProperties($instance, $mockPaths = null, $mockMo
260327
$property->setValue($instance, $mockBlacklist);
261328
}
262329

330+
/**
331+
* Mocks MftfApplicationConfig->forceGenerateEnabled()
332+
* @param $forceGenerate
333+
* @throws \Exception
334+
* @return void
335+
*/
336+
private function mockForceGenerate($forceGenerate)
337+
{
338+
$mockConfig = AspectMock::double(
339+
MftfApplicationConfig::class,
340+
['forceGenerateEnabled' => $forceGenerate]
341+
);
342+
$instance = AspectMock::double(
343+
ObjectManager::class,
344+
['create' => $mockConfig->make(), 'get' => null]
345+
)->make();
346+
AspectMock::double(ObjectManagerFactory::class, ['getObjectManager' => $instance]);
347+
}
348+
263349
/**
264350
* After method functionality
265351
* @return void
266352
*/
267353
protected function tearDown()
268354
{
355+
// re set env
356+
if (!isset($_ENV['MAGENTO_ADMIN_USERNAME'])) {
357+
$_ENV['MAGENTO_ADMIN_USERNAME'] = "admin";
358+
}
359+
269360
AspectMock::clean();
270361
}
271362
}

dev/tests/verification/Resources/DataReplacementTest.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,7 @@ class DataReplacementTestCest
5151
$I->searchAndMultiSelectOption("#selector", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]);
5252
$I->selectMultipleOptions("#Doe" . msq("uniqueData"), "#element", [msq("uniqueData") . "John", "Doe" . msq("uniqueData")]);
5353
$I->fillField(".selector", "0");
54+
$insertCommand = $I->magentoCLI("do something Doe" . msq("uniqueData") . " with uniqueness");
55+
$I->comment($insertCommand);
5456
}
5557
}

dev/tests/verification/Resources/functionalSuiteHooks.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class functionalSuiteHooks extends \Codeception\GroupObject
5858
$createThis = DataObjectHandler::getInstance()->getObject("createThis");
5959
$this->create = new DataPersistenceHandler($createThis, [], $createFields);
6060
$this->create->createEntity();
61+
$webDriver->see("John", msq("uniqueData") . "John");
6162

6263
// reset configuration and close session
6364
$this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig();
@@ -95,6 +96,7 @@ class functionalSuiteHooks extends \Codeception\GroupObject
9596
$webDriver->_initializeSession();
9697
$webDriver->amOnPage("some.url");
9798
$webDriver->deleteEntityByUrl("deleteThis");
99+
$webDriver->see("John", msq("uniqueData") . "John");
98100

99101
// reset configuration and close session
100102
$this->getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver')->_resetConfig();

dev/tests/verification/TestModule/ActionGroup/BasicActionGroup.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@
1919
<see selector="{{SampleSection.oneParamElement('test1')}}" userInput="{{someArgument.firstname}}" stepKey="seeFirstName" />
2020
</actionGroup>
2121

22+
<actionGroup name="actionGroupWithTwoArguments">
23+
<arguments>
24+
<argument name="somePerson"/>
25+
<argument name="anotherPerson"/>
26+
</arguments>
27+
28+
<see selector="{{anotherPerson.firstname}}" userInput="{{somePerson.firstname}}" stepKey="seeFirstName" />
29+
</actionGroup>
30+
2231
<actionGroup name="actionGroupWithSingleParameterSelectorFromArgument">
2332
<arguments>
2433
<argument name="someArgument" defaultValue="ReplacementPerson" />

dev/tests/verification/TestModule/Test/DataReplacementTest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@
3737
</selectMultipleOptions>
3838

3939
<fillField stepKey="insertZero" selector=".selector" userInput="{{simpleData.favoriteIndex}}"/>
40+
<magentoCLI stepKey="insertCommand" command="do something {{uniqueData.lastname}} with uniqueness"/>
4041
</test>
4142
</tests>

dev/tests/verification/_suite/functionalSuiteHooks.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,18 @@
1616
<createData entity="createThis" stepKey="create">
1717
<field key="someKey">dataHere</field>
1818
</createData>
19+
<actionGroup ref="actionGroupWithTwoArguments" stepKey="AC">
20+
<argument name="somePerson" value="simpleData"/>
21+
<argument name="anotherPerson" value="uniqueData"/>
22+
</actionGroup>
1923
</before>
2024
<after>
2125
<amOnPage url="some.url" stepKey="after"/>
2226
<deleteData url="deleteThis" stepKey="delete"/>
27+
<actionGroup ref="actionGroupWithTwoArguments" stepKey="AC">
28+
<argument name="somePerson" value="simpleData"/>
29+
<argument name="anotherPerson" value="uniqueData"/>
30+
</actionGroup>
2331
</after>
2432
</suite>
2533
</suites>

etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@
361361
<argument name="idAttributes" xsi:type="array">
362362
<item name="/suites/suite" xsi:type="string">name</item>
363363
<item name="/suites/suite/(before|after)/remove" xsi:type="string">keyForRemoval</item>
364+
<item name="/suites/suite/(before|after)/actionGroup/argument" xsi:type="string">name</item>
364365
<item name="/suites/suite/(before|after)/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item>
365366
<item name="/suites/suite/(before|after)/createData/requiredEntity" xsi:type="string">createDataKey</item>
366367
<item name="/suites/suite/(before|after)/createData/field" xsi:type="string">key</item>
@@ -377,6 +378,7 @@
377378
<argument name="assocArrayAttributes" xsi:type="array">
378379
<item name="/suites/suite" xsi:type="string">name</item>
379380
<item name="/suites/suite/(before|after)/remove" xsi:type="string">keyForRemoval</item>
381+
<item name="/suites/suite/(before|after)/actionGroup/argument" xsi:type="string">name</item>
380382
<item name="/suites/suite/(before|after)/(actionGroup|&commonTestActions;)" xsi:type="string">stepKey</item>
381383
<item name="/suites/suite/(before|after)/createData/requiredEntity" xsi:type="string">createDataKey</item>
382384
<item name="/suites/suite/(before|after)/createData/field" xsi:type="string">key</item>

src/Magento/FunctionalTestingFramework/Config/Dom/ArrayNodeConfig.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ class ArrayNodeConfig
2424
*/
2525
private $assocArrays = [];
2626

27+
/**
28+
* Flat array of expanded patterns for matching xpath
29+
*
30+
* @var array
31+
*/
32+
private $flatAssocArray = [];
33+
2734
/**
2835
* Format: array('/numeric/array/path', ...)
2936
*
@@ -44,6 +51,7 @@ public function __construct(
4451
) {
4552
$this->nodePathMatcher = $nodePathMatcher;
4653
$this->assocArrays = $assocArrayAttributes;
54+
$this->flatAssocArray = $this->flattenToAssocKeyAttributes($assocArrayAttributes);
4755
$this->numericArrays = $numericArrays;
4856
}
4957

@@ -71,11 +79,68 @@ public function isNumericArray($nodeXpath)
7179
*/
7280
public function getAssocArrayKeyAttribute($nodeXpath)
7381
{
82+
if (array_key_exists($nodeXpath, $this->flatAssocArray)) {
83+
return $this->flatAssocArray[$nodeXpath];
84+
}
85+
7486
foreach ($this->assocArrays as $pathPattern => $keyAttribute) {
7587
if ($this->nodePathMatcher->match($pathPattern, $nodeXpath)) {
7688
return $keyAttribute;
7789
}
7890
}
7991
return null;
8092
}
93+
94+
/**
95+
* Function which takes a patterned list of xpath matchers and flattens to a single level array for
96+
* performance improvement
97+
*
98+
* @param array $assocArrayAttributes
99+
* @return array
100+
*/
101+
private function flattenToAssocKeyAttributes($assocArrayAttributes)
102+
{
103+
$finalPatterns = [];
104+
foreach ($assocArrayAttributes as $pattern => $key) {
105+
$vars = explode("/", ltrim($pattern, "/"));
106+
$stringPatterns = [""];
107+
foreach ($vars as $var) {
108+
if (strstr($var, "|")) {
109+
$repOpen = str_replace("(", "", $var);
110+
$repClosed = str_replace(")", "", $repOpen);
111+
$nestedPatterns = explode("|", $repClosed);
112+
$stringPatterns = $this->mergeStrings($stringPatterns, $nestedPatterns);
113+
continue;
114+
}
115+
116+
// append this path to all of the paths that currently exist
117+
array_walk($stringPatterns, function (&$value, $key) use ($var) {
118+
$value .= "/" . $var;
119+
});
120+
}
121+
122+
$finalPatterns = array_merge($finalPatterns, array_fill_keys($stringPatterns, $key));
123+
}
124+
125+
return $finalPatterns;
126+
}
127+
128+
/**
129+
* Takes 2 arrays and appends all string in the second array to each entry in the first.
130+
*
131+
* @param string[] $parentStrings
132+
* @param string[] $childStrings
133+
* @return array
134+
*/
135+
private function mergeStrings($parentStrings, $childStrings)
136+
{
137+
$result = [];
138+
foreach ($parentStrings as $pString) {
139+
foreach ($childStrings as $cString) {
140+
$result[] = $pString . "/" . $cString;
141+
}
142+
}
143+
144+
return $result;
145+
}
81146
}

src/Magento/FunctionalTestingFramework/Console/BuildProjectCommand.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
7676
$codeceptBuildCommand = realpath(PROJECT_ROOT . '/vendor/bin/codecept') . ' build';
7777
$process = new Process($codeceptBuildCommand);
7878
$process->setWorkingDirectory(TESTS_BP);
79+
$process->setIdleTimeout(600);
80+
$process->setTimeout(0);
7981
$process->run(
8082
function ($type, $buffer) use ($output) {
8183
if ($output->isVerbose()) {

src/Magento/FunctionalTestingFramework/Console/GenerateTestsCommand.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
7777
$testManifest->createTestGroups($time);
7878
}
7979

80-
SuiteGenerator::getInstance()->generateAllSuites($testManifest);
80+
if (empty($tests)) {
81+
SuiteGenerator::getInstance()->generateAllSuites($testManifest);
82+
}
83+
8184
$testManifest->generate();
8285

8386
$output->writeln("Generate Tests Command Run");

src/Magento/FunctionalTestingFramework/Console/RunTestCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
6363

6464
$process = new Process($codeceptionCommand);
6565
$process->setWorkingDirectory(TESTS_BP);
66+
$process->setIdleTimeout(600);
67+
$process->setTimeout(0);
6668
$process->run(
6769
function ($type, $buffer) use ($output) {
6870
$output->write($buffer);
6971
}
7072
);
7173
}
72-
7374
}

src/Magento/FunctionalTestingFramework/Console/RunTestGroupCommand.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
6868

6969
$process = new Process($codeceptionCommand);
7070
$process->setWorkingDirectory(TESTS_BP);
71+
$process->setIdleTimeout(600);
72+
$process->setTimeout(0);
7173
$process->run(
7274
function ($type, $buffer) use ($output) {
7375
$output->write($buffer);

0 commit comments

Comments
 (0)