From 9bb0472cbf2aaf36b8269d05e7191d4cc1e8ad74 Mon Sep 17 00:00:00 2001 From: tleon Date: Mon, 11 Mar 2024 16:52:14 +0100 Subject: [PATCH] chore(api): product listing endpoint --- src/ApiPlatform/Resources/ProductList.php | 77 +++++++++++++++++ .../ProductListingEndpointTest.php | 86 +++++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 src/ApiPlatform/Resources/ProductList.php create mode 100644 tests/Integration/ApiPlatform/ProductListingEndpointTest.php diff --git a/src/ApiPlatform/Resources/ProductList.php b/src/ApiPlatform/Resources/ProductList.php new file mode 100644 index 0000000..b9583d3 --- /dev/null +++ b/src/ApiPlatform/Resources/ProductList.php @@ -0,0 +1,77 @@ + + * @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 PrestaShop\Module\APIResources\ApiPlatform\Resources; + + +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductNotFoundException; +use PrestaShop\PrestaShop\Core\Domain\Shop\Exception\ShopAssociationNotFound; +use PrestaShop\PrestaShop\Core\Search\Filters\ProductFilters; +use PrestaShopBundle\ApiPlatform\Metadata\DQBPaginatedList; +use PrestaShopBundle\ApiPlatform\Provider\QueryListProvider; +use Symfony\Component\HttpFoundation\Response; + +#[ApiResource( + operations: [ + new DQBPaginatedList( + uriTemplate: '/products', + provider: QueryListProvider::class, + scopes: ['product_read'], + ApiResourceMapping: [ + '[id_product]' => '[productId]', + '[final_price_tax_excluded]' => '[price]' + ], + queryBuilder: 'prestashop.core.grid.query_builder.product', + filterClass: ProductFilters::class, + ), + ], + exceptionToStatus: [ + ProductNotFoundException::class => Response::HTTP_NOT_FOUND, + ShopAssociationNotFound::class => Response::HTTP_NOT_FOUND, + ], +)] +class ProductList +{ + #[ApiProperty(identifier: true)] + public int $productId; + + public string $type; + + public bool $active; + + public string $name; + + public int $quantity; + + public string $price; + + public string $category; +} diff --git a/tests/Integration/ApiPlatform/ProductListingEndpointTest.php b/tests/Integration/ApiPlatform/ProductListingEndpointTest.php new file mode 100644 index 0000000..8876f2c --- /dev/null +++ b/tests/Integration/ApiPlatform/ProductListingEndpointTest.php @@ -0,0 +1,86 @@ + + * @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; + +use Tests\Resources\Resetter\LanguageResetter; +use Tests\Resources\Resetter\ProductResetter; +use Tests\Resources\ResourceResetter; + +class ProductListingEndpointTest extends ApiTestCase +{ + protected static int $frenchLangId; + + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + (new ResourceResetter())->backupTestModules(); + ProductResetter::resetProducts(); + LanguageResetter::resetLanguages(); + self::$frenchLangId = self::addLanguageByLocale('fr-FR'); + self::createApiClient(['product_read']); + } + + public static function tearDownAfterClass(): void + { + parent::tearDownAfterClass(); + ProductResetter::resetProducts(); + LanguageResetter::resetLanguages(); + // Reset modules folder that are removed with the FR language + (new ResourceResetter())->resetTestModules(); + } + public function getProtectedEndpoints(): iterable + { + yield 'list endpoint' => [ + 'GET', + '/api/products', + ]; + } + + public function testListProducts(): void + { + $bearerToken = $this->getBearerToken([ + 'product_read', + ]); + + $response = static::createClient()->request('GET', '/api/products', ['auth_bearer' => $bearerToken]); + self::assertResponseStatusCodeSame(200); + self::assertCount(50, json_decode($response->getContent())->items); + + $response = static::createClient()->request('GET', '/api/products?limit=10', ['auth_bearer' => $bearerToken]); + self::assertResponseStatusCodeSame(200); + self::assertCount(10, json_decode($response->getContent())->items); + + // maybe add more tests + + static::createClient()->request('GET', '/api/products'); + self::assertResponseStatusCodeSame(401); + } + +} \ No newline at end of file