diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php index f91f071f0..1fe5bb6b5 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/Config/Reader/FilesystemTest.php @@ -3,20 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace tests\unit\Magento\FunctionalTestFramework\Config\Reader; +use Magento\FunctionalTestingFramework\Config\ConverterInterface; use Magento\FunctionalTestingFramework\Config\FileResolver\Module; use Magento\FunctionalTestingFramework\Config\Reader\Filesystem; +use Magento\FunctionalTestingFramework\Config\SchemaLocatorInterface; use Magento\FunctionalTestingFramework\Config\ValidationState; use Magento\FunctionalTestingFramework\Util\Iterator\File; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use AspectMock\Test as AspectMock; use tests\unit\Util\TestLoggingUtil; class FilesystemTest extends TestCase { /** - * Before test functionality * @return void */ public function setUp(): void @@ -25,79 +28,80 @@ public function setUp(): void } /** - * Test Reading Empty Files * @throws \Exception */ public function testEmptyXmlFile() { - // create mocked items and read the file - $someFile = $this->setMockFile("somepath.xml", ""); - $filesystem = $this->createPseudoFileSystem($someFile); - $filesystem->read(); + $filesystem = $this->getFilesystem($this->getFileIterator('somepath.xml', '')); + $this->assertEquals([], $filesystem->read()); - // validate log statement TestLoggingUtil::getInstance()->validateMockLogStatement( - "warning", - "XML File is empty.", - ["File" => "somepath.xml"] + 'warning', + 'XML File is empty.', + ['File' => 'somepath.xml'] ); } /** - * Function used to set mock for File created in test + * Retrieve mocked file iterator * * @param string $fileName * @param string $content - * @return object + * @return File|MockObject * @throws \Exception */ - public function setMockFile($fileName, $content) + public function getFileIterator(string $fileName, string $content): File { - $file = AspectMock::double( - File::class, - [ - 'current' => "", - 'count' => 1, - 'getFilename' => $fileName - ] - )->make(); + $iterator = new \ArrayIterator([$content]); + + $file = $this->createMock(File::class); + + $file->method('current') + ->willReturn($content); + $file->method('getFilename') + ->willReturn($fileName); + $file->method('count') + ->willReturn(1); + + $file->method('next') + ->willReturnCallback(function () use ($iterator): void { + $iterator->next(); + }); - //set mocked data property for File - $property = new \ReflectionProperty(File::class, 'data'); - $property->setAccessible(true); - $property->setValue($file, [$fileName => $content]); + $file->method('valid') + ->willReturnCallback(function () use ($iterator): bool { + return $iterator->valid(); + }); return $file; } /** - * Function used to set mock for filesystem class during test + * Get real instance of Filesystem class with mocked dependencies * - * @param string $fileList - * @return object - * @throws \Exception + * @param File $fileIterator + * @return Filesystem */ - public function createPseudoFileSystem($fileList) + public function getFilesystem(File $fileIterator): Filesystem { - $filesystem = AspectMock::double(Filesystem::class)->make(); - - //set resolver to use mocked resolver - $mockFileResolver = AspectMock::double(Module::class, ['get' => $fileList])->make(); - $property = new \ReflectionProperty(Filesystem::class, 'fileResolver'); - $property->setAccessible(true); - $property->setValue($filesystem, $mockFileResolver); - - //set validator to use mocked validator - $mockValidation = AspectMock::double(ValidationState::class, ['isValidationRequired' => false])->make(); - $property = new \ReflectionProperty(Filesystem::class, 'validationState'); - $property->setAccessible(true); - $property->setValue($filesystem, $mockValidation); + $fileResolver = $this->createMock(Module::class); + $fileResolver->method('get') + ->willReturn($fileIterator); + $validationState = $this->createMock(ValidationState::class); + $validationState->method('isValidationRequired') + ->willReturn(false); + $filesystem = new Filesystem( + $fileResolver, + $this->createMock(ConverterInterface::class), + $this->createMock(SchemaLocatorInterface::class), + $validationState, + '' + ); return $filesystem; } /** - * After class functionality * @return void */ public static function tearDownAfterClass(): void diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/AnnotationsCheckTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/AnnotationsCheckTest.php index 010a9e357..004955998 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/AnnotationsCheckTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/AnnotationsCheckTest.php @@ -3,32 +3,27 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace tests\unit\Magento\FunctionalTestFramework\StaticCheck; -use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\StaticCheck\AnnotationsCheck; use Magento\FunctionalTestingFramework\Test\Objects\TestObject; -use tests\unit\Util\MagentoTestCase; use ReflectionClass; +use tests\unit\Util\MagentoTestCase; class AnnotationsCheckTest extends MagentoTestCase { /** @var AnnotationsCheck */ private $staticCheck; - /** @var ReflectionClass*/ + /** @var ReflectionClass */ private $staticCheckClass; public function setUp(): void { $this->staticCheck = new AnnotationsCheck(); - $this->staticCheckClass = new \ReflectionClass($this->staticCheck); - } - - public function tearDown(): void - { - AspectMock::clean(); + $this->staticCheckClass = new ReflectionClass($this->staticCheck); } public function testValidateRequiredAnnotationsNoError() @@ -56,11 +51,9 @@ public function testValidateRequiredAnnotationsNoError() ]; $expected = []; - // mock test object - $test = AspectMock::double( - TestObject::class, - ['getAnnotations' => $annotations, 'getName' => 'AnnotationsCheckTest'] - )->make(); + $test = $this->createMock(TestObject::class); + + $test->expects($this->once())->method('getAnnotations')->willReturn($annotations); $validateRequiredAnnotations = $this->staticCheckClass->getMethod('validateRequiredAnnotations'); $validateRequiredAnnotations->setAccessible(true); @@ -99,11 +92,10 @@ public function testValidateRequiredAnnotationsMissing() ] ]; - // mock test object - $test = AspectMock::double( - TestObject::class, - ['getAnnotations' => $annotations, 'getName' => 'AnnotationsCheckTest'] - )->make(); + $test = $this->createMock(TestObject::class); + + $test->expects($this->once())->method('getAnnotations')->willReturn($annotations); + $test->expects($this->once())->method('getName')->willReturn('AnnotationsCheckTest'); $validateRequiredAnnotations = $this->staticCheckClass->getMethod('validateRequiredAnnotations'); $validateRequiredAnnotations->setAccessible(true); @@ -137,11 +129,10 @@ public function testValidateRequiredAnnotationsMissingNoTestCaseId() ] ]; - // mock test object - $test = AspectMock::double( - TestObject::class, - ['getAnnotations' => $annotations, 'getName' => 'AnnotationsCheckTest'] - )->make(); + $test = $this->createMock(TestObject::class); + + $test->expects($this->once())->method('getAnnotations')->willReturn($annotations); + $test->expects($this->once())->method('getName')->willReturn('AnnotationsCheckTest'); $validateRequiredAnnotations = $this->staticCheckClass->getMethod('validateRequiredAnnotations'); $validateRequiredAnnotations->setAccessible(true); @@ -179,11 +170,10 @@ public function testValidateRequiredAnnotationsEmpty() ] ]; - // mock test object - $test = AspectMock::double( - TestObject::class, - ['getAnnotations' => $annotations, 'getName' => 'AnnotationsCheckTest'] - )->make(); + $test = $this->createMock(TestObject::class); + + $test->expects($this->once())->method('getAnnotations')->willReturn($annotations); + $test->expects($this->once())->method('getName')->willReturn('AnnotationsCheckTest'); $validateRequiredAnnotations = $this->staticCheckClass->getMethod('validateRequiredAnnotations'); $validateRequiredAnnotations->setAccessible(true); diff --git a/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/DeprecatedEntityUsageCheckTest.php b/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/DeprecatedEntityUsageCheckTest.php index dc339c8a3..bb4c96e89 100644 --- a/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/DeprecatedEntityUsageCheckTest.php +++ b/dev/tests/unit/Magento/FunctionalTestFramework/StaticCheck/DeprecatedEntityUsageCheckTest.php @@ -6,7 +6,6 @@ namespace tests\unit\Magento\FunctionalTestFramework\StaticCheck; -use AspectMock\Test as AspectMock; use Magento\FunctionalTestingFramework\DataGenerator\Handlers\OperationDefinitionObjectHandler; use Magento\FunctionalTestingFramework\DataGenerator\Objects\EntityDataObject; use Magento\FunctionalTestingFramework\Page\Objects\ElementObject; @@ -34,11 +33,6 @@ public function setUp(): void $this->staticCheckClass = new \ReflectionClass($this->staticCheck); } - public function tearDown(): void - { - AspectMock::clean(); - } - public function testInvalidPathOption() { $input = $this->getMockBuilder(InputInterface::class) diff --git a/dev/tests/verification/Resources/BasicFunctionalTest.txt b/dev/tests/verification/Resources/BasicFunctionalTest.txt index 2a67888f6..29cfd9baf 100644 --- a/dev/tests/verification/Resources/BasicFunctionalTest.txt +++ b/dev/tests/verification/Resources/BasicFunctionalTest.txt @@ -113,6 +113,7 @@ class BasicFunctionalTestCest $generateDateKey2 = $date->format("H:i:s"); $getOtp = $I->getOTP(); // stepKey: getOtp + $getOtpWithInput = $I->getOTP("someInput"); // stepKey: getOtpWithInput $grabAttributeFromKey1 = $I->grabAttributeFrom(".functionalTestSelector", "someInput"); // stepKey: grabAttributeFromKey1 $grabCookieKey1 = $I->grabCookie("grabCookieInput", ['domain' => 'www.google.com']); // stepKey: grabCookieKey1 $grabFromCurrentUrlKey1 = $I->grabFromCurrentUrl("/grabCurrentUrl"); // stepKey: grabFromCurrentUrlKey1 diff --git a/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml index 81a43ca12..53bd1f7ef 100644 --- a/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml +++ b/dev/tests/verification/TestModule/Test/BasicFunctionalTest/BasicFunctionalTest.xml @@ -69,6 +69,7 @@ + diff --git a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php index 494c62908..edf490669 100644 --- a/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php +++ b/src/Magento/FunctionalTestingFramework/Config/Reader/Filesystem.php @@ -148,7 +148,7 @@ protected function readFiles($fileList) /** @var \Magento\FunctionalTestingFramework\Config\Dom $configMerger */ $configMerger = null; $debugLevel = MftfApplicationConfig::getConfig()->getDebugLevel(); - foreach ($fileList as $key => $content) { + foreach ($fileList as $content) { //check if file is empty and continue to next if it is if (!$this->verifyFileEmpty($content, $fileList->getFilename())) { continue; diff --git a/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php index dcd6715c9..32c1f6b81 100644 --- a/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php +++ b/src/Magento/FunctionalTestingFramework/DataTransport/Auth/Tfa/OTP.php @@ -20,42 +20,47 @@ class OTP /** * TOTP object * - * @var TOTP + * @var TOTP[] */ - private static $totp = null; + private static $totps = []; /** * Return OTP for custom secret stored in `magento/tfa/OTP_SHARED_SECRET` * + * @param string|null $path * @return string * @throws TestFrameworkException */ - public static function getOTP() + public static function getOTP($path = null) { - return self::create()->now(); + if ($path === null) { + $path = self::OTP_SHARED_SECRET_PATH; + } + return self::create($path)->now(); } /** * Create TOTP object * + * @param string $path * @return TOTP * @throws TestFrameworkException */ - private static function create() + private static function create($path) { - if (self::$totp === null) { + if (!isset(self::$totps[$path])) { try { // Get shared secret from Credential storage - $encryptedSecret = CredentialStore::getInstance()->getSecret(self::OTP_SHARED_SECRET_PATH); + $encryptedSecret = CredentialStore::getInstance()->getSecret($path); $secret = CredentialStore::getInstance()->decryptSecretValue($encryptedSecret); } catch (TestFrameworkException $e) { throw new TestFrameworkException('Unable to get OTP' . PHP_EOL . $e->getMessage()); } - self::$totp = TOTP::create($secret); - self::$totp->setIssuer('MFTF'); - self::$totp->setLabel('MFTF Testing'); + self::$totps[$path] = TOTP::create($secret); + self::$totps[$path]->setIssuer('MFTF'); + self::$totps[$path]->setLabel('MFTF Testing'); } - return self::$totp; + return self::$totps[$path]; } } diff --git a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php index 00e295606..7a3220921 100644 --- a/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php +++ b/src/Magento/FunctionalTestingFramework/Module/MagentoWebDriver.php @@ -970,12 +970,13 @@ public function makeScreenshot($name = null) /** * Return OTP based on a shared secret * + * @param string|null $secretsPath * @return string * @throws TestFrameworkException */ - public function getOTP() + public function getOTP($secretsPath = null) { - return OTP::getOTP(); + return OTP::getOTP($secretsPath); } /** diff --git a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd index b1d6e1b02..2ea291cd8 100644 --- a/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd +++ b/src/Magento/FunctionalTestingFramework/Test/etc/Actions/customActions.xsd @@ -335,6 +335,7 @@ + diff --git a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php index 9d2d097f4..b019d5f2a 100644 --- a/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php +++ b/src/Magento/FunctionalTestingFramework/Util/TestGenerator.php @@ -1262,7 +1262,8 @@ public function generateStepsPhp($actionObjects, $generationScope = TestGenerato $testSteps .= $this->wrapFunctionCallWithReturnValue( $stepKey, $actor, - $actionObject + $actionObject, + $input ); break; case "resizeWindow":