From a936362a9a088b8bc752ffbe78899817d6662297 Mon Sep 17 00:00:00 2001 From: Morgan Pichat Date: Thu, 15 Feb 2024 16:02:45 +0100 Subject: [PATCH 1/5] Update Protected Endpoints tests --- tests/Integration/ApiPlatform/CustomerGroupApiTest.php | 6 +----- tests/Integration/ApiPlatform/ProductEndpointTest.php | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php index ede250c..4b79292 100644 --- a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php +++ b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php @@ -61,11 +61,7 @@ public function testProtectedEndpoints(string $method, string $uri): void $content = $response->getContent(false); $this->assertNotEmpty($content); - $decodedContent = json_decode($content, true); - $this->assertArrayHasKey('title', $decodedContent); - $this->assertArrayHasKey('detail', $decodedContent); - $this->assertStringContainsString('An error occurred', $decodedContent['title']); - $this->assertStringContainsString('Full authentication is required to access this resource.', $decodedContent['detail']); + $this->assertEquals('No Authorization header provided', $content); } public function getProtectedEndpoints(): iterable diff --git a/tests/Integration/ApiPlatform/ProductEndpointTest.php b/tests/Integration/ApiPlatform/ProductEndpointTest.php index a8522b6..4504af9 100644 --- a/tests/Integration/ApiPlatform/ProductEndpointTest.php +++ b/tests/Integration/ApiPlatform/ProductEndpointTest.php @@ -77,11 +77,7 @@ public function testProtectedEndpoints(string $method, string $uri, string $cont $content = $response->getContent(false); $this->assertNotEmpty($content); - $decodedContent = json_decode($content, true); - $this->assertArrayHasKey('title', $decodedContent); - $this->assertArrayHasKey('detail', $decodedContent); - $this->assertStringContainsString('An error occurred', $decodedContent['title']); - $this->assertStringContainsString('Full authentication is required to access this resource.', $decodedContent['detail']); + $this->assertEquals('No Authorization header provided', $content); } public function getProtectedEndpoints(): iterable From 5946d90f4a95bffcbf1ed6a8c2b3cd2038d66337 Mon Sep 17 00:00:00 2001 From: Jonathan Lelievre Date: Wed, 21 Feb 2024 17:35:24 +0100 Subject: [PATCH 2/5] Add check for delete endpoints, add tests for ApiClient endpoints --- .../ApiPlatform/ApiClientEndpointTest.php | 281 ++++++++++++++++++ .../ApiPlatform/CustomerGroupApiTest.php | 5 + .../ApiPlatform/ProductEndpointTest.php | 7 +- 3 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 tests/Integration/ApiPlatform/ApiClientEndpointTest.php diff --git a/tests/Integration/ApiPlatform/ApiClientEndpointTest.php b/tests/Integration/ApiPlatform/ApiClientEndpointTest.php new file mode 100644 index 0000000..6064581 --- /dev/null +++ b/tests/Integration/ApiPlatform/ApiClientEndpointTest.php @@ -0,0 +1,281 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +declare(strict_types=1); + +namespace PsApiResourcesTest\Integration\ApiPlatform; + +class ApiClientEndpointTest extends ApiTestCase +{ + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + self::createApiClient(['api_client_write', 'api_client_read']); + } + + /** + * @dataProvider getProtectedEndpoints + * + * @param string $method + * @param string $uri + */ + public function testProtectedEndpoints(string $method, string $uri, string $contentType = 'application/json'): void + { + $options['headers']['content-type'] = $contentType; + // Check that endpoints are not accessible without a proper Bearer token + $client = static::createClient([], $options); + $response = $client->request($method, $uri); + self::assertResponseStatusCodeSame(401); + + $content = $response->getContent(false); + $this->assertNotEmpty($content); + $this->assertEquals('No Authorization header provided', $content); + } + + public function getProtectedEndpoints(): iterable + { + yield 'get endpoint' => [ + 'GET', + '/api/api-client/1', + ]; + + yield 'create endpoint' => [ + 'POST', + '/api/api-client', + ]; + + yield 'update endpoint' => [ + 'PUT', + '/api/api-client/1', + ]; + + yield 'delete endpoint' => [ + 'DELETE', + '/api/api-client/1', + 'application/merge-patch+json', + ]; + } + + public function testAddApiClient(): int + { + $bearerToken = $this->getBearerToken(['api_client_write']); + $client = static::createClient(); + $response = $client->request('POST', '/api/api-client', [ + 'auth_bearer' => $bearerToken, + 'json' => [ + 'clientId' => 'client_id_test', + 'clientName' => 'Client name test', + 'description' => 'Client description test', + 'enabled' => true, + 'lifetime' => 3600, + 'scopes' => [ + 'api_client_read', + 'hook_read', + ], + ], + ]); + self::assertResponseStatusCodeSame(201); + $decodedResponse = json_decode($response->getContent(), true); + $this->assertNotFalse($decodedResponse); + $this->assertArrayHasKey('apiClientId', $decodedResponse); + $this->assertArrayHasKey('secret', $decodedResponse); + $apiClientId = $decodedResponse['apiClientId']; + $secret = $decodedResponse['secret']; + $this->assertEquals( + [ + 'apiClientId' => $apiClientId, + 'secret' => $secret, + ], + $decodedResponse + ); + + return $apiClientId; + } + + /** + * @depends testAddApiClient + * + * @param int $apiClientId + * + * @return int + */ + public function testGetApiClient(int $apiClientId): int + { + $bearerToken = $this->getBearerToken(['api_client_read']); + $client = static::createClient(); + $response = $client->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + ]); + self::assertResponseStatusCodeSame(200); + + $decodedResponse = json_decode($response->getContent(), true); + $this->assertNotFalse($decodedResponse); + $this->assertEquals( + [ + 'apiClientId' => $apiClientId, + 'clientId' => 'client_id_test', + 'clientName' => 'Client name test', + 'description' => 'Client description test', + 'enabled' => true, + 'lifetime' => 3600, + 'scopes' => [ + 'api_client_read', + 'hook_read', + ], + ], + $decodedResponse + ); + + return $apiClientId; + } + + /** + * @depends testGetApiClient + * + * @param int $apiClientId + * + * @return int + */ + public function testUpdateApiClient(int $apiClientId): int + { + $bearerToken = $this->getBearerToken(['api_client_write']); + $client = static::createClient(); + + // Update product with partial data, even multilang fields can be updated language by language + $response = $client->request('PUT', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + 'json' => [ + 'clientId' => 'client_id_test_updated', + 'clientName' => 'Client name test updated', + 'description' => 'Client description test updated', + 'enabled' => false, + 'lifetime' => 1800, + 'scopes' => [ + 'api_client_write', + 'hook_read', + ], + ], + ]); + self::assertResponseStatusCodeSame(200); + + $decodedResponse = json_decode($response->getContent(), true); + $this->assertNotFalse($decodedResponse); + // Returned data has modified fields, the others haven't changed + $this->assertEquals( + [ + 'apiClientId' => $apiClientId, + 'clientId' => 'client_id_test_updated', + 'clientName' => 'Client name test updated', + 'description' => 'Client description test updated', + 'enabled' => false, + 'lifetime' => 1800, + 'scopes' => [ + 'api_client_write', + 'hook_read', + ], + ], + $decodedResponse + ); + + return $apiClientId; + } + + /** + * @depends testUpdateApiClient + * + * @param int $apiClientId + * + * @return int + */ + public function testGetUpdatedApiClient(int $apiClientId): int + { + $bearerToken = $this->getBearerToken(['api_client_read']); + $client = static::createClient(); + $response = $client->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + ]); + self::assertResponseStatusCodeSame(200); + + $decodedResponse = json_decode($response->getContent(), true); + $this->assertNotFalse($decodedResponse); + $this->assertEquals( + [ + 'apiClientId' => $apiClientId, + 'clientId' => 'client_id_test_updated', + 'clientName' => 'Client name test updated', + 'description' => 'Client description test updated', + 'enabled' => false, + 'lifetime' => 1800, + 'scopes' => [ + 'api_client_write', + 'hook_read', + ], + ], + $decodedResponse + ); + + return $apiClientId; + } + + /** + * @depends testGetUpdatedApiClient + * + * @param int $apiClientId + */ + public function testDeleteApiClient(int $apiClientId): void + { + $bearerToken = $this->getBearerToken(['api_client_read', 'api_client_write']); + $client = static::createClient(); + + // Delete API client without token + $client->request('DELETE', '/api/api-client/' . $apiClientId); + self::assertResponseStatusCodeSame(401); + // Delete API client without token + $client->request('DELETE', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => 'toto', + ]); + self::assertResponseStatusCodeSame(401); + + // Check that API client was not deleted + $client->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + ]); + self::assertResponseStatusCodeSame(200); + + // Delete API client with valid token + $response = $client->request('DELETE', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + ]); + self::assertResponseStatusCodeSame(204); + $this->assertEmpty($response->getContent()); + + $client = static::createClient(); + $client->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + ]); + self::assertResponseStatusCodeSame(404); + } +} diff --git a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php index 4b79292..848792c 100644 --- a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php +++ b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php @@ -80,6 +80,11 @@ public function getProtectedEndpoints(): iterable 'PUT', '/api/customers/group/1', ]; + + yield 'delete endpoint' => [ + 'DELETE', + '/api/customers/group/1', + ]; } public function testAddCustomerGroup(): int diff --git a/tests/Integration/ApiPlatform/ProductEndpointTest.php b/tests/Integration/ApiPlatform/ProductEndpointTest.php index 4504af9..fcf45f9 100644 --- a/tests/Integration/ApiPlatform/ProductEndpointTest.php +++ b/tests/Integration/ApiPlatform/ProductEndpointTest.php @@ -97,6 +97,11 @@ public function getProtectedEndpoints(): iterable '/api/product/1', 'application/merge-patch+json', ]; + + yield 'delete endpoint' => [ + 'DELETE', + '/api/product/1', + ]; } public function testAddProduct(): int @@ -278,7 +283,7 @@ public function testDeleteProduct(int $productId): void $productsNumber = $this->getProductsNumber(); $bearerToken = $this->getBearerToken(['product_read', 'product_write']); $client = static::createClient(); - // Update customer group with partial data + // Delete product $response = $client->request('DELETE', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, ]); From 20b89ca8ef081ccf00f9c11e25ba5626e727d0b4 Mon Sep 17 00:00:00 2001 From: Jonathan Lelievre Date: Thu, 22 Feb 2024 14:17:00 +0100 Subject: [PATCH 3/5] Setup composer scripts that helps setting up a local temporary test environment to run the module tests --- .gitignore | 2 + composer.json | 8 +- composer.lock | 56 ++++- tests/EnvironmentBuilder.php | 252 +++++++++++++++++++++ tests/local-parameters/parameters.php.dist | 64 ++++++ tests/local-parameters/parameters.yml.dist | 27 +++ 6 files changed, 406 insertions(+), 3 deletions(-) create mode 100644 tests/EnvironmentBuilder.php create mode 100644 tests/local-parameters/parameters.php.dist create mode 100644 tests/local-parameters/parameters.yml.dist diff --git a/.gitignore b/.gitignore index ee73bc9..caca874 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /vendor .php-cs-fixer.cache .phpunit.result.cache +tests/local-parameters/parameters.php +tests/local-parameters/parameters.yml diff --git a/composer.json b/composer.json index c2511d0..bc11207 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,8 @@ "php": ">=8.1" }, "require-dev": { - "prestashop/php-dev-tools": "^4.2" + "prestashop/php-dev-tools": "^4.2", + "czproject/git-php": "^4.2" }, "autoload": { "psr-4": { @@ -35,5 +36,10 @@ "php": "8.1.0" } }, + "scripts": { + "clear-test-cache": "PsApiResourcesTest\\EnvironmentBuilder::clearCache", + "create-test-db": "@composer setup-local-tests -- --build-db", + "setup-local-tests": "PsApiResourcesTest\\EnvironmentBuilder::setupLocalTests" + }, "type": "prestashop-module" } diff --git a/composer.lock b/composer.lock index 7604fc1..b4cce2f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "75b8c3c14f37ae4e0252cfdaaac748a5", + "content-hash": "8db0a33415a2c4ad2364eb95e917c54a", "packages": [], "packages-dev": [ { @@ -225,6 +225,58 @@ ], "time": "2022-02-25T21:32:43+00:00" }, + { + "name": "czproject/git-php", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/czproject/git-php.git", + "reference": "e257f2c3b43fe8fef19ddb5727b604416b423107" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/czproject/git-php/zipball/e257f2c3b43fe8fef19ddb5727b604416b423107", + "reference": "e257f2c3b43fe8fef19ddb5727b604416b423107", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "require-dev": { + "nette/tester": "^2.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jan Pecha", + "email": "janpecha@email.cz" + } + ], + "description": "Library for work with Git repository in PHP.", + "keywords": [ + "git" + ], + "support": { + "issues": "https://github.com/czproject/git-php/issues", + "source": "https://github.com/czproject/git-php/tree/v4.2.0" + }, + "funding": [ + { + "url": "https://www.janpecha.cz/donate/git-php/", + "type": "other" + } + ], + "time": "2023-07-12T09:14:30+00:00" + }, { "name": "friendsofphp/php-cs-fixer", "version": "v3.34.1", @@ -2100,5 +2152,5 @@ "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } diff --git a/tests/EnvironmentBuilder.php b/tests/EnvironmentBuilder.php new file mode 100644 index 0000000..49135eb --- /dev/null +++ b/tests/EnvironmentBuilder.php @@ -0,0 +1,252 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ + +declare(strict_types=1); + +namespace PsApiResourcesTest; + +use Composer\Script\Event; +use CzProject\GitPhp\Git; +use CzProject\GitPhp\GitRepository; +use Symfony\Component\Filesystem\Filesystem; + +class EnvironmentBuilder +{ + public static function setupLocalTests(Event $event): void + { + $arguments = self::parseArguments($event); + static::log('Setup local environment: ' . var_export($arguments, true)); + $vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); + $moduleDir = realpath($vendorDir . '/..'); + $prestashopDir = sys_get_temp_dir() . '/prestashop-api-resources'; + self::setupPrestashop($prestashopDir, $moduleDir, $arguments); + } + + public static function clearCache(): void + { + $prestashopDir = sys_get_temp_dir() . '/prestashop-api-resources'; + self::clearTestCache($prestashopDir); + } + + private static function setupPrestashop(string $prestashopDir, string $moduleDir, array $arguments): void + { + $fs = new Filesystem(); + if (is_dir($prestashopDir) && $arguments['force-clone']) { + static::log('Removing prestashop folder to force clone ' . $prestashopDir); + $fs->remove($prestashopDir); + } + + // Init git repository or get reference to existing one + $git = new Git(); + if (!is_dir($prestashopDir)) { + static::log('Cloning PrestaShop folder to ' . $prestashopDir); + $repo = $git->cloneRepository('https://github.com/PrestaShop/PrestaShop.git', $prestashopDir); + $buildAssetsNeeded = true; + $buildDbNeeded = true; + } else { + static::log('Found PrestaShop folder at ' . $prestashopDir); + $repo = $git->open($prestashopDir); + $buildAssetsNeeded = false; + $buildDbNeeded = false; + } + + // Checkout to appropriate branch, if branch as changed then we must rebuild assets and DB + $branchChanged = self::checkoutBranch($repo, $arguments); + if ($branchChanged) { + $buildAssetsNeeded = true; + $buildDbNeeded = true; + } + + // Build assets (composer dependencies and UI assets) + if ($buildAssetsNeeded || $arguments['build-assets']) { + static::log('Install composer dependencies'); + passthru('cd ' . $prestashopDir . ' && composer install'); + + static::log('Build assets'); + passthru('cd ' . $prestashopDir . ' && make assets'); + static::clearTestCache($prestashopDir); + } + + // Link the current module folder into the PrestaShop test instance + $prestashopModulePath = $prestashopDir . '/modules/ps_apiresources'; + if (!is_link($prestashopModulePath)) { + static::log('Remove installed module from modules folder'); + $fs->remove($prestashopModulePath); + static::log('Linking module into modules folder ' . $prestashopModulePath); + symlink($moduleDir, $prestashopModulePath); + static::clearTestCache($prestashopDir); + $buildDbNeeded = true; + } + + // Copy parameters + $configFolder = $prestashopDir . '/app/config/'; + $localeParameters = $moduleDir . '/tests/local-parameters/'; + foreach (['parameters.php', 'parameters.yml'] as $parameterFile) { + if (!file_exists($configFolder . $parameterFile) || $arguments['update-local-parameters']) { + // Prefer using the local file if present, if not use the dist default configuration + $localFile = $localeParameters . $parameterFile; + if (!file_exists($localFile)) { + $localFile = $localeParameters . $parameterFile . '.dist'; + } + $configFile = $configFolder . $parameterFile; + + static::log('Copy parameter file ' . $localFile . ' into config folder ' . $configFile); + $fs->copy($localFile, $configFile); + static::clearTestCache($prestashopDir); + + // DB settings may have changed so we rebuild the DB + $buildDbNeeded = true; + } + } + + // Build test DB + if ($buildDbNeeded || $arguments['build-db']) { + static::log('Build test DB'); + passthru('cd ' . $prestashopDir . ' && composer run create-test-db'); + } + } + + /** + * @param GitRepository $repo + * @param array $arguments + * + * @return bool returns if the branch was changed + */ + private static function checkoutBranch(GitRepository $repo, array $arguments): bool + { + if (empty($arguments['core-branch'])) { + self::log('No specified branch no need to checkout any particular one.'); + + return false; + } + + $matches = []; + if (preg_match('/([^:]+)\:(.+)/', $arguments['core-branch'], $matches)) { + $remoteName = $matches[1]; + $coreBranch = $matches[2]; + } else { + $remoteName = null; + $coreBranch = $arguments['core-branch']; + } + if (!empty($remoteName)) { + $remoteBranch = $remoteName . '/' . $coreBranch; + } else { + $remoteBranch = 'origin/' . $coreBranch; + } + + if ($repo->getCurrentBranchName() !== $coreBranch) { + if (!empty($remoteName)) { + $remoteUrl = 'git@github.com:' . $remoteName . '/PrestaShop.git'; + $remoteList = $repo->execute('remote'); + if (!in_array($remoteName, $remoteList)) { + self::log('Add new remote ' . $remoteUrl); + $repo->addRemote($remoteName, $remoteUrl); + } + + self::log('Fetch remote ' . $remoteName); + $repo->fetch($remoteName); + } else { + self::log('Fetch origin'); + $repo->fetch('origin'); + } + + if (in_array($coreBranch, $repo->getLocalBranches())) { + self::log('Remove local branch ' . $coreBranch); + $repo->removeBranch($coreBranch); + } + + self::log('Create branch ' . $remoteBranch); + $repo->execute('checkout', '-b', $coreBranch, $remoteBranch); + + // Change of branch requires rebuild + return true; + } else { + self::log('Already on branch ' . $remoteBranch); + + return false; + } + } + + private static function clearTestCache(string $prestashopDir): void + { + $cacheFolder = $prestashopDir . '/var/cache/test'; + if (is_dir($cacheFolder)) { + static::log('Remove cache folder ' . $cacheFolder); + $fs = new Filesystem(); + $fs->remove($cacheFolder); + } + } + + private static function log(string $message): void + { + echo $message . PHP_EOL; + } + + private static function parseArguments(Event $event): array + { + $arguments = [ + 'force-clone' => false, + 'build-assets' => false, + 'build-db' => false, + 'update-local-parameters' => false, + // We keep null by default meaning no change of branch will be done unless specified + 'core-branch' => null, + ]; + + $composerArguments = $event->getArguments(); + if (in_array('--force', $composerArguments)) { + // Force all init boolean options to true + $arguments = array_merge($arguments, [ + 'force-clone' => true, + 'build-assets' => true, + 'build-db' => true, + 'update-local-parameters' => true, + ]); + } else { + foreach ($composerArguments as $argument) { + foreach ($arguments as $argumentKey => $argumentValue) { + if (is_bool($argumentValue) && '--' . $argumentKey === $argument) { + $arguments[$argumentKey] = true; + } + } + } + } + + // Handle arguments with values + foreach ($composerArguments as $argument) { + $matches = []; + if (preg_match('/\-\-(.+)\=(.+)/', $argument, $matches)) { + $argumentKey = $matches[1]; + $argumentValue = $matches[2]; + if (array_key_exists($argumentKey, $arguments)) { + $arguments[$argumentKey] = $argumentValue; + } + } + } + + return $arguments; + } +} diff --git a/tests/local-parameters/parameters.php.dist b/tests/local-parameters/parameters.php.dist new file mode 100644 index 0000000..643ad09 --- /dev/null +++ b/tests/local-parameters/parameters.php.dist @@ -0,0 +1,64 @@ + + array ( + 'database_host' => '127.0.0.1', + 'database_port' => '', + 'database_name' => 'prestashop', + 'database_user' => 'root', + 'database_password' => 'password', + 'database_prefix' => 'ps_', + 'database_engine' => 'InnoDB', + 'mailer_transport' => 'smtp', + 'mailer_host' => '127.0.0.1', + 'mailer_user' => NULL, + 'mailer_password' => NULL, + 'secret' => 'Mf6zkVBCg695Tw7hYOTHBEWQEpdNLd1jonigbi3EQh0aI1857czKDwN3MpecM4Pp', + 'ps_caching' => 'CacheMemcache', + 'ps_cache_enable' => false, + 'ps_creation_date' => '2021-07-12', + 'locale' => 'en-US', + 'use_debug_toolbar' => true, + 'cookie_key' => 'cw399s5jwV58Wbz2VvIx5DjKBiu54pAP5YvAOasWAOwDo1REWXZLW6QncnjnNOfk', + 'cookie_iv' => '8hw6IbWVusjdPSgUWOgoGMgaSGCFqm5E', + 'new_cookie_key' => 'def00000a92a6f83ac259b6d7e5353a35a2af33614b268a8b781e4a4d8fcf2b658571b1a9ce281eb9916afdcf1d39359e439741a3f749f90c3db3f7d1c546328e14c508c', + 'api_public_key' => '-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt7051COt+l79vlOO56/G +AEUL3VeF8QvQo5uqIIUTpYbnu/Vabmq2PVKeEr191V/1lY6Wf9o406qfNc2dys+9 +5jRTBWKXTsAtZE+fry2j9Pm0sdHSQTsUSJUQkKSevixFOTFW+o8N8NhGCY+/xGzB +3nv+tw8rl2iSZols4hWS5nJX56yQvu7N6B2cakkhMvUEi4tPnLGi2f72FSaVSgSi +Ma5J4ukWXiDcMbIYM0Ks1FnPEUtQEbqw9btYrrG7PRt/AmNQzLqdtkRToA6oKhTs +uAzb34jIhb5/qd3Z1fQseVLnTJuPIg2W7U8H+L7lNSOQ8s7gaxxongEYDXZFN+BA +4wIDAQAB +-----END PUBLIC KEY----- +', + 'api_private_key' => '-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3vTnUI636Xv2+ +U47nr8YARQvdV4XxC9Cjm6oghROlhue79VpuarY9Up4SvX3VX/WVjpZ/2jjTqp81 +zZ3Kz73mNFMFYpdOwC1kT5+vLaP0+bSx0dJBOxRIlRCQpJ6+LEU5MVb6jw3w2EYJ +j7/EbMHee/63DyuXaJJmiWziFZLmclfnrJC+7s3oHZxqSSEy9QSLi0+csaLZ/vYV +JpVKBKIxrkni6RZeINwxshgzQqzUWc8RS1ARurD1u1iusbs9G38CY1DMup22RFOg +DqgqFOy4DNvfiMiFvn+p3dnV9Cx5UudMm48iDZbtTwf4vuU1I5DyzuBrHGieARgN +dkU34EDjAgMBAAECggEAf+2SG/ATrCUDSsbm0s2BcKKiViQgL+poA+HYG/hL6434 +PtffdM17wUqKoMWqnSvI066Jfs8zjbxYSZ+144Ws1GFOBIvWiZAoipUdu1xtsZ1C +gCR03dICl16iP/M+S26La/y8cIu1yyDp8rJRdLO8b+mpOU+orCy08gtw8iDPPP7l +zHhNene33xO9K/BS0eVbwBXwlGayLmH3naTewqVkfp3FzWFEB3aNeyDryp7fN8ca +m2/iW8KKlKzl+bZ+CRZN8wGjZL0sjcP1W+kzxvQxCeQXTSB7LhM2XvF61tNqIBDm +hEfWvoG4wTrM0SEuf86smgNByw6hiGcr3ARcokpg4QKBgQDanAkHDYe9izm0VtV3 +DJs8uPIf4AHraEVbbii5tOy+prxcb2MkWmys/ghQbzMmhxycr9HW9lLRovLGhxeh +5CGb6fkLXUu3Dxl7IerUk4Uk8x8SFw4Y2S5WWjIDIQTIkn0QIy2PuqbxWNo/ZJIs +OiV7taDT/CoBv0UHC8PtMZv5qQKBgQDXKl5w75HYtCq9yXoFw/d6ZEz+iE0Sfntr +R98Cgnoyt0PnTpzFhTWzEbIoMvNzjF1l5FPRTbyZDXcJqa5GdQPERqhrnf7x5u6B +dz9Ox3kJOvPz8ZIUY0oyqDyqU8YU4JdCaeyYTmjtwduK1O3maE8gsQMHj9UUMLKj +u59Jl0y1qwKBgBQheEdY/J38uySbNm8PDyCJW2qKA0M9R93CiCeJvJ9V1VShwTxw +wz8u6W8WvlwW5xCatDUaW8gIPFkBybBTxLCJ3DAquDU0Q8Ft/yTyLLmZVcwhqV+q +aDT1e1OEb99UdgXNZ32rz4G8D+T0iu1dsWPx9sxulSOyDFY4xCMMhXN5AoGBAIaQ +pe3ltoYb75swVVMjwzPVZN3PKryFQ/TNRyjPp1LukNYpsRxK+lGaoJxJeT5rq8Hc +sZr2Dhx+clMlvqur5QYs1oovjtGFBucLSBmh4Q2nxAhtrVl421+hHge8Sualq5PK +oUCD0VXY5tAF6R8vX0Vnzyg8iRuOdTq3TaB9smjvAoGAbgypIUPilY/5aUVT3GuK +58qob/qzixaQeuk9/kjN0dvRUqkAUQ5WCYL1drOzj2zFay0hjUGoIZ5UwDixjvbI +bj0qsVWs5bShy+QCbc5QD0cnECEm1YsTosyrUsjfBz47zzSbxnu8YoKQfXDJ24Jz +y8JR3k1WPeuuoUpTLKM1C/8= +-----END PRIVATE KEY----- +', + ), +); diff --git a/tests/local-parameters/parameters.yml.dist b/tests/local-parameters/parameters.yml.dist new file mode 100644 index 0000000..fc50899 --- /dev/null +++ b/tests/local-parameters/parameters.yml.dist @@ -0,0 +1,27 @@ +# This file is used by GitHub Actions. +parameters: + database_host: localhost + database_port: ~ + database_name: prestashop + database_user: root + database_password: password + database_prefix: ps_ + database_engine: InnoDB + # You should uncomment this if you want use pdo_sqlite + # database_path: "%kernel.project_dir%/data.db3" + + mailer_transport: smtp + mailer_host: localhost + mailer_user: ~ + mailer_password: ~ + + # A secret key that's used to generate certain security-related tokens + secret: ThisTokenIsNotSoSecretChangeIt + ps_caching: CacheMemcache + ps_cache_enable: true + ps_creation_date: ~ + locale: en-US + cookie_key: ThisTokenIsNotSoSecretChangeIt + cookie_iv: ThisTokenIsNotSoSecretChangeIt + + use_debug_toolbar: false From acbeeea65e908be377c81f87d1f084d64105b19b Mon Sep 17 00:00:00 2001 From: Jonathan Lelievre Date: Thu, 22 Feb 2024 16:29:20 +0100 Subject: [PATCH 4/5] Handle composer script to run tests locally --- .github/workflows/integration.yml | 2 +- composer.json | 9 +- composer.lock | 1973 +++++++++++++++-- tests/Integration/bootstrap-local.php | 27 + tests/Integration/bootstrap.php | 8 +- .../{phpunit.xml => phpunit-ci.xml} | 6 - tests/Integration/phpunit-local.xml | 14 + 7 files changed, 1845 insertions(+), 194 deletions(-) create mode 100644 tests/Integration/bootstrap-local.php rename tests/Integration/{phpunit.xml => phpunit-ci.xml} (80%) create mode 100644 tests/Integration/phpunit-local.xml diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index bd59b32..db7763b 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -51,4 +51,4 @@ jobs: USER_ID=$(id -u) GROUP_ID=$(id -g) docker exec prestashop_prestashop-git_1 composer create-test-db - name: Run integration tests run : | - USER_ID=$(id -u) GROUP_ID=$(id -g) docker exec prestashop_prestashop-git_1 vendor/bin/phpunit -c modules/ps_apiresources/tests/Integration/phpunit.xml + USER_ID=$(id -u) GROUP_ID=$(id -g) docker exec prestashop_prestashop-git_1 vendor/bin/phpunit -c modules/ps_apiresources/tests/Integration/phpunit-ci.xml diff --git a/composer.json b/composer.json index bc11207..d9be3e4 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ }, "require-dev": { "prestashop/php-dev-tools": "^4.2", - "czproject/git-php": "^4.2" + "czproject/git-php": "^4.2", + "phpunit/phpunit": "^9.6" }, "autoload": { "psr-4": { @@ -38,7 +39,11 @@ }, "scripts": { "clear-test-cache": "PsApiResourcesTest\\EnvironmentBuilder::clearCache", - "create-test-db": "@composer setup-local-tests -- --build-db", + "create-test-db": [ + "@composer clear-test-cache", + "@composer setup-local-tests -- --build-db" + ], + "run-module-tests": "@php -d date.timezone=UTC ./vendor/bin/phpunit -c tests/Integration/phpunit-local.xml", "setup-local-tests": "PsApiResourcesTest\\EnvironmentBuilder::setupLocalTests" }, "type": "prestashop-module" diff --git a/composer.lock b/composer.lock index b4cce2f..7fb155b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8db0a33415a2c4ad2364eb95e917c54a", + "content-hash": "a9b12f34524f22f42552315515db2a84", "packages": [], "packages-dev": [ { @@ -277,6 +277,76 @@ ], "time": "2023-07-12T09:14:30+00:00" }, + { + "name": "doctrine/instantiator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:23:10+00:00" + }, { "name": "friendsofphp/php-cs-fixer", "version": "v3.34.1", @@ -372,18 +442,77 @@ ], "time": "2023-10-03T23:51:05+00:00" }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, { "name": "nikic/php-parser", - "version": "v4.17.1", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", - "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", "shasum": "" }, "require": { @@ -424,332 +553,1772 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" }, - "time": "2023-08-13T19:53:39+00:00" + "time": "2023-12-10T21:03:43+00:00" }, { - "name": "prestashop/autoindex", - "version": "v2.1.0", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/PrestaShopCorp/autoindex.git", - "reference": "235f3ec115432ffc32d582198ea498467b3946d0" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/autoindex/zipball/235f3ec115432ffc32d582198ea498467b3946d0", - "reference": "235f3ec115432ffc32d582198ea498467b3946d0", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "nikic/php-parser": "^4.10", - "php": "^8.0 || ^7.2", - "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", - "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, - "require-dev": { - "phpstan/phpstan": "^0.12.83", - "prestashop/php-dev-tools": "1.*" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } }, - "bin": [ - "bin/autoindex" + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, "type": "library", "autoload": { - "psr-4": { - "PrestaShop\\AutoIndex\\": "src/" + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.30", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "AFL-3.0" + "BSD-3-Clause" ], "authors": [ { - "name": "PrestaShop SA", - "email": "contact@prestashop.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Automatically add an 'index.php' in all the current or specified directories and all sub-directories.", - "homepage": "https://github.com/PrestaShopCorp/autoindex", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], "support": { - "source": "https://github.com/PrestaShopCorp/autoindex/tree/v2.1.0" + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30" }, - "time": "2022-10-10T08:35:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:47:57+00:00" }, { - "name": "prestashop/header-stamp", - "version": "v2.3", + "name": "phpunit/php-file-iterator", + "version": "3.0.6", "source": { "type": "git", - "url": "https://github.com/PrestaShopCorp/header-stamp.git", - "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShopCorp/header-stamp/zipball/3104b69ad73b6039c7082dbba4af9dbeb0b936b3", - "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "nikic/php-parser": "^4.10", - "php": "^8.0 || ^7.2", - "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", - "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.16", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3767b2c56ce02d01e3491046f33466a1ae60a37f", + "reference": "3767b2c56ce02d01e3491046f33466a1ae60a37f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.16" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-01-19T07:03:14+00:00" + }, + { + "name": "prestashop/autoindex", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/PrestaShopCorp/autoindex.git", + "reference": "235f3ec115432ffc32d582198ea498467b3946d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PrestaShopCorp/autoindex/zipball/235f3ec115432ffc32d582198ea498467b3946d0", + "reference": "235f3ec115432ffc32d582198ea498467b3946d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": "^8.0 || ^7.2", + "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", + "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.83", + "prestashop/php-dev-tools": "1.*" + }, + "bin": [ + "bin/autoindex" + ], + "type": "library", + "autoload": { + "psr-4": { + "PrestaShop\\AutoIndex\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AFL-3.0" + ], + "authors": [ + { + "name": "PrestaShop SA", + "email": "contact@prestashop.com" + } + ], + "description": "Automatically add an 'index.php' in all the current or specified directories and all sub-directories.", + "homepage": "https://github.com/PrestaShopCorp/autoindex", + "support": { + "source": "https://github.com/PrestaShopCorp/autoindex/tree/v2.1.0" + }, + "time": "2022-10-10T08:35:00+00:00" + }, + { + "name": "prestashop/header-stamp", + "version": "v2.3", + "source": { + "type": "git", + "url": "https://github.com/PrestaShopCorp/header-stamp.git", + "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PrestaShopCorp/header-stamp/zipball/3104b69ad73b6039c7082dbba4af9dbeb0b936b3", + "reference": "3104b69ad73b6039c7082dbba4af9dbeb0b936b3", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": "^8.0 || ^7.2", + "symfony/console": "^3.4 || ~4.0 || ~5.0 || ~6.0", + "symfony/finder": "^3.4 || ~4.0 || ~5.0 || ~6.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.83", + "prestashop/php-dev-tools": "1.*" + }, + "bin": [ + "bin/header-stamp" + ], + "type": "library", + "autoload": { + "psr-4": { + "PrestaShop\\HeaderStamp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AFL-3.0" + ], + "authors": [ + { + "name": "PrestaShop SA", + "email": "contact@prestashop.com" + } + ], + "description": "Rewrite your file headers to add the license or to make them up-to-date", + "homepage": "https://github.com/PrestaShopCorp/header-stamp", + "support": { + "issues": "https://github.com/PrestaShopCorp/header-stamp/issues", + "source": "https://github.com/PrestaShopCorp/header-stamp/tree/v2.3" + }, + "time": "2023-03-23T14:44:10+00:00" + }, + { + "name": "prestashop/php-dev-tools", + "version": "v4.3.0", + "source": { + "type": "git", + "url": "https://github.com/PrestaShop/php-dev-tools.git", + "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/843275b19729ba810d8ba2b9c97b568e5bbabe03", + "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03", + "shasum": "" + }, + "require": { + "friendsofphp/php-cs-fixer": "^3.2", + "php": ">=7.2.5", + "prestashop/autoindex": "^2.0", + "prestashop/header-stamp": "^2.0", + "squizlabs/php_codesniffer": "^3.4", + "symfony/console": "~3.2 || ~4.0 || ~5.0 || ~6.0", + "symfony/filesystem": "~3.2 || ~4.0 || ~5.0 || ~6.0" + }, + "bin": [ + "bin/prestashop-coding-standards" + ], + "type": "library", + "autoload": { + "psr-4": { + "PrestaShop\\CodingStandards\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PrestaShop coding standards", + "support": { + "issues": "https://github.com/PrestaShop/php-dev-tools/issues", + "source": "https://github.com/PrestaShop/php-dev-tools/tree/v4.3.0" + }, + "time": "2022-10-18T14:19:51+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T05:35:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bde739e7565280bda77be70044ac1047bc007e34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-02T09:26:13+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.83", - "prestashop/php-dev-tools": "1.*" + "phpunit/phpunit": "^9.3" }, - "bin": [ - "bin/header-stamp" - ], "type": "library", - "autoload": { - "psr-4": { - "PrestaShop\\HeaderStamp\\": "src/" + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "AFL-3.0" + "BSD-3-Clause" ], "authors": [ { - "name": "PrestaShop SA", - "email": "contact@prestashop.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Rewrite your file headers to add the license or to make them up-to-date", - "homepage": "https://github.com/PrestaShopCorp/header-stamp", + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/PrestaShopCorp/header-stamp/issues", - "source": "https://github.com/PrestaShopCorp/header-stamp/tree/v2.3" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" }, - "time": "2023-03-23T14:44:10+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" }, { - "name": "prestashop/php-dev-tools", - "version": "v4.3.0", + "name": "sebastian/object-reflector", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/PrestaShop/php-dev-tools.git", - "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PrestaShop/php-dev-tools/zipball/843275b19729ba810d8ba2b9c97b568e5bbabe03", - "reference": "843275b19729ba810d8ba2b9c97b568e5bbabe03", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^3.2", - "php": ">=7.2.5", - "prestashop/autoindex": "^2.0", - "prestashop/header-stamp": "^2.0", - "squizlabs/php_codesniffer": "^3.4", - "symfony/console": "~3.2 || ~4.0 || ~5.0 || ~6.0", - "symfony/filesystem": "~3.2 || ~4.0 || ~5.0 || ~6.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, - "bin": [ - "bin/prestashop-coding-standards" - ], "type": "library", - "autoload": { - "psr-4": { - "PrestaShop\\CodingStandards\\": "src/" + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "PrestaShop coding standards", + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/PrestaShop/php-dev-tools/issues", - "source": "https://github.com/PrestaShop/php-dev-tools/tree/v4.3.0" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" }, - "time": "2022-10-18T14:19:51+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" }, { - "name": "psr/container", - "version": "2.0.2", + "name": "sebastian/recursion-context", + "version": "4.0.5", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { - "php": ">=7.4.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, - "time": "2021-11-05T16:47:00+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "sebastian/resource-operations", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\EventDispatcher\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "Standard interfaces for event handling.", - "keywords": [ - "events", - "psr", - "psr-14" - ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" }, - "time": "2019-01-08T18:20:26+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" }, { - "name": "psr/log", - "version": "3.0.0", + "name": "sebastian/type", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", - "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "psr-4": { - "Psr\\Log\\": "src" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, - "time": "2021-07-14T16:46:02+00:00" + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" }, { - "name": "sebastian/diff", - "version": "5.0.3", + "name": "sebastian/version", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", - "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": ">=8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0", - "symfony/process": "^4.2 || ^5" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -764,25 +2333,15 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" }, "funding": [ { @@ -790,7 +2349,7 @@ "type": "github" } ], - "time": "2023-05-01T07:48:21+00:00" + "time": "2020-09-28T06:39:44+00:00" }, { "name": "squizlabs/php_codesniffer", @@ -2138,6 +3697,56 @@ } ], "time": "2023-09-18T10:38:32+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2023-11-20T00:12:19+00:00" } ], "aliases": [], diff --git a/tests/Integration/bootstrap-local.php b/tests/Integration/bootstrap-local.php new file mode 100644 index 0000000..6b532a3 --- /dev/null +++ b/tests/Integration/bootstrap-local.php @@ -0,0 +1,27 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + */ +define('_PS_ROOT_DIR_', sys_get_temp_dir() . '/prestashop-api-resources'); +include_once 'bootstrap.php'; diff --git a/tests/Integration/bootstrap.php b/tests/Integration/bootstrap.php index 61c5218..db9f86b 100644 --- a/tests/Integration/bootstrap.php +++ b/tests/Integration/bootstrap.php @@ -23,12 +23,14 @@ * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ +if (!defined('_PS_ROOT_DIR_')) { + define('_PS_ROOT_DIR_', dirname(__DIR__, 4)); +} define('_PS_IN_TEST_', true); define('_PS_API_FORCE_TLS_VERSION_', false); -define('_PS_ROOT_DIR_', dirname(__DIR__, 4)); define('_PS_MODULE_DIR_', _PS_ROOT_DIR_ . '/tests/Resources/modules/'); -require_once dirname(__DIR__, 4) . '/vendor/smarty/smarty/libs/functions.php'; -require_once dirname(__DIR__, 4) . '/admin-dev/bootstrap.php'; +require_once _PS_ROOT_DIR_ . '/vendor/smarty/smarty/libs/functions.php'; +require_once _PS_ROOT_DIR_ . '/admin-dev/bootstrap.php'; /* * Following code makes tests run under phpstorm diff --git a/tests/Integration/phpunit.xml b/tests/Integration/phpunit-ci.xml similarity index 80% rename from tests/Integration/phpunit.xml rename to tests/Integration/phpunit-ci.xml index 5611864..def2d24 100644 --- a/tests/Integration/phpunit.xml +++ b/tests/Integration/phpunit-ci.xml @@ -11,10 +11,4 @@ . - - - - isolatedProcess - - diff --git a/tests/Integration/phpunit-local.xml b/tests/Integration/phpunit-local.xml new file mode 100644 index 0000000..a74ec29 --- /dev/null +++ b/tests/Integration/phpunit-local.xml @@ -0,0 +1,14 @@ + + + + + + + + . + + + From 44a9649ab44713ccc8b31be58b93d5ec26d5d6ef Mon Sep 17 00:00:00 2001 From: Jonathan Lelievre Date: Fri, 23 Feb 2024 00:12:25 +0100 Subject: [PATCH 5/5] Force checking protected endpoints in all tests, protected endpoints are also checked with no scopes, deletion tests have been improved with a failing delete to make sure the entity is really not deleted, and client is always created on the fly to prevent Response caching issues --- .../ApiPlatform/ApiClientEndpointTest.php | 98 ++++++++++--------- tests/Integration/ApiPlatform/ApiTestCase.php | 53 ++++++++-- .../ApiPlatform/CustomerGroupApiTest.php | 32 +----- .../ApiPlatform/GetHookStatusTest.php | 13 +++ tests/Integration/ApiPlatform/GetHookTest.php | 8 ++ .../ApiPlatform/ProductEndpointTest.php | 55 +++++------ .../ProductMultiShopEndpointTest.php | 20 ++-- 7 files changed, 161 insertions(+), 118 deletions(-) diff --git a/tests/Integration/ApiPlatform/ApiClientEndpointTest.php b/tests/Integration/ApiPlatform/ApiClientEndpointTest.php index 6064581..bb75b4d 100644 --- a/tests/Integration/ApiPlatform/ApiClientEndpointTest.php +++ b/tests/Integration/ApiPlatform/ApiClientEndpointTest.php @@ -36,25 +36,6 @@ public static function setUpBeforeClass(): void self::createApiClient(['api_client_write', 'api_client_read']); } - /** - * @dataProvider getProtectedEndpoints - * - * @param string $method - * @param string $uri - */ - public function testProtectedEndpoints(string $method, string $uri, string $contentType = 'application/json'): void - { - $options['headers']['content-type'] = $contentType; - // Check that endpoints are not accessible without a proper Bearer token - $client = static::createClient([], $options); - $response = $client->request($method, $uri); - self::assertResponseStatusCodeSame(401); - - $content = $response->getContent(false); - $this->assertNotEmpty($content); - $this->assertEquals('No Authorization header provided', $content); - } - public function getProtectedEndpoints(): iterable { yield 'get endpoint' => [ @@ -68,22 +49,20 @@ public function getProtectedEndpoints(): iterable ]; yield 'update endpoint' => [ - 'PUT', + 'PATCH', '/api/api-client/1', ]; yield 'delete endpoint' => [ 'DELETE', '/api/api-client/1', - 'application/merge-patch+json', ]; } public function testAddApiClient(): int { $bearerToken = $this->getBearerToken(['api_client_write']); - $client = static::createClient(); - $response = $client->request('POST', '/api/api-client', [ + $response = static::createClient()->request('POST', '/api/api-client', [ 'auth_bearer' => $bearerToken, 'json' => [ 'clientId' => 'client_id_test', @@ -125,8 +104,7 @@ public function testAddApiClient(): int public function testGetApiClient(int $apiClientId): int { $bearerToken = $this->getBearerToken(['api_client_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/api-client/' . $apiClientId, [ + $response = static::createClient()->request('GET', '/api/api-client/' . $apiClientId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(200); @@ -162,10 +140,9 @@ public function testGetApiClient(int $apiClientId): int public function testUpdateApiClient(int $apiClientId): int { $bearerToken = $this->getBearerToken(['api_client_write']); - $client = static::createClient(); - // Update product with partial data, even multilang fields can be updated language by language - $response = $client->request('PUT', '/api/api-client/' . $apiClientId, [ + // Update API client + $response = static::createClient()->request('PATCH', '/api/api-client/' . $apiClientId, [ 'auth_bearer' => $bearerToken, 'json' => [ 'clientId' => 'client_id_test_updated', @@ -200,6 +177,35 @@ public function testUpdateApiClient(int $apiClientId): int $decodedResponse ); + // Update partially API client + $response = static::createClient()->request('PATCH', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $bearerToken, + 'json' => [ + 'description' => 'Client description test partially updated', + 'lifetime' => 900, + ], + ]); + self::assertResponseStatusCodeSame(200); + + $decodedResponse = json_decode($response->getContent(), true); + $this->assertNotFalse($decodedResponse); + // Returned data has modified fields, the others haven't changed + $this->assertEquals( + [ + 'apiClientId' => $apiClientId, + 'clientId' => 'client_id_test_updated', + 'clientName' => 'Client name test updated', + 'description' => 'Client description test partially updated', + 'enabled' => false, + 'lifetime' => 900, + 'scopes' => [ + 'api_client_write', + 'hook_read', + ], + ], + $decodedResponse + ); + return $apiClientId; } @@ -213,8 +219,7 @@ public function testUpdateApiClient(int $apiClientId): int public function testGetUpdatedApiClient(int $apiClientId): int { $bearerToken = $this->getBearerToken(['api_client_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/api-client/' . $apiClientId, [ + $response = static::createClient()->request('GET', '/api/api-client/' . $apiClientId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(200); @@ -226,9 +231,9 @@ public function testGetUpdatedApiClient(int $apiClientId): int 'apiClientId' => $apiClientId, 'clientId' => 'client_id_test_updated', 'clientName' => 'Client name test updated', - 'description' => 'Client description test updated', + 'description' => 'Client description test partially updated', 'enabled' => false, - 'lifetime' => 1800, + 'lifetime' => 900, 'scopes' => [ 'api_client_write', 'hook_read', @@ -247,34 +252,39 @@ public function testGetUpdatedApiClient(int $apiClientId): int */ public function testDeleteApiClient(int $apiClientId): void { - $bearerToken = $this->getBearerToken(['api_client_read', 'api_client_write']); - $client = static::createClient(); - // Delete API client without token - $client->request('DELETE', '/api/api-client/' . $apiClientId); + static::createClient()->request('DELETE', '/api/api-client/' . $apiClientId); self::assertResponseStatusCodeSame(401); // Delete API client without token - $client->request('DELETE', '/api/api-client/' . $apiClientId, [ + static::createClient()->request('DELETE', '/api/api-client/' . $apiClientId, [ 'auth_bearer' => 'toto', ]); self::assertResponseStatusCodeSame(401); + // Try to delete with a token with only read scope + $readBearerToken = $this->getBearerToken(['api_client_read']); + $response = static::createClient()->request('DELETE', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $readBearerToken, + ]); + $this->assertEquals(403, $response->getStatusCode()); + self::assertResponseStatusCodeSame(403); + // Check that API client was not deleted - $client->request('GET', '/api/api-client/' . $apiClientId, [ - 'auth_bearer' => $bearerToken, + static::createClient()->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $readBearerToken, ]); self::assertResponseStatusCodeSame(200); // Delete API client with valid token - $response = $client->request('DELETE', '/api/api-client/' . $apiClientId, [ - 'auth_bearer' => $bearerToken, + $writeBearerToken = $this->getBearerToken(['api_client_write']); + $response = static::createClient()->request('DELETE', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $writeBearerToken, ]); self::assertResponseStatusCodeSame(204); $this->assertEmpty($response->getContent()); - $client = static::createClient(); - $client->request('GET', '/api/api-client/' . $apiClientId, [ - 'auth_bearer' => $bearerToken, + static::createClient()->request('GET', '/api/api-client/' . $apiClientId, [ + 'auth_bearer' => $readBearerToken, ]); self::assertResponseStatusCodeSame(404); } diff --git a/tests/Integration/ApiPlatform/ApiTestCase.php b/tests/Integration/ApiPlatform/ApiTestCase.php index 4728be4..f3e03b4 100644 --- a/tests/Integration/ApiPlatform/ApiTestCase.php +++ b/tests/Integration/ApiPlatform/ApiTestCase.php @@ -56,6 +56,50 @@ public static function tearDownAfterClass(): void self::$clientSecret = null; } + /** + * @dataProvider getProtectedEndpoints + * + * @param string $method + * @param string $uri + */ + public function testProtectedEndpoints(string $method, string $uri, string $contentType = 'application/json'): void + { + $options['headers']['content-type'] = $contentType; + // Check that endpoints are not accessible without a proper Bearer token + $response = static::createClient([], $options)->request($method, $uri); + self::assertResponseStatusCodeSame(401); + + $content = $response->getContent(false); + $this->assertNotEmpty($content); + $this->assertEquals('No Authorization header provided', $content); + + // Test same endpoint with a token but without scopes + $emptyBearerToken = $this->getBearerToken(); + static::createClient([], $options)->request($method, $uri, ['auth_bearer' => $emptyBearerToken]); + self::assertResponseStatusCodeSame(403); + } + + /** + * You must provide a list of protected endpoints that will we automatically checked, + * the test will check that the endpoints are not accessible when no token is specified + * AND that they are not accessible when the no particular scope is specified. + * + * You should use yield return like this: + * + * yield 'get endpoint' => [ + * 'GET', + * '/api/product/1', + * ]; + * + * Since all Api Platform resources should likely have some protected endpoints this provider + * method was made abstract to force its implementation. In the unlikely event you need to use + * this class on a resouce with absolutely no protected endpoints you can still implement this + * method and return new \EmptyIterator(); + * + * @return iterable + */ + abstract public function getProtectedEndpoints(): iterable; + protected static function createClient(array $kernelOptions = [], array $defaultOptions = []): Client { if (!isset($defaultOptions['headers']['accept'])) { @@ -74,7 +118,6 @@ protected function getBearerToken(array $scopes = []): string if (null === self::$clientSecret) { self::createApiClient($scopes); } - $client = static::createClient(); $parameters = ['parameters' => [ 'client_id' => static::CLIENT_ID, 'client_secret' => static::$clientSecret, @@ -87,14 +130,13 @@ protected function getBearerToken(array $scopes = []): string 'content-type' => 'application/x-www-form-urlencoded', ], ]; - $response = $client->request('POST', '/api/oauth2/token', $options); + $response = static::createClient()->request('POST', '/api/oauth2/token', $options); return json_decode($response->getContent())->access_token; } protected static function createApiClient(array $scopes = [], int $lifetime = 10000): void { - $client = static::createClient(); $command = new AddApiClientCommand( static::CLIENT_NAME, static::CLIENT_ID, @@ -104,7 +146,7 @@ protected static function createApiClient(array $scopes = [], int $lifetime = 10 $scopes ); - $container = $client->getContainer(); + $container = static::createClient()->getContainer(); $commandBus = $container->get('prestashop.core.command_bus'); $createdApiClient = $commandBus->handle($command); @@ -113,7 +155,6 @@ protected static function createApiClient(array $scopes = [], int $lifetime = 10 protected static function addLanguageByLocale(string $locale): int { - $client = static::createClient(); $isoCode = substr($locale, 0, strpos($locale, '-')); // Copy resource assets into tmp folder to mimic an upload file path @@ -140,7 +181,7 @@ protected static function addLanguageByLocale(string $locale): int [1] ); - $container = $client->getContainer(); + $container = static::createClient()->getContainer(); $commandBus = $container->get('prestashop.core.command_bus'); return $commandBus->handle($command)->getValue(); diff --git a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php index 848792c..723a5f9 100644 --- a/tests/Integration/ApiPlatform/CustomerGroupApiTest.php +++ b/tests/Integration/ApiPlatform/CustomerGroupApiTest.php @@ -47,23 +47,6 @@ public static function tearDownAfterClass(): void DatabaseDump::restoreTables(['group', 'group_lang', 'group_reduction', 'group_shop', 'category_group']); } - /** - * @dataProvider getProtectedEndpoints - * - * @param string $method - * @param string $uri - */ - public function testProtectedEndpoints(string $method, string $uri): void - { - $client = static::createClient(); - $response = $client->request($method, $uri); - self::assertResponseStatusCodeSame(401); - - $content = $response->getContent(false); - $this->assertNotEmpty($content); - $this->assertEquals('No Authorization header provided', $content); - } - public function getProtectedEndpoints(): iterable { yield 'get endpoint' => [ @@ -92,8 +75,7 @@ public function testAddCustomerGroup(): int $numberOfGroups = count(\Group::getGroups(\Context::getContext()->language->id)); $bearerToken = $this->getBearerToken(['customer_group_write']); - $client = static::createClient(); - $response = $client->request('POST', '/api/customers/group', [ + $response = static::createClient()->request('POST', '/api/customers/group', [ 'auth_bearer' => $bearerToken, 'json' => [ 'localizedNames' => [ @@ -141,9 +123,8 @@ public function testUpdateCustomerGroup(int $customerGroupId): int $numberOfGroups = count(\Group::getGroups(\Context::getContext()->language->id)); $bearerToken = $this->getBearerToken(['customer_group_write']); - $client = static::createClient(); // Update customer group with partial data - $response = $client->request('PUT', '/api/customers/group/' . $customerGroupId, [ + $response = static::createClient()->request('PUT', '/api/customers/group/' . $customerGroupId, [ 'auth_bearer' => $bearerToken, 'json' => [ 'localizedNames' => [ @@ -187,8 +168,7 @@ public function testUpdateCustomerGroup(int $customerGroupId): int public function testGetCustomerGroup(int $customerGroupId): int { $bearerToken = $this->getBearerToken(['customer_group_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/customers/group/' . $customerGroupId, [ + $response = static::createClient()->request('GET', '/api/customers/group/' . $customerGroupId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(200); @@ -223,16 +203,14 @@ public function testGetCustomerGroup(int $customerGroupId): int public function testDeleteCustomerGroup(int $customerGroupId): void { $bearerToken = $this->getBearerToken(['customer_group_read', 'customer_group_write']); - $client = static::createClient(); // Update customer group with partial data - $response = $client->request('DELETE', '/api/customers/group/' . $customerGroupId, [ + $response = static::createClient()->request('DELETE', '/api/customers/group/' . $customerGroupId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(204); $this->assertEmpty($response->getContent()); - $client = static::createClient(); - $client->request('GET', '/api/customers/group/' . $customerGroupId, [ + static::createClient()->request('GET', '/api/customers/group/' . $customerGroupId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(404); diff --git a/tests/Integration/ApiPlatform/GetHookStatusTest.php b/tests/Integration/ApiPlatform/GetHookStatusTest.php index 3f53338..c04b845 100644 --- a/tests/Integration/ApiPlatform/GetHookStatusTest.php +++ b/tests/Integration/ApiPlatform/GetHookStatusTest.php @@ -44,6 +44,19 @@ public static function tearDownAfterClass(): void DatabaseDump::restoreTables(['hook']); } + public function getProtectedEndpoints(): iterable + { + yield 'get endpoint' => [ + 'GET', + '/api/hook-status/1', + ]; + + yield 'put endpoint' => [ + 'PUT', + '/api/hook-status', + ]; + } + public function testGetHookStatus(): void { $inactiveHook = new \Hook(); diff --git a/tests/Integration/ApiPlatform/GetHookTest.php b/tests/Integration/ApiPlatform/GetHookTest.php index e6c109f..9b23c6b 100644 --- a/tests/Integration/ApiPlatform/GetHookTest.php +++ b/tests/Integration/ApiPlatform/GetHookTest.php @@ -45,6 +45,14 @@ public static function tearDownAfterClass(): void DatabaseDump::restoreTables(['hook']); } + public function getProtectedEndpoints(): iterable + { + yield 'get endpoint' => [ + 'GET', + '/api/hooks/1', + ]; + } + public function testGetHook(): void { $hook = new \Hook(); diff --git a/tests/Integration/ApiPlatform/ProductEndpointTest.php b/tests/Integration/ApiPlatform/ProductEndpointTest.php index fcf45f9..effa9de 100644 --- a/tests/Integration/ApiPlatform/ProductEndpointTest.php +++ b/tests/Integration/ApiPlatform/ProductEndpointTest.php @@ -61,25 +61,6 @@ public static function tearDownAfterClass(): void (new ResourceResetter())->resetTestModules(); } - /** - * @dataProvider getProtectedEndpoints - * - * @param string $method - * @param string $uri - */ - public function testProtectedEndpoints(string $method, string $uri, string $contentType = 'application/json'): void - { - $options['headers']['content-type'] = $contentType; - // Check that endpoints are not accessible without a proper Bearer token - $client = static::createClient([], $options); - $response = $client->request($method, $uri); - self::assertResponseStatusCodeSame(401); - - $content = $response->getContent(false); - $this->assertNotEmpty($content); - $this->assertEquals('No Authorization header provided', $content); - } - public function getProtectedEndpoints(): iterable { yield 'get endpoint' => [ @@ -108,8 +89,7 @@ public function testAddProduct(): int { $productsNumber = $this->getProductsNumber(); $bearerToken = $this->getBearerToken(['product_write']); - $client = static::createClient(); - $response = $client->request('POST', '/api/product', [ + $response = static::createClient()->request('POST', '/api/product', [ 'auth_bearer' => $bearerToken, 'json' => [ 'type' => ProductType::TYPE_STANDARD, @@ -158,10 +138,9 @@ public function testPartialUpdateProduct(int $productId): int { $productsNumber = $this->getProductsNumber(); $bearerToken = $this->getBearerToken(['product_write']); - $client = static::createClient(); // Update product with partial data, even multilang fields can be updated language by language - $response = $client->request('PATCH', '/api/product/' . $productId, [ + $response = static::createClient()->request('PATCH', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, 'headers' => [ 'content-type' => 'application/merge-patch+json', @@ -201,7 +180,7 @@ public function testPartialUpdateProduct(int $productId): int ); // Update product with partial data, only name default language the other names are not impacted - $response = $client->request('PATCH', '/api/product/' . $productId, [ + $response = static::createClient()->request('PATCH', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, 'headers' => [ 'content-type' => 'application/merge-patch+json', @@ -244,8 +223,7 @@ public function testPartialUpdateProduct(int $productId): int public function testGetProduct(int $productId): int { $bearerToken = $this->getBearerToken(['product_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/product/' . $productId, [ + $response = static::createClient()->request('GET', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(200); @@ -281,11 +259,22 @@ public function testGetProduct(int $productId): int public function testDeleteProduct(int $productId): void { $productsNumber = $this->getProductsNumber(); - $bearerToken = $this->getBearerToken(['product_read', 'product_write']); - $client = static::createClient(); - // Delete product - $response = $client->request('DELETE', '/api/product/' . $productId, [ - 'auth_bearer' => $bearerToken, + $readBearerToken = $this->getBearerToken(['product_read']); + // Delete product with token without write permission + static::createClient()->request('DELETE', '/api/product/' . $productId, [ + 'auth_bearer' => $readBearerToken, + ]); + self::assertResponseStatusCodeSame(403); + // The product should still exists + static::createClient()->request('GET', '/api/product/' . $productId, [ + 'auth_bearer' => $readBearerToken, + ]); + self::assertResponseStatusCodeSame(200); + + // Delete product with proper token + $writeBearerToken = $this->getBearerToken(['product_write']); + $response = static::createClient()->request('DELETE', '/api/product/' . $productId, [ + 'auth_bearer' => $writeBearerToken, ]); self::assertResponseStatusCodeSame(204); $this->assertEmpty($response->getContent()); @@ -293,8 +282,8 @@ public function testDeleteProduct(int $productId): void // One less products $this->assertEquals($productsNumber - 1, $this->getProductsNumber()); - $client = static::createClient(); - $client->request('GET', '/api/product/' . $productId, [ + $bearerToken = $this->getBearerToken(['product_read', 'product_write']); + static::createClient()->request('GET', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, ]); self::assertResponseStatusCodeSame(404); diff --git a/tests/Integration/ApiPlatform/ProductMultiShopEndpointTest.php b/tests/Integration/ApiPlatform/ProductMultiShopEndpointTest.php index f935f1e..ee4aab2 100644 --- a/tests/Integration/ApiPlatform/ProductMultiShopEndpointTest.php +++ b/tests/Integration/ApiPlatform/ProductMultiShopEndpointTest.php @@ -85,6 +85,14 @@ public static function setUpBeforeClass(): void ]; } + public function getProtectedEndpoints(): iterable + { + yield 'get endpoint' => [ + 'GET', + '/api/product/1', + ]; + } + public static function tearDownAfterClass(): void { parent::tearDownAfterClass(); @@ -99,8 +107,7 @@ public static function tearDownAfterClass(): void public function testShopContextIsRequired(): void { $bearerToken = $this->getBearerToken(['product_write']); - $client = static::createClient(); - $response = $client->request('POST', '/api/product', [ + $response = static::createClient()->request('POST', '/api/product', [ 'auth_bearer' => $bearerToken, 'json' => [ 'type' => ProductType::TYPE_STANDARD, @@ -118,8 +125,7 @@ public function testShopContextIsRequired(): void public function testCreateProductForFirstShop(): int { $bearerToken = $this->getBearerToken(['product_write']); - $client = static::createClient(); - $response = $client->request('POST', '/api/product', [ + $response = static::createClient()->request('POST', '/api/product', [ 'auth_bearer' => $bearerToken, 'json' => [ 'type' => ProductType::TYPE_STANDARD, @@ -155,8 +161,7 @@ public function testCreateProductForFirstShop(): int public function testGetProductForFirstShopIsSuccessful(int $productId): int { $bearerToken = $this->getBearerToken(['product_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/product/' . $productId, [ + $response = static::createClient()->request('GET', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, 'extra' => [ 'parameters' => [ @@ -180,8 +185,7 @@ public function testGetProductForFirstShopIsSuccessful(int $productId): int public function testGetProductForSecondShopIsFailing(int $productId): int { $bearerToken = $this->getBearerToken(['product_read']); - $client = static::createClient(); - $response = $client->request('GET', '/api/product/' . $productId, [ + $response = static::createClient()->request('GET', '/api/product/' . $productId, [ 'auth_bearer' => $bearerToken, 'extra' => [ 'parameters' => [