From 10564d39f3b24f54ca03a8f1814cb463444bc307 Mon Sep 17 00:00:00 2001 From: hschoenenberger Date: Mon, 30 Dec 2024 17:42:20 +0100 Subject: [PATCH] refactor: implement 5.6 compat with conditional class loading instead of sed transformation --- Makefile | 15 +- tests/BaseTestCase.php | 300 ++++++++++++++++++ .../UpgradeModuleHandlerTest.php | 4 +- tests/Feature/FeatureTestCase.php | 4 +- tests/TestCase.php | 298 +---------------- tests/TestCase56.php | 16 + tests/TestCase71.php | 18 ++ .../UpgradeModuleHandlerTest.php | 4 +- .../Session/ShopSession/RefreshTokenTest.php | 8 +- tests/Unit/Cqrs/CommandBusTest.php | 4 +- .../CircuitBreaker/CircuitBreakerTest.php | 6 +- .../GetOrRefreshTokenTest.php | 4 +- 12 files changed, 357 insertions(+), 324 deletions(-) create mode 100644 tests/BaseTestCase.php create mode 100644 tests/TestCase56.php create mode 100644 tests/TestCase71.php diff --git a/Makefile b/Makefile index 45b0892eb..755f9cd5d 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,7 @@ platform-init: platform-pull platform-restart platform-is-alive platform-module- # PS80 | 7.4 - 8.0 | vendor71 # PS90 | 8.O - * | vendor80 -platform-1.6.1.24-5.6-fpm-stretch: phpunit-fix-compat-php56 +platform-1.6.1.24-5.6-fpm-stretch: $(call build-platform,$@,,,composer56.json,phpstan\-PS\-1.6.neon) platform-1.6.1.24-7.1: @@ -164,19 +164,6 @@ phpunit-display-logs: phpunit: phpunit-run-unit phpunit-run-feature -REGEX_COMPAT_VOID := "s/\(function \(setUp\|tearDown\)()\)\(: void\)\?/\1/" -REGEX_COMPAT_TRAIT := "s/\#\?\(use \\\\DMS\\\\PHPUnitExtensions\\\\ArraySubset\\\\ArraySubsetAsserts;\)/\#\1/" -phpunit-fix-compat-php56: - @echo "fixing compat for php56..." - find ./tests -type f -name "TestCase.php" -exec sed -i -e ${REGEX_COMPAT_TRAIT} {} \; - find ./tests -type f -name "TestCase.php" -exec sed -i -e ${REGEX_COMPAT_VOID} {} \; - find ./tests/Unit -type f -name "*.php" -exec sed -i -e ${REGEX_COMPAT_VOID} {} \; - find ./tests/Feature -type f -name "*.php" -exec sed -i -e ${REGEX_COMPAT_VOID} {} \; - -phpunit-reset-compat-php56: REGEX_COMPAT_VOID := "s/\(function \(setUp\|tearDown\)()\)\(: void\)\?/\1: void/" -phpunit-reset-compat-php56: REGEX_COMPAT_TRAIT := "s/\#\?\(use \\\\DMS\\\\PHPUnitExtensions\\\\ArraySubset\\\\ArraySubsetAsserts;\)/\1/" -phpunit-reset-compat-php56: phpunit-fix-compat-php56 - ######### # PHPSTAN diff --git a/tests/BaseTestCase.php b/tests/BaseTestCase.php new file mode 100644 index 000000000..865d15fd6 --- /dev/null +++ b/tests/BaseTestCase.php @@ -0,0 +1,300 @@ +enableTransactions) { + $this->startTransaction(); + } + + $this->faker = \Faker\Factory::create(); + + $this->module = $this->getModuleInstance(); + + (new ServiceInjector($this, function ($propName, $class) { + $this->$propName = $this->module->getService($class); + }))->resolveServices(); + } + + /** + * @return void + */ + public function tear_down() + { + $this->rollback(); + + // FIXME: shouldn't every test class do its cleanup ? + foreach ([ + ShopSession::class, + Firebase\ShopSession::class, + Firebase\OwnerSession::class + ] as $class) { + $this->module->getService($class)->resetRefreshTokenErrors(); + } + + $this->restoreProperties(); + + parent::tearDown(); + } + + /** + * @param \DateTimeImmutable|null $expiresAt + * @param array $claims + * + * @return Token + */ + public function makeJwtToken(\DateTimeImmutable $expiresAt = null, array $claims = []) + { + $builder = (new Builder())->expiresAt($expiresAt); + + if (isset($claims['sub'])) { + $builder->relatedTo($claims['sub']); + unset($claims['sub']); + } + + foreach ($claims as $claim => $value) { + $builder->withClaim($claim, $value); + } + + $configuration = Configuration::forUnsecuredSigner(); + + return $builder->getToken( + $configuration->signer(), + $configuration->signingKey() + ); + } + + /** + * @param \DateTimeImmutable|null $expiresAt + * @param array $claims + * + * @return Token + * + * @throws \Exception + */ + public function makeFirebaseToken(\DateTimeImmutable $expiresAt = null, array $claims = []) + { + if (null === $expiresAt) { + $expiresAt = new \DateTimeImmutable('tomorrow'); + } + return $this->makeJwtToken($expiresAt, array_merge([ + 'sub' => $this->faker->uuid, + 'email' => $this->faker->safeEmail, + 'email_verified' => $this->faker->boolean, + ], $claims)); + } + + /** + * @return void + */ + public function startTransaction() + { + Db::getInstance()->execute('START TRANSACTION'); + } + + /** + * @return void + */ + public function rollback() + { + Db::getInstance()->execute('ROLLBACK'); + } + + /** + * @return Ps_accounts + * + * @throws Exception + */ + protected function getModuleInstance() + { + /** @var Ps_accounts|false $module */ + $module = Module::getInstanceByName('ps_accounts'); + + if ($module === false) { + throw new Exception('Module not installed'); + } + + return $module; + } + + /** + * @param array $body + * @param int $httpCode + * @param bool $status + * + * @return array + */ + protected function createApiResponse(array $body, $httpCode, $status) + { + return [ + 'status' => $status, + 'httpCode' => $httpCode, + 'body' => $body, + ]; + } + + /** + * @param $class + * @param $methods + * + * @return \#o#Э#A#M#C\PrestaShop\Module\PsAccounts\Tests\TestCase.createMockWithMethods.0|(\#o#Э#A#M#C\PrestaShop\Module\PsAccounts\Tests\TestCase.createMockWithMethods.0&\PHPUnit_Framework_MockObject_MockObject)|\PHPUnit_Framework_MockObject_MockObject + */ + protected function createMockWithMethods($class, $methods = []) + { + $mock = $this->createMock($class); + foreach ($methods as $method => $return) { + $mock->method($method)->willReturn($return); + } + return $mock; + } + + /** + * FIXME: hard dependency with non public members + * + * @param mixed $object + * @param string $propertyName + * @param mixed $replacement + * + * @return void + * + * @throws \ReflectionException + */ + protected function replaceProperty($object, $propertyName, $replacement) + { + $reflection = new \ReflectionClass($object); + $property = $reflection->getProperty($propertyName); + $property->setAccessible(true); + $this->setPropertyToRestore($object, $propertyName, $property->getValue($object)); + $property->setValue($object, $replacement); + } + + /** + * @param mixed $object + * @param string $propertyName + * @param mixed $originalValue + * + * @return void + */ + protected function setPropertyToRestore($object, $propertyName, $originalValue) + { + $prop = new ServiceProperty(); + $prop->object = $object; + $prop->propertyName = $propertyName; + $prop->originalValue = $originalValue; + $this->replacedProperties[] = $prop; + } + + /** + * @return void + * + * @throws \ReflectionException + */ + protected function restoreProperties() + { + foreach ($this->replacedProperties as $property) { + $this->replaceProperty( + $property->object, + $property->propertyName, + $property->originalValue + ); + } + $this->replacedProperties = []; + } + + /** + * @param array $subset + * @param array $array + * @param string $message + * @param bool $markTestIncomplete + * + * @return void + */ + protected function assertBodySubset($subset, $array, $message = '', $markTestIncomplete = false) + { + if (!$markTestIncomplete || is_array($array)) { + $this->assertArraySubset($subset, $array, $message); + } else { + $this->markTestIncomplete('WARNING: Cannot evaluate response [body is empty]'); + } + } + + /** + * @param array $subset + * @param array $array + * @param string $message + * + * @return void + */ + protected function assertBodySubsetOrMarkAsIncomplete($subset, $array, $message = '') + { + $this->assertBodySubset($subset, $array, $message, true); + } +} diff --git a/tests/Feature/Account/CommandHandler/UpgradeModuleHandlerTest.php b/tests/Feature/Account/CommandHandler/UpgradeModuleHandlerTest.php index da7e8e164..4647dacd3 100644 --- a/tests/Feature/Account/CommandHandler/UpgradeModuleHandlerTest.php +++ b/tests/Feature/Account/CommandHandler/UpgradeModuleHandlerTest.php @@ -21,9 +21,9 @@ class UpgradeModuleHandlerTest extends FeatureTestCase */ private $cookieJar; - public function setUp(): void + public function set_up() { - parent::setUp(); + parent::set_up(); if (version_compare(_PS_VERSION_, '1.7.0.0', '<') || version_compare(_PS_VERSION_, '9', '>=')) { diff --git a/tests/Feature/FeatureTestCase.php b/tests/Feature/FeatureTestCase.php index bba0d06d9..4f0822b83 100644 --- a/tests/Feature/FeatureTestCase.php +++ b/tests/Feature/FeatureTestCase.php @@ -41,9 +41,9 @@ class FeatureTestCase extends TestCase * * @throws \Exception */ - public function setUp(): void + public function set_up() { - parent::setUp(); + parent::set_up(); $scheme = $this->configuration->get('PS_SSL_ENABLED') ? 'https://' : 'http://'; $domain = $this->configuration->get('PS_SHOP_DOMAIN'); diff --git a/tests/TestCase.php b/tests/TestCase.php index 1e5609631..2ff6f3bde 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,301 +2,13 @@ namespace PrestaShop\Module\PsAccounts\Tests; -use Db; -use Exception; -use Faker\Generator; -use Module; -use PrestaShop\Module\PsAccounts\Account\Session\Firebase; -use PrestaShop\Module\PsAccounts\Account\Session\ShopSession; -use PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Builder; -use PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Configuration; -use PrestaShop\Module\PsAccounts\Vendor\Lcobucci\JWT\Token; -use Ps_accounts; - -class TestCase extends \PHPUnit\Framework\TestCase -{ - use \DMS\PHPUnitExtensions\ArraySubset\ArraySubsetAsserts; - - /** - * @var Generator - */ - public $faker; - - /** - * @var Ps_accounts - */ - public $module; - - /** - * @inject - * @var \PrestaShop\Module\PsAccounts\Cqrs\CommandBus - */ - public $commandBus; - - /** - * @inject - * @var \PrestaShop\Module\PsAccounts\Adapter\Configuration - */ - public $configuration; - - /** - * @inject - * @var \PrestaShop\Module\PsAccounts\Repository\ConfigurationRepository - */ - public $configurationRepository; - - /** - * @inject - * @var \PrestaShop\Module\PsAccounts\Account\LinkShop - */ - public $linkShop; - - /** - * @var bool - */ - protected $enableTransactions = true; - - /** - * @var ServiceProperty[] - */ - protected $replacedProperties = []; - - /** - * @return void - * - * @throws \Exception - */ - protected function setUp(): void - { - // Don't remove this line - \Configuration::clearConfigurationCacheForTesting(); - - parent::setUp(); - - if (true === $this->enableTransactions) { - $this->startTransaction(); - } - - $this->faker = \Faker\Factory::create(); - - $this->module = $this->getModuleInstance(); - - (new ServiceInjector($this, function ($propName, $class) { - $this->$propName = $this->module->getService($class); - }))->resolveServices(); - } - - /** - * @return void - */ - public function tearDown(): void - { - $this->rollback(); - - // FIXME: shouldn't every test class do its cleanup ? - foreach ([ - ShopSession::class, - Firebase\ShopSession::class, - Firebase\OwnerSession::class - ] as $class) { - $this->module->getService($class)->resetRefreshTokenErrors(); - } - - $this->restoreProperties(); - - parent::tearDown(); - } - - /** - * @param \DateTimeImmutable|null $expiresAt - * @param array $claims - * - * @return Token - */ - public function makeJwtToken(\DateTimeImmutable $expiresAt = null, array $claims = []) - { - $builder = (new Builder())->expiresAt($expiresAt); - - if (isset($claims['sub'])) { - $builder->relatedTo($claims['sub']); - unset($claims['sub']); - } - - foreach ($claims as $claim => $value) { - $builder->withClaim($claim, $value); - } - - $configuration = Configuration::forUnsecuredSigner(); - - return $builder->getToken( - $configuration->signer(), - $configuration->signingKey() - ); - } - - /** - * @param \DateTimeImmutable|null $expiresAt - * @param array $claims - * - * @return Token - * - * @throws \Exception - */ - public function makeFirebaseToken(\DateTimeImmutable $expiresAt = null, array $claims = []) +if (version_compare(phpversion(), '7.1', '>=')) { + class TestCase extends TestCase71 { - if (null === $expiresAt) { - $expiresAt = new \DateTimeImmutable('tomorrow'); - } - return $this->makeJwtToken($expiresAt, array_merge([ - 'sub' => $this->faker->uuid, - 'email' => $this->faker->safeEmail, - 'email_verified' => $this->faker->boolean, - ], $claims)); } - - /** - * @return void - */ - public function startTransaction() - { - Db::getInstance()->execute('START TRANSACTION'); - } - - /** - * @return void - */ - public function rollback() - { - Db::getInstance()->execute('ROLLBACK'); - } - - /** - * @return Ps_accounts - * - * @throws Exception - */ - protected function getModuleInstance() - { - /** @var Ps_accounts|false $module */ - $module = Module::getInstanceByName('ps_accounts'); - - if ($module === false) { - throw new Exception('Module not installed'); - } - - return $module; - } - - /** - * @param array $body - * @param int $httpCode - * @param bool $status - * - * @return array - */ - protected function createApiResponse(array $body, $httpCode, $status) +} else { + class TestCase extends TestCase56 { - return [ - 'status' => $status, - 'httpCode' => $httpCode, - 'body' => $body, - ]; - } - - /** - * @param $class - * @param $methods - * - * @return \#o#Э#A#M#C\PrestaShop\Module\PsAccounts\Tests\TestCase.createMockWithMethods.0|(\#o#Э#A#M#C\PrestaShop\Module\PsAccounts\Tests\TestCase.createMockWithMethods.0&\PHPUnit_Framework_MockObject_MockObject)|\PHPUnit_Framework_MockObject_MockObject - */ - protected function createMockWithMethods($class, $methods = []) - { - $mock = $this->createMock($class); - foreach ($methods as $method => $return) { - $mock->method($method)->willReturn($return); - } - return $mock; - } - - /** - * FIXME: hard dependency with non public members - * - * @param mixed $object - * @param string $propertyName - * @param mixed $replacement - * - * @return void - * - * @throws \ReflectionException - */ - protected function replaceProperty($object, $propertyName, $replacement) - { - $reflection = new \ReflectionClass($object); - $property = $reflection->getProperty($propertyName); - $property->setAccessible(true); - $this->setPropertyToRestore($object, $propertyName, $property->getValue($object)); - $property->setValue($object, $replacement); - } - - /** - * @param mixed $object - * @param string $propertyName - * @param mixed $originalValue - * - * @return void - */ - protected function setPropertyToRestore($object, $propertyName, $originalValue) - { - $prop = new ServiceProperty(); - $prop->object = $object; - $prop->propertyName = $propertyName; - $prop->originalValue = $originalValue; - $this->replacedProperties[] = $prop; - } - - /** - * @return void - * - * @throws \ReflectionException - */ - protected function restoreProperties() - { - foreach ($this->replacedProperties as $property) { - $this->replaceProperty( - $property->object, - $property->propertyName, - $property->originalValue - ); - } - $this->replacedProperties = []; - } - - /** - * @param array $subset - * @param array $array - * @param string $message - * @param bool $markTestIncomplete - * - * @return void - */ - protected function assertBodySubset($subset, $array, $message = '', $markTestIncomplete = false) - { - if (!$markTestIncomplete || is_array($array)) { - $this->assertArraySubset($subset, $array, $message); - } else { - $this->markTestIncomplete('WARNING: Cannot evaluate response [body is empty]'); - } - } - - /** - * @param array $subset - * @param array $array - * @param string $message - * - * @return void - */ - protected function assertBodySubsetOrMarkAsIncomplete($subset, $array, $message = '') - { - $this->assertBodySubset($subset, $array, $message, true); } } + diff --git a/tests/TestCase56.php b/tests/TestCase56.php new file mode 100644 index 000000000..e688221fd --- /dev/null +++ b/tests/TestCase56.php @@ -0,0 +1,16 @@ +set_up(); + } + + protected function tearDown() + { + $this->tear_down(); + } +} diff --git a/tests/TestCase71.php b/tests/TestCase71.php new file mode 100644 index 000000000..c58fa8124 --- /dev/null +++ b/tests/TestCase71.php @@ -0,0 +1,18 @@ +set_up(); + } + + protected function tearDown(): void + { + $this->tear_down(); + } +} diff --git a/tests/Unit/Account/CommandHandler/UpgradeModuleHandlerTest.php b/tests/Unit/Account/CommandHandler/UpgradeModuleHandlerTest.php index 0828c1466..a6b57f6a2 100644 --- a/tests/Unit/Account/CommandHandler/UpgradeModuleHandlerTest.php +++ b/tests/Unit/Account/CommandHandler/UpgradeModuleHandlerTest.php @@ -50,9 +50,9 @@ class UpgradeModuleHandlerTest extends TestCase */ protected $shopId = 1; - public function setUp(): void + public function set_up() { - parent::setUp(); + parent::set_up(); $this->firebaseToken = new Token((string) $this->makeJwtToken(new \DateTimeImmutable()), 'not-fresh'); $this->firebaseRefreshedToken = new Token((string) $this->makeJwtToken(new \DateTimeImmutable('+1hour')), 'not-fresh'); diff --git a/tests/Unit/Account/Session/ShopSession/RefreshTokenTest.php b/tests/Unit/Account/Session/ShopSession/RefreshTokenTest.php index 0072bedb3..2146090eb 100644 --- a/tests/Unit/Account/Session/ShopSession/RefreshTokenTest.php +++ b/tests/Unit/Account/Session/ShopSession/RefreshTokenTest.php @@ -42,9 +42,9 @@ class RefreshTokenTest extends TestCase */ protected $validAccessToken; - function setUp(): void + function set_up() { - parent::setUp(); + parent::set_up(); $this->validAccessToken = $this->makeJwtToken(new \DateTimeImmutable('tomorrow')); $shopProvider = $this->createMock(ShopProvider::class); @@ -70,9 +70,9 @@ function setUp(): void /** * @return void */ - public function tearDown(): void + public function tear_down() { - parent::tearDown(); + parent::tear_down(); $this->shopSession->cleanup(); } diff --git a/tests/Unit/Cqrs/CommandBusTest.php b/tests/Unit/Cqrs/CommandBusTest.php index 898ce2f68..1dc59b602 100644 --- a/tests/Unit/Cqrs/CommandBusTest.php +++ b/tests/Unit/Cqrs/CommandBusTest.php @@ -37,9 +37,9 @@ class CommandBusTest extends TestCase * * @throws \Exception */ - public function setUp(): void + public function set_up() { - parent::setUp(); + parent::set_up(); $this->commandBus = $this->module->getService(CommandBus::class); } diff --git a/tests/Unit/Http/Client/CircuitBreaker/CircuitBreakerTest.php b/tests/Unit/Http/Client/CircuitBreaker/CircuitBreakerTest.php index 3046bccb0..419e4af7a 100644 --- a/tests/Unit/Http/Client/CircuitBreaker/CircuitBreakerTest.php +++ b/tests/Unit/Http/Client/CircuitBreaker/CircuitBreakerTest.php @@ -1,10 +1,10 @@ circuitBreaker = $this->createCircuitBreaker( 'FOO_BAR', diff --git a/tests/Unit/Service/PsAccountsService/GetOrRefreshTokenTest.php b/tests/Unit/Service/PsAccountsService/GetOrRefreshTokenTest.php index a63ee0cf2..57d29dc15 100644 --- a/tests/Unit/Service/PsAccountsService/GetOrRefreshTokenTest.php +++ b/tests/Unit/Service/PsAccountsService/GetOrRefreshTokenTest.php @@ -30,9 +30,9 @@ class GetOrRefreshTokenTest extends TestCase */ protected $oauthClient; - public function setUp(): void + public function set_up() { - parent::setUp(); + parent::set_up(); $this->configurationRepository->updateAccessToken('');