Skip to content

Commit fadb951

Browse files
Merge remote-tracking branch 'mainline/develop' into MAGETWO-46837-readiness-flag-develop
2 parents 5c2d01a + 62b6540 commit fadb951

File tree

12 files changed

+256
-29
lines changed

12 files changed

+256
-29
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"require": {
1212
"php": "7.0.2|7.0.4|~7.0.6|~7.1.0|~7.2.0",
1313
"allure-framework/allure-codeception": "~1.2.6",
14-
"codeception/codeception": "~2.3.4",
14+
"codeception/codeception": "~2.3.4 || ~2.4.0",
1515
"consolidation/robo": "^1.0.0",
1616
"epfremme/swagger-php": "^2.0",
1717
"flow/jsonpath": ">0.2",
@@ -23,7 +23,7 @@
2323
},
2424
"require-dev": {
2525
"squizlabs/php_codesniffer": "~3.2",
26-
"sebastian/phpcpd": "~3.0",
26+
"sebastian/phpcpd": "~3.0 || ~4.0",
2727
"brainmaestro/composer-git-hooks": "^2.3",
2828
"doctrine/cache": "<1.7.0",
2929
"codeception/aspect-mock": "^3.0",

composer.lock

Lines changed: 55 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dev/tests/verification/Resources/BasicFunctionalTest.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ class BasicFunctionalTestCest
9999
$executeJSKey1 = $I->executeJS("someJSFunction");
100100
$I->fillField(".functionalTestSelector", "someInput");
101101
$I->fillField(".functionalTestSelector", "0");
102+
$date = new \DateTime();
103+
$date->setTimestamp(strtotime("Now"));
104+
$date->setTimezone(new \DateTimeZone("America/Los_Angeles"));
105+
$generateDateKey = $date->format("H:i:s");
102106
$grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput");
103107
$grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']);
104108
$grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl");
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
namespace Magento\AcceptanceTest\_default\Backend;
3+
4+
use Magento\FunctionalTestingFramework\AcceptanceTester;
5+
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\DataObjectHandler;
6+
use Magento\FunctionalTestingFramework\DataGenerator\Persist\DataPersistenceHandler;
7+
use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject;
8+
use Magento\FunctionalTestingFramework\DataGenerator\Handlers\CredentialStore;
9+
use \Codeception\Util\Locator;
10+
use Yandex\Allure\Adapter\Annotation\Features;
11+
use Yandex\Allure\Adapter\Annotation\Stories;
12+
use Yandex\Allure\Adapter\Annotation\Title;
13+
use Yandex\Allure\Adapter\Annotation\Description;
14+
use Yandex\Allure\Adapter\Annotation\Parameter;
15+
use Yandex\Allure\Adapter\Annotation\Severity;
16+
use Yandex\Allure\Adapter\Model\SeverityLevel;
17+
use Yandex\Allure\Adapter\Annotation\TestCaseId;
18+
19+
/**
20+
*/
21+
class ExecuteJsEscapingTestCest
22+
{
23+
/**
24+
* @Features({"TestModule"})
25+
* @Parameter(name = "AcceptanceTester", value="$I")
26+
* @param AcceptanceTester $I
27+
* @return void
28+
* @throws \Exception
29+
*/
30+
public function ExecuteJsEscapingTest(AcceptanceTester $I)
31+
{
32+
$javaVariableEscape = $I->executeJS("return \$javascriptVariable");
33+
$mftfVariableNotEscaped = $I->executeJS("return {$doNotEscape}");
34+
}
35+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
<executeJS function="someJSFunction" stepKey="executeJSKey1"/>
6161
<fillField selector=".functionalTestSelector" userInput="someInput" stepKey="fillFieldKey1" />
6262
<fillField selector=".functionalTestSelector" userInput="0" stepKey="fillFieldKey2" />
63+
<generateDate date="Now" format="H:i:s" stepKey="generateDateKey"/>
6364
<grabAttributeFrom selector=".functionalTestSelector" userInput="someInput" stepKey="grabAttributeFromKey1" />
6465
<grabCookie userInput="grabCookieInput" parameterArray="['domain' => 'www.google.com']" stepKey="grabCookieKey1" />
6566
<grabFromCurrentUrl regex="/grabCurrentUrl" stepKey="grabFromCurrentUrlKey1" />
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="../../../../../src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd">
11+
<test name="ExecuteJsEscapingTest">
12+
<executeJS function="return $javascriptVariable" stepKey="javaVariableEscape"/>
13+
<executeJS function="return {$doNotEscape}" stepKey="mftfVariableNotEscaped"/>
14+
</test>
15+
</tests>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace tests\verification\Tests;
7+
8+
use tests\util\MftfTestCase;
9+
10+
class ExecuteJsTest extends MftfTestCase
11+
{
12+
/**
13+
* Tests escaping of $javascriptVariable => \$javascriptVariable in the executeJs function
14+
*
15+
* @throws \Exception
16+
* @throws \Magento\FunctionalTestingFramework\Exceptions\TestReferenceException
17+
*/
18+
public function testExecuteJsTest()
19+
{
20+
$this->generateAndCompareTest('ExecuteJsEscapingTest');
21+
}
22+
}

etc/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
<!-- Entity value gets replaced in Dom.php before reading $xml -->
1010
<!DOCTYPE config [
11-
<!ENTITY commonTestActions "acceptPopup|actionGroup|amOnPage|amOnUrl|amOnSubdomain|appendField|assertArrayIsSorted|assertArraySubset|assertElementContainsAttribute|attachFile|cancelPopup|checkOption|clearField|click|clickWithLeftButton|clickWithRightButton|closeAdminNotification|closeTab|comment|conditionalClick|createData|deleteData|updateData|getData|dontSee|dontSeeJsError|dontSeeCheckboxIsChecked|dontSeeCookie|dontSeeCurrentUrlEquals|dontSeeCurrentUrlMatches|dontSeeElement|dontSeeElementInDOM|dontSeeInCurrentUrl|dontSeeInField|dontSeeInFormFields|dontSeeInPageSource|dontSeeInSource|dontSeeInTitle|dontSeeLink|dontSeeOptionIsSelected|doubleClick|dragAndDrop|entity|executeJS|executeInSelenium|fillField|formatMoney|grabAttributeFrom|grabCookie|grabFromCurrentUrl|grabMultiple|grabPageSource|grabTextFrom|grabValueFrom|loadSessionSnapshot|loginAsAdmin|magentoCLI|makeScreenshot|maximizeWindow|moveBack|moveForward|moveMouseOver|mSetLocale|mResetLocale|openNewTab|pauseExecution|parseFloat|performOn|pressKey|reloadPage|resetCookie|submitForm|resizeWindow|saveSessionSnapshot|scrollTo|scrollToTopOfPage|searchAndMultiSelectOption|see|seeCheckboxIsChecked|seeCookie|seeCurrentUrlEquals|seeCurrentUrlMatches|seeElement|seeElementInDOM|seeInCurrentUrl|seeInField|seeInFormFields|seeInPageSource|seeInPopup|seeInSource|seeInTitle|seeLink|seeNumberOfElements|seeOptionIsSelected|selectOption|setCookie|submitForm|switchToIFrame|switchToNextTab|switchToPreviousTab|switchToWindow|typeInPopup|uncheckOption|unselectOption|wait|waitForAjaxLoad|waitForElement|waitForElementChange|waitForElementNotVisible|waitForElementVisible|waitForJS|waitForLoadingMaskToDisappear|waitForPageLoad|waitForText|assertArrayHasKey|assertArrayNotHasKey|assertArraySubset|assertContains|assertCount|assertEmpty|assertEquals|assertFalse|assertFileExists|assertFileNotExists|assertGreaterOrEquals|assertGreaterThan|assertGreaterThanOrEqual|assertInstanceOf|assertInternalType|assertIsEmpty|assertLessOrEquals|assertLessThan|assertLessThanOrEqual|assertNotContains|assertNotEmpty|assertNotEquals|assertNotInstanceOf|assertNotNull|assertNotRegExp|assertNotSame|assertNull|assertRegExp|assertSame|assertStringStartsNotWith|assertStringStartsWith|assertTrue|expectException|fail|dontSeeFullUrlEquals|dontSee|dontSeeFullUrlMatches|dontSeeInFullUrl|seeFullUrlEquals|seeFullUrlMatches|seeInFullUrl|grabFromFullUrl">
11+
<!ENTITY commonTestActions "acceptPopup|actionGroup|amOnPage|amOnUrl|amOnSubdomain|appendField|assertArrayIsSorted|assertArraySubset|assertElementContainsAttribute|attachFile|cancelPopup|checkOption|clearField|click|clickWithLeftButton|clickWithRightButton|closeAdminNotification|closeTab|comment|conditionalClick|createData|deleteData|updateData|getData|dontSee|dontSeeJsError|dontSeeCheckboxIsChecked|dontSeeCookie|dontSeeCurrentUrlEquals|dontSeeCurrentUrlMatches|dontSeeElement|dontSeeElementInDOM|dontSeeInCurrentUrl|dontSeeInField|dontSeeInFormFields|dontSeeInPageSource|dontSeeInSource|dontSeeInTitle|dontSeeLink|dontSeeOptionIsSelected|doubleClick|dragAndDrop|entity|executeJS|executeInSelenium|fillField|formatMoney|generateDate|grabAttributeFrom|grabCookie|grabFromCurrentUrl|grabMultiple|grabPageSource|grabTextFrom|grabValueFrom|loadSessionSnapshot|loginAsAdmin|magentoCLI|makeScreenshot|maximizeWindow|moveBack|moveForward|moveMouseOver|mSetLocale|mResetLocale|openNewTab|pauseExecution|parseFloat|performOn|pressKey|reloadPage|resetCookie|submitForm|resizeWindow|saveSessionSnapshot|scrollTo|scrollToTopOfPage|searchAndMultiSelectOption|see|seeCheckboxIsChecked|seeCookie|seeCurrentUrlEquals|seeCurrentUrlMatches|seeElement|seeElementInDOM|seeInCurrentUrl|seeInField|seeInFormFields|seeInPageSource|seeInPopup|seeInSource|seeInTitle|seeLink|seeNumberOfElements|seeOptionIsSelected|selectOption|setCookie|submitForm|switchToIFrame|switchToNextTab|switchToPreviousTab|switchToWindow|typeInPopup|uncheckOption|unselectOption|wait|waitForAjaxLoad|waitForElement|waitForElementChange|waitForElementNotVisible|waitForElementVisible|waitForJS|waitForLoadingMaskToDisappear|waitForPageLoad|waitForText|assertArrayHasKey|assertArrayNotHasKey|assertArraySubset|assertContains|assertCount|assertEmpty|assertEquals|assertFalse|assertFileExists|assertFileNotExists|assertGreaterOrEquals|assertGreaterThan|assertGreaterThanOrEqual|assertInstanceOf|assertInternalType|assertIsEmpty|assertLessOrEquals|assertLessThan|assertLessThanOrEqual|assertNotContains|assertNotEmpty|assertNotEquals|assertNotInstanceOf|assertNotNull|assertNotRegExp|assertNotSame|assertNull|assertRegExp|assertSame|assertStringStartsNotWith|assertStringStartsWith|assertTrue|expectException|fail|dontSeeFullUrlEquals|dontSee|dontSeeFullUrlMatches|dontSeeInFullUrl|seeFullUrlEquals|seeFullUrlMatches|seeInFullUrl|grabFromFullUrl">
1212
]>
1313

1414
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../src/Magento/FunctionalTestingFramework/ObjectManager/etc/config.xsd">

src/Magento/FunctionalTestingFramework/Extension/TestContextExtension.php

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ class TestContextExtension extends \Codeception\Extension
2323
*/
2424
public static $events = [
2525
Events::TEST_FAIL => 'testFail',
26-
Events::STEP_AFTER => 'afterStep'
26+
Events::STEP_AFTER => 'afterStep',
27+
Events::TEST_END => 'testError'
2728
];
2829

2930
/**
@@ -38,22 +39,61 @@ public function testFail(\Codeception\Event\FailEvent $e)
3839
// Do not attempt to run _after if failure was in the _after block
3940
// Try to run _after but catch exceptions to prevent them from overwriting original failure.
4041
if ($context != TestContextExtension::TEST_PHASE_AFTER) {
41-
try {
42-
$actorClass = $e->getTest()->getMetadata()->getCurrent('actor');
43-
$I = new $actorClass($cest->getScenario());
44-
call_user_func(\Closure::bind(
45-
function () use ($cest, $I) {
46-
$cest->executeHook($I, 'after');
47-
},
48-
null,
49-
$cest
50-
));
51-
} catch (\Exception $e) {
52-
// Do not rethrow Exception
42+
$this->runAfterBlock($e, $cest);
43+
}
44+
}
45+
46+
/**
47+
* Codeception event listener function, triggered on test error.
48+
* @param \Codeception\Event\TestEvent $e
49+
* @return void
50+
*/
51+
public function testError(\Codeception\Event\TestEvent $e)
52+
{
53+
$cest = $e->getTest();
54+
55+
//Access private TestResultObject to find stack and if there are any errors (as opposed to failures)
56+
$testResultObject = call_user_func(\Closure::bind(
57+
function () use ($cest) {
58+
return $cest->getTestResultObject();
59+
},
60+
$cest
61+
));
62+
$errors = $testResultObject->errors();
63+
if (!empty($errors)) {
64+
$stack = $errors[0]->thrownException()->getTrace();
65+
$context = $this->extractContext($stack, $cest->getTestMethod());
66+
// Do not attempt to run _after if failure was in the _after block
67+
// Try to run _after but catch exceptions to prevent them from overwriting original failure.
68+
if ($context != TestContextExtension::TEST_PHASE_AFTER) {
69+
$this->runAfterBlock($e, $cest);
5370
}
5471
}
5572
}
5673

74+
/**
75+
* Runs cest's after block, if necessary.
76+
* @param Symfony\Component\EventDispatcher\Event $e
77+
* @param \Codeception\TestInterface $cest
78+
* @return void
79+
*/
80+
private function runAfterBlock($e, $cest)
81+
{
82+
try {
83+
$actorClass = $e->getTest()->getMetadata()->getCurrent('actor');
84+
$I = new $actorClass($cest->getScenario());
85+
call_user_func(\Closure::bind(
86+
function () use ($cest, $I) {
87+
$cest->executeHook($I, 'after');
88+
},
89+
null,
90+
$cest
91+
));
92+
} catch (\Exception $e) {
93+
// Do not rethrow Exception
94+
}
95+
}
96+
5797
/**
5898
* Extracts hook method from trace, looking specifically for the cest class given.
5999
* @param array $trace

src/Magento/FunctionalTestingFramework/Test/Objects/ActionObject.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ class ActionObject
3939
"expectedResult",
4040
"actualResult",
4141
"command",
42-
"regex"
42+
"regex",
43+
"date",
44+
"format"
4345
];
4446
const SELECTOR_ENABLED_ATTRIBUTES = [
4547
'selector',

src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<xs:element type="scrollToTopOfPageType" name="scrollToTopOfPage" minOccurs="0" maxOccurs="unbounded"/>
2323
<xs:element type="clearFieldType" name="clearField" minOccurs="0" maxOccurs="unbounded"/>
2424
<xs:element type="assertArrayIsSortedType" name="assertArrayIsSorted" minOccurs="0" maxOccurs="unbounded"/>
25+
<xs:element type="generateDateType" name="generateDate" minOccurs="0" maxOccurs="unbounded"/>
2526
</xs:choice>
2627
</xs:group>
2728

@@ -219,6 +220,41 @@
219220
<xs:attributeGroup ref="commonActionAttributes"/>
220221
</xs:complexType>
221222

223+
<xs:complexType name="generateDateType">
224+
<xs:annotation>
225+
<xs:documentation>
226+
Generates a date according to input and format.
227+
</xs:documentation>
228+
</xs:annotation>
229+
<xs:simpleContent>
230+
<xs:extension base="xs:string">
231+
<xs:attribute name="date" use="required" type="xs:string">
232+
<xs:annotation>
233+
<xs:documentation>
234+
Date input to parse, uses same functionality as php strtotime() function.
235+
</xs:documentation>
236+
</xs:annotation>
237+
</xs:attribute>
238+
<xs:attribute name="format" use="required" type="xs:string">
239+
<xs:annotation>
240+
<xs:documentation>
241+
Format to save given date in, uses same functionality as php date() function.
242+
</xs:documentation>
243+
</xs:annotation>
244+
</xs:attribute>
245+
<xs:attribute name="timezone" use="optional" type="xs:string">
246+
<xs:annotation>
247+
<xs:documentation>
248+
Timezone to generate date in, defaults to "America/Los_Angeles".
249+
</xs:documentation>
250+
</xs:annotation>
251+
</xs:attribute>
252+
<xs:attributeGroup ref="commonActionAttributes"/>
253+
</xs:extension>
254+
</xs:simpleContent>
255+
</xs:complexType>
256+
257+
222258
<xs:complexType name="arrayType">
223259
<xs:simpleContent>
224260
<xs:extension base="xs:string">

0 commit comments

Comments
 (0)