diff --git a/api/migrations/Version20220407091642.php b/api/migrations/Version20220407091642.php index 29e1f1c0b..3bfc31a2a 100644 --- a/api/migrations/Version20220407091642.php +++ b/api/migrations/Version20220407091642.php @@ -27,7 +27,6 @@ public function up(Schema $schema): void public function down(Schema $schema): void { // this down() migration is auto-generated, please modify it to your needs - $this->addSql('CREATE SCHEMA public'); $this->addSql('ALTER TABLE source_field DROP is_system'); $this->addSql('ALTER TABLE source_field DROP default_label'); } diff --git a/api/migrations/Version20220408122945.php b/api/migrations/Version20220408122945.php new file mode 100644 index 000000000..3223ddc0b --- /dev/null +++ b/api/migrations/Version20220408122945.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE localized_catalog ADD is_default BOOLEAN DEFAULT \'false\' NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE localized_catalog DROP is_default'); + } +} diff --git a/api/src/Elasticsuite/Standard/src/Catalog/DataPersister/LocalizedCatalogDataPersister.php b/api/src/Elasticsuite/Standard/src/Catalog/DataPersister/LocalizedCatalogDataPersister.php new file mode 100644 index 000000000..82b12c025 --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/DataPersister/LocalizedCatalogDataPersister.php @@ -0,0 +1,68 @@ + + * @copyright 2022 Smile + * @license Licensed to Smile-SA. All rights reserved. No warranty, explicit or implicit, provided. + * Unauthorized copying of this file, via any medium, is strictly prohibited. + */ + +declare(strict_types=1); + +namespace Elasticsuite\Catalog\DataPersister; + +use ApiPlatform\Core\DataPersister\DataPersisterInterface; +use Doctrine\ORM\EntityManagerInterface; +use Elasticsuite\Catalog\Model\LocalizedCatalog; +use Elasticsuite\Catalog\Repository\LocalizedCatalogRepository; + +class LocalizedCatalogDataPersister implements DataPersisterInterface +{ + public function __construct( + private EntityManagerInterface $entityManager, + private LocalizedCatalogRepository $localizedCatalogRepository + ) { + } + + /** + * {@inheritdoc} + */ + public function supports($data): bool + { + return $data instanceof LocalizedCatalog; + } + + /** + * {@inheritdoc} + * + * @param LocalizedCatalog $data + * + * @return LocalizedCatalog + */ + public function persist($data) + { + if ($data->isDefault()) { + $this->localizedCatalogRepository->unsetDefaultLocalizedCatalog(); + } + $this->entityManager->persist($data); + $this->entityManager->flush(); + + return $data; + } + + /** + * {@inheritdoc} + * + * @param LocalizedCatalog $data + */ + public function remove($data) + { + $this->entityManager->remove($data); + $this->entityManager->flush(); + } +} diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Exception/NoCatalogException.php b/api/src/Elasticsuite/Standard/src/Catalog/Exception/NoCatalogException.php new file mode 100644 index 000000000..924333eb9 --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/Exception/NoCatalogException.php @@ -0,0 +1,30 @@ + + * @copyright 2022 Smile + * @license Licensed to Smile-SA. All rights reserved. No warranty, explicit or implicit, provided. + * Unauthorized copying of this file, via any medium, is strictly prohibited. + */ + +declare(strict_types=1); + +namespace Elasticsuite\Catalog\Exception; + +use ApiPlatform\Core\Exception\ExceptionInterface; + +class NoCatalogException extends \LogicException implements ExceptionInterface +{ + public function __construct( + string $message = 'No localized catalog found', + int $code = 0, + ?\Throwable $previous = null + ) { + parent::__construct($message, $code, $previous); + } +} diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Model/LocalizedCatalog.php b/api/src/Elasticsuite/Standard/src/Catalog/Model/LocalizedCatalog.php index 375e5bb44..becd08cae 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Model/LocalizedCatalog.php +++ b/api/src/Elasticsuite/Standard/src/Catalog/Model/LocalizedCatalog.php @@ -48,6 +48,8 @@ class LocalizedCatalog private string $locale; + private bool $isDefault = false; + private Catalog $catalog; public function getId(): ?int @@ -91,6 +93,18 @@ public function setLocale(string $locale): self return $this; } + public function isDefault(): bool + { + return $this->isDefault; + } + + public function setIsDefault(bool $isDefault): self + { + $this->isDefault = $isDefault; + + return $this; + } + public function getCatalog(): ?Catalog { return $this->catalog; diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Repository/LocalizedCatalogRepository.php b/api/src/Elasticsuite/Standard/src/Catalog/Repository/LocalizedCatalogRepository.php index f7f3f2dc1..8f03de637 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Repository/LocalizedCatalogRepository.php +++ b/api/src/Elasticsuite/Standard/src/Catalog/Repository/LocalizedCatalogRepository.php @@ -32,4 +32,14 @@ public function __construct(ManagerRegistry $registry) { parent::__construct($registry, LocalizedCatalog::class); } + + public function unsetDefaultLocalizedCatalog(): void + { + $this->createQueryBuilder('') + ->update(LocalizedCatalog::class, 'lc') + ->set('lc.isDefault', ':isDefault') + ->setParameter('isDefault', false) + ->getQuery() + ->execute(); + } } diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/doctrine/LocalizedCatalog.orm.xml b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/doctrine/LocalizedCatalog.orm.xml index 967cc76d4..6cd378598 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/doctrine/LocalizedCatalog.orm.xml +++ b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/doctrine/LocalizedCatalog.orm.xml @@ -11,6 +11,11 @@ + + + + + diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/services.yaml b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/services.yaml index 82f0a36f1..1686e987c 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/services.yaml +++ b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/services.yaml @@ -10,3 +10,15 @@ services: - '@Doctrine\Persistence\ManagerRegistry' tags: - { name: doctrine.repository_service } + + Elasticsuite\Catalog\DataPersister\LocalizedCatalogDataPersister: + arguments: + - '@doctrine.orm.entity_manager' + - '@Elasticsuite\Catalog\Repository\LocalizedCatalogRepository' + tags: + - { name: api_platform.data_persister } + + Elasticsuite\Catalog\Service\DefaultCatalogProvider: + arguments: + - '@Elasticsuite\Catalog\Repository\LocalizedCatalogRepository' + diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/test/services.yaml b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/test/services.yaml new file mode 100644 index 000000000..719db40f9 --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/Resources/config/test/services.yaml @@ -0,0 +1,4 @@ +services: + Elasticsuite\Catalog\Service\DefaultCatalogProviderTest: + alias: Elasticsuite\Catalog\Service\DefaultCatalogProvider + public: true diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Service/DefaultCatalogProvider.php b/api/src/Elasticsuite/Standard/src/Catalog/Service/DefaultCatalogProvider.php new file mode 100644 index 000000000..77fa3fca9 --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/Service/DefaultCatalogProvider.php @@ -0,0 +1,42 @@ + + * @copyright 2022 Smile + * @license Licensed to Smile-SA. All rights reserved. No warranty, explicit or implicit, provided. + * Unauthorized copying of this file, via any medium, is strictly prohibited. + */ + +declare(strict_types=1); + +namespace Elasticsuite\Catalog\Service; + +use Elasticsuite\Catalog\Exception\NoCatalogException; +use Elasticsuite\Catalog\Model\LocalizedCatalog; +use Elasticsuite\Catalog\Repository\LocalizedCatalogRepository; + +class DefaultCatalogProvider +{ + /** + * @param LocalizedCatalogRepository $localizedCatalogRepository + */ + public function __construct( + private LocalizedCatalogRepository $localizedCatalogRepository + ) { + } + + public function getDefaultLocalizedCatalog(): LocalizedCatalog + { + $catalog = $this->localizedCatalogRepository->findOneBy([], ['isDefault' => 'DESC', 'id' => 'ASC']); + if (null === $catalog) { + throw new NoCatalogException(); + } + + return $catalog; + } +} diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/CatalogsTest.php b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/CatalogsTest.php index 03bb37a10..197fe47ab 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/CatalogsTest.php +++ b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/CatalogsTest.php @@ -16,63 +16,22 @@ namespace Elasticsuite\Catalog\Tests\Api\Rest; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; use Elasticsuite\Catalog\Model\Catalog; -use Elasticsuite\User\DataFixtures\LoginTrait; -use Liip\TestFixturesBundle\Services\DatabaseToolCollection; -use Liip\TestFixturesBundle\Services\DatabaseTools\AbstractDatabaseTool; +use Elasticsuite\Standard\src\Test\AbstractEntityTest; -class CatalogsTest extends ApiTestCase +class CatalogsTest extends AbstractEntityTest { - use LoginTrait; - - private AbstractDatabaseTool $databaseTool; - - protected function setUp(): void + protected static function getFixtureFiles(): array { - $this->databaseTool = static::getContainer()->get(DatabaseToolCollection::class)->get(); + return [__DIR__ . '/../../fixtures/catalogs.yaml']; } - /** - * @dataProvider validCatalogProvider - * - * @param mixed $validCatalog - */ - public function testCreateValidCatalog($validCatalog): void + protected function getEntityClass(): string { - $client = static::createClient(); - - $loginJson = $this->login( - $client, - static::getContainer()->get('doctrine')->getManager(), // @phpstan-ignore-line - static::getContainer()->get('security.user_password_hasher') - ); - - $response = $client->request('POST', '/catalogs', ['auth_bearer' => $loginJson['token'], 'json' => $validCatalog]); - - $this->assertResponseStatusCodeSame(201); - $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); - $this->assertJsonContains( - [ - '@context' => '/contexts/Catalog', - '@type' => 'Catalog', - 'code' => $validCatalog['code'], - ] - ); - - if (isset($validCatalog['name'])) { - $this->assertJsonContains( - [ - 'name' => $validCatalog['name'] ?? '', - ] - ); - } - - $this->assertMatchesRegularExpression('~^/catalogs/\d+$~', $response->toArray()['@id']); - $this->assertMatchesResourceItemJsonSchema(Catalog::class); + return Catalog::class; } - public function validCatalogProvider(): array + public function createValidDataProvider(): array { return [ [['code' => 'valid_code', 'name' => 'B2C Catalog']], @@ -81,55 +40,30 @@ public function validCatalogProvider(): array ]; } - /** - * @dataProvider invalidCatalogProvider - * - * @param mixed $invalidCatalog - */ - public function testCreateInvalidCatalog($invalidCatalog): void + public function createInvalidDataProvider(): array { - $client = static::createClient(); - - $loginJson = $this->login( - $client, - static::getContainer()->get('doctrine')->getManager(),// @phpstan-ignore-line - static::getContainer()->get('security.user_password_hasher') - ); - - $client->request('POST', '/catalogs', ['auth_bearer' => $loginJson['token'], 'json' => $invalidCatalog]); - - $this->assertResponseStatusCodeSame(422); - $this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8'); - $this->assertJsonContains( - [ - '@context' => '/contexts/ConstraintViolationList', - '@type' => 'ConstraintViolationList', - 'hydra:title' => 'An error occurred', - 'hydra:description' => 'code: This value should not be blank.', - ] - ); + return [ + [['code' => '', 'name' => 'Empty Code'], 'code: This value should not be blank.'], + [['code' => ''], 'code: This value should not be blank.'], + [['name' => 'Missing Code'], 'code: This value should not be blank.'], + ]; } - public function invalidCatalogProvider(): array + protected function getJsonCreationValidation(array $validData): array { - return [ - [['code' => '', 'name' => 'Empty Code']], - [['code' => '']], - [['name' => 'Missing Code']], + $data = [ + 'code' => $validData['code'], ]; + + if (isset($validData['name'])) { + $data['name'] = $validData['name']; + } + + return $data; } - /** - * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface - * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface - * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface - * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface - * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface - */ public function testGetCollection(): void { - $this->databaseTool->loadAliceFixture([__DIR__ . '/../../fixtures/catalogs.yaml']); - $client = static::createClient(); $loginJson = $this->login( @@ -153,4 +87,37 @@ public function testGetCollection(): void ] ); } + + public function getDataProvider(): array + { + return [ + [1, ['id' => 1, 'code' => 'b2c_test', 'name' => 'B2C Test Catalog'], 200], + [5, ['id' => 5, 'code' => 'missing_name'], 200], + [10, [], 404], + ]; + } + + protected function getJsonGetValidation(array $expectedData): array + { + $data = ['code' => $expectedData['code']]; + if (isset($expectedData['name'])) { + $data['name'] = $expectedData['name']; + } + + return $data; + } + + public function deleteDataProvider(): array + { + return [ + [1, 200], + [5, 200], + [10, 404], + ]; + } + + protected function getJsonGetCollectionValidation(): array + { + return ['hydra:totalItems' => 20]; + } } diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/LocalizedCatalogsTest.php b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/LocalizedCatalogsTest.php index d08fad0a0..6f4bf5a30 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/LocalizedCatalogsTest.php +++ b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Api/Rest/LocalizedCatalogsTest.php @@ -16,15 +16,100 @@ namespace Elasticsuite\Catalog\Tests\Api\Rest; -use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase; use Elasticsuite\Catalog\Model\LocalizedCatalog; -use Elasticsuite\User\DataFixtures\LoginTrait; +use Elasticsuite\Standard\src\Test\AbstractEntityTest; use Liip\TestFixturesBundle\Services\DatabaseToolCollection; use Liip\TestFixturesBundle\Services\DatabaseTools\AbstractDatabaseTool; -class LocalizedCatalogsTest extends ApiTestCase +class LocalizedCatalogsTest extends AbstractEntityTest { - use LoginTrait; + protected static function getFixtureFiles(): array + { + return [ + __DIR__ . '/../../fixtures/catalogs.yaml', + __DIR__ . '/../../fixtures/localized_catalogs.yaml', + ]; + } + + protected function getEntityClass(): string + { + return LocalizedCatalog::class; + } + + public function createValidDataProvider(): array + { + return [ + [['catalog' => '/catalogs/1', 'code' => 'valid_code', 'name' => 'B2C French catalog', 'locale' => 'fr_FR']], + [['catalog' => '/catalogs/1', 'code' => 'empty_name', 'name' => '', 'locale' => 'en_US']], + [['catalog' => '/catalogs/1', 'code' => 'missing_name', 'locale' => 'fr_FR']], + ]; + } + + public function createInvalidDataProvider(): array + { + return [ + [['code' => 'no_catalog', 'name' => 'B2C French catalog', 'locale' => 'fr_FR'], 'catalog: This value should not be blank.'], + [['catalog' => '/catalogs/2', 'code' => 'valid_code', 'locale' => 'fr_FR', 'name' => 'Empty Code'], 'locale: This code and locale couple already exists.'], + [['catalog' => '/catalogs/1', 'code' => '', 'locale' => 'en_US', 'name' => 'Empty Code'], 'code: This value should not be blank.'], + [['catalog' => '/catalogs/1', 'code' => '', 'locale' => 'en_US'], 'code: This value should not be blank.'], + [['catalog' => '/catalogs/1', 'locale' => 'en_US', 'name' => 'Missing Code'], 'code: This value should not be blank.'], + [['catalog' => '/catalogs/1', 'code' => 'missing_locale'], 'locale: This value should not be blank.'], + [['catalog' => '/catalogs/1', 'code' => 'cat_1_invalid', 'locale' => 'fr-fr'], 'locale: This value is not valid.'], + [['catalog' => '/catalogs/1', 'code' => 'cat_1_invalid', 'locale' => 'strin'], 'locale: This value is not valid.'], + [['catalog' => '/catalogs/1', 'code' => 'cat_1_invalid', 'locale' => 'too_long_locale'], "locale: This value is not valid.\nlocale: This value should have exactly 5 characters."], + [['catalog' => '/catalogs/1', 'code' => 'cat_1_invalid', 'locale' => 'a'], "locale: This value is not valid.\nlocale: This value should have exactly 5 characters."], + [['catalog' => '/catalogs/1', 'code' => 'cat_1_invalid', 'locale' => 'abc'], "locale: This value is not valid.\nlocale: This value should have exactly 5 characters."], + ]; + } + + protected function getJsonCreationValidation(array $validData): array + { + $data = [ + 'code' => $validData['code'], + 'locale' => $validData['locale'], + ]; + if (isset($validData['name'])) { + $data['name'] = $validData['name']; + } + + return $data; + } + + public function getDataProvider(): array + { + return [ + [1, ['id' => 1, 'code' => 'b2c_fr', 'locale' => 'fr_FR', 'name' => 'B2C French Store View'], 200], + [5, ['id' => 5, 'code' => 'empty_name', 'locale' => 'en_US'], 200], + [10, [], 404], + ]; + } + + protected function getJsonGetValidation(array $expectedData): array + { + $data = [ + 'code' => $expectedData['code'], + 'locale' => $expectedData['locale'], + ]; + if (isset($expectedData['name'])) { + $data['name'] = $expectedData['name']; + } + + return $data; + } + + public function deleteDataProvider(): array + { + return [ + [1, 200], + [5, 200], + [10, 404], + ]; + } + + protected function getJsonGetCollectionValidation(): array + { + return ['hydra:totalItems' => 3]; + } private AbstractDatabaseTool $databaseTool; @@ -280,7 +365,7 @@ public function invalidCatalogLocaleLengthProvider(): array */ public function testGetCollection(): void { - $this->databaseTool->loadAliceFixture([__DIR__ . '/../../fixtures/localized_catalogs.yaml']); + $this->databaseTool->loadAliceFixture([__DIR__ . '/../../fixtures/catalogs.yaml', __DIR__ . '/../../fixtures/localized_catalogs.yaml']); $client = static::createClient(); diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Tests/Unit/DefaultCatalogProviderTest.php b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Unit/DefaultCatalogProviderTest.php new file mode 100644 index 000000000..e5568a34d --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/Tests/Unit/DefaultCatalogProviderTest.php @@ -0,0 +1,50 @@ + + * @copyright 2022 Smile + * @license Licensed to Smile-SA. All rights reserved. No warranty, explicit or implicit, provided. + * Unauthorized copying of this file, via any medium, is strictly prohibited. + */ + +declare(strict_types=1); + +namespace Elasticsuite\Catalog\Tests\Unit; + +use Elasticsuite\Catalog\Exception\NoCatalogException; +use Elasticsuite\Catalog\Service\DefaultCatalogProvider; +use Elasticsuite\Standard\src\Test\AbstractTest; + +class DefaultCatalogProviderTest extends AbstractTest +{ + protected DefaultCatalogProvider $defaultCatalogProvider; + + protected function setUp(): void + { + parent::setUp(); + $this->defaultCatalogProvider = static::getContainer()->get('Elasticsuite\Catalog\Service\DefaultCatalogProviderTest'); // @phpstan-ignore-line + $this->loadFixture([__DIR__ . '/../fixtures/catalogs.yaml']); + } + + public function testNoLocalizedCatalog(): void + { + $this->expectException(NoCatalogException::class); + $this->defaultCatalogProvider->getDefaultLocalizedCatalog(); + } + + public function testGetLocalizedCatalog(): void + { + $this->loadFixture([__DIR__ . '/../fixtures/catalogs.yaml', __DIR__ . '/../fixtures/localized_catalogs.yaml']); + $catalog = $this->defaultCatalogProvider->getDefaultLocalizedCatalog(); + $this->assertEquals('B2C French Store View', $catalog->getName()); + + $this->loadFixture([__DIR__ . '/../fixtures/catalogs.yaml', __DIR__ . '/../fixtures/localized_catalogs_with_default.yaml']); + $catalog = $this->defaultCatalogProvider->getDefaultLocalizedCatalog(); + $this->assertEquals('B2B English Store View', $catalog->getName()); + } +} diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs.yaml b/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs.yaml index d0e6437f8..37c7fc3cb 100644 --- a/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs.yaml +++ b/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs.yaml @@ -1,10 +1,3 @@ -Elasticsuite\Catalog\Model\Catalog: - catalog1: - code: b2c - name: B2C Catalog - catalog2: - code: b2b - name: B2B Catalog Elasticsuite\Catalog\Model\LocalizedCatalog: localized_catalog1: @@ -12,13 +5,16 @@ Elasticsuite\Catalog\Model\LocalizedCatalog: code: b2c_fr locale: fr_FR name: B2C French Store View + isDefault: false localized_catalog2: catalog: '@catalog1' code: b2c_en locale: en_US name: B2C English Store View + isDefault: false localized_catalog3: catalog: '@catalog2' code: b2b_en locale: en_US name: B2B English Store View + isDefault: false diff --git a/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs_with_default.yaml b/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs_with_default.yaml new file mode 100644 index 000000000..4d3496464 --- /dev/null +++ b/api/src/Elasticsuite/Standard/src/Catalog/Tests/fixtures/localized_catalogs_with_default.yaml @@ -0,0 +1,20 @@ + +Elasticsuite\Catalog\Model\LocalizedCatalog: + localized_catalog1: + catalog: '@catalog1' + code: b2c_fr + locale: fr_FR + name: B2C French Store View + isDefault: false + localized_catalog2: + catalog: '@catalog1' + code: b2c_en + locale: en_US + name: B2C English Store View + isDefault: false + localized_catalog3: + catalog: '@catalog2' + code: b2b_en + locale: en_US + name: B2B English Store View + isDefault: true diff --git a/api/src/Elasticsuite/Standard/src/DependencyInjection/ElasticsuiteExtension.php b/api/src/Elasticsuite/Standard/src/DependencyInjection/ElasticsuiteExtension.php index 685633f5d..f31b35ae8 100644 --- a/api/src/Elasticsuite/Standard/src/DependencyInjection/ElasticsuiteExtension.php +++ b/api/src/Elasticsuite/Standard/src/DependencyInjection/ElasticsuiteExtension.php @@ -112,6 +112,9 @@ public function load(array $configs, ContainerBuilder $container) } $loader->load('Fixture/Resources/config/services.yaml'); $loader->load('Catalog/Resources/config/services.yaml'); + if ('test' === $container->getParameter('kernel.environment')) { + $loader->load('Catalog/Resources/config/test/services.yaml'); + } $loader->load('User/Resources/config/services.yaml'); $loader->load('Security/Resources/config/services.yaml'); $loader->load('Cache/Resources/config/services.yaml'); diff --git a/api/src/Elasticsuite/Standard/src/Index/Tests/Api/Rest/IndexOperationsTest.php b/api/src/Elasticsuite/Standard/src/Index/Tests/Api/Rest/IndexOperationsTest.php index 5f6715a79..db189ea7d 100644 --- a/api/src/Elasticsuite/Standard/src/Index/Tests/Api/Rest/IndexOperationsTest.php +++ b/api/src/Elasticsuite/Standard/src/Index/Tests/Api/Rest/IndexOperationsTest.php @@ -52,11 +52,6 @@ protected function getEntityClass(): string return Index::class; } - protected function getApiPath(): string - { - return '/indices'; - } - protected static function getFixtureFiles(): array { return [ @@ -68,8 +63,6 @@ protected static function getFixtureFiles(): array protected function getJsonCreationValidation(array $validData): array { return [ - '@context' => '/contexts/Index', - '@type' => 'Index', 'aliases' => [ '.catalog_' . $validData['catalog'], '.entity_' . $validData['entityType'], @@ -79,19 +72,12 @@ protected function getJsonCreationValidation(array $validData): array protected function getJsonGetValidation(array $expectedData): array { - return [ - '@context' => '/contexts/Index', - '@id' => '/indices/' . $expectedData['id'], - '@type' => 'Index', - ]; + return []; } protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/Index', - '@id' => '/indices', - '@type' => 'hydra:Collection', 'hydra:totalItems' => self::$initialIndicesCount + 6, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Index/Tests/fixtures/catalogs.yaml b/api/src/Elasticsuite/Standard/src/Index/Tests/fixtures/catalogs.yaml index 79f4a7965..26917b801 100644 --- a/api/src/Elasticsuite/Standard/src/Index/Tests/fixtures/catalogs.yaml +++ b/api/src/Elasticsuite/Standard/src/Index/Tests/fixtures/catalogs.yaml @@ -12,13 +12,16 @@ Elasticsuite\Catalog\Model\LocalizedCatalog: code: b2c_fr locale: fr_FR name: B2C French Store View + isDefault: false catalog1_en: catalog: '@catalog1' code: b2c_en locale: en_US name: B2C English Store View + isDefault: false catalog2_en: catalog: '@catalog2' code: b2b_en locale: en_US name: B2B English Store View + isDefault: false diff --git a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/MetadataTest.php b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/MetadataTest.php index 197350a18..d2f75a35f 100644 --- a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/MetadataTest.php +++ b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/MetadataTest.php @@ -31,16 +31,9 @@ protected function getEntityClass(): string return Metadata::class; } - protected function getApiPath(): string - { - return '/metadata'; - } - protected function getJsonCreationValidation(array $validData): array { return [ - '@context' => '/contexts/Metadata', - '@type' => 'Metadata', 'entity' => $validData['entity'], ]; } @@ -48,9 +41,6 @@ protected function getJsonCreationValidation(array $validData): array protected function getJsonGetValidation(array $expectedData): array { return [ - '@context' => '/contexts/Metadata', - '@id' => '/metadata/' . $expectedData['id'], - '@type' => 'Metadata', 'entity' => $expectedData['entity'], ]; } @@ -58,9 +48,6 @@ protected function getJsonGetValidation(array $expectedData): array protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/Metadata', - '@id' => '/metadata', - '@type' => 'hydra:Collection', 'hydra:totalItems' => 2, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldLabelTest.php b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldLabelTest.php index 99d692ec4..9a295131e 100644 --- a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldLabelTest.php +++ b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldLabelTest.php @@ -36,35 +36,21 @@ protected function getEntityClass(): string return SourceFieldLabel::class; } - protected function getApiPath(): string - { - return '/source_field_labels'; - } - protected function getJsonCreationValidation(array $validData): array { return [ - '@context' => '/contexts/SourceFieldLabel', - '@type' => 'SourceFieldLabel', 'label' => $validData['label'], ]; } protected function getJsonGetValidation(array $expectedData): array { - return [ - '@context' => '/contexts/SourceFieldLabel', - '@id' => '/source_field_labels/' . $expectedData['id'], - '@type' => 'SourceFieldLabel', - ]; + return []; } protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/SourceFieldLabel', - '@id' => '/source_field_labels', - '@type' => 'hydra:Collection', 'hydra:totalItems' => 4, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionLabelTest.php b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionLabelTest.php index 35af6e66b..6776f8271 100644 --- a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionLabelTest.php +++ b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionLabelTest.php @@ -37,35 +37,21 @@ protected function getEntityClass(): string return SourceFieldOptionLabel::class; } - protected function getApiPath(): string - { - return '/source_field_option_labels'; - } - protected function getJsonCreationValidation(array $validData): array { return [ - '@context' => '/contexts/SourceFieldOptionLabel', - '@type' => 'SourceFieldOptionLabel', 'label' => $validData['label'], ]; } protected function getJsonGetValidation(array $expectedData): array { - return [ - '@context' => '/contexts/SourceFieldOptionLabel', - '@id' => '/source_field_option_labels/' . $expectedData['id'], - '@type' => 'SourceFieldOptionLabel', - ]; + return []; } protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/SourceFieldOptionLabel', - '@id' => '/source_field_option_labels', - '@type' => 'hydra:Collection', 'hydra:totalItems' => 4, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionTest.php b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionTest.php index d521ec904..4dd09bb41 100644 --- a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionTest.php +++ b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldOptionTest.php @@ -35,34 +35,19 @@ protected function getEntityClass(): string return SourceFieldOption::class; } - protected function getApiPath(): string - { - return '/source_field_options'; - } - protected function getJsonCreationValidation(array $validData): array { - return [ - '@context' => '/contexts/SourceFieldOption', - '@type' => 'SourceFieldOption', - ]; + return []; } protected function getJsonGetValidation(array $expectedData): array { - return [ - '@context' => '/contexts/SourceFieldOption', - '@id' => '/source_field_options/' . $expectedData['id'], - '@type' => 'SourceFieldOption', - ]; + return []; } protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/SourceFieldOption', - '@id' => '/source_field_options', - '@type' => 'hydra:Collection', 'hydra:totalItems' => 4, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldTest.php b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldTest.php index 625be3d6a..b8a634ade 100644 --- a/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldTest.php +++ b/api/src/Elasticsuite/Standard/src/Metadata/Tests/Api/Rest/SourceFieldTest.php @@ -34,16 +34,9 @@ protected function getEntityClass(): string return SourceField::class; } - protected function getApiPath(): string - { - return '/source_fields'; - } - protected function getJsonCreationValidation(array $validData): array { $json = [ - '@context' => '/contexts/SourceField', - '@type' => 'SourceField', 'name' => $validData['name'], ]; @@ -57,9 +50,6 @@ protected function getJsonCreationValidation(array $validData): array protected function getJsonGetValidation(array $expectedData): array { return [ - '@context' => '/contexts/SourceField', - '@id' => '/source_fields/' . $expectedData['id'], - '@type' => 'SourceField', 'name' => $expectedData['name'], ]; } @@ -67,9 +57,6 @@ protected function getJsonGetValidation(array $expectedData): array protected function getJsonGetCollectionValidation(): array { return [ - '@context' => '/contexts/SourceField', - '@id' => '/source_fields', - '@type' => 'hydra:Collection', 'hydra:totalItems' => 11, ]; } diff --git a/api/src/Elasticsuite/Standard/src/Test/AbstractEntityTest.php b/api/src/Elasticsuite/Standard/src/Test/AbstractEntityTest.php index 2547a76f0..5b1f8f154 100644 --- a/api/src/Elasticsuite/Standard/src/Test/AbstractEntityTest.php +++ b/api/src/Elasticsuite/Standard/src/Test/AbstractEntityTest.php @@ -16,8 +16,23 @@ namespace Elasticsuite\Standard\src\Test; +use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; +use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; +use ApiPlatform\Core\Operation\PathSegmentNameGeneratorInterface; + abstract class AbstractEntityTest extends AbstractTest { + private PathSegmentNameGeneratorInterface $pathGenerator; + private ResourceMetadataFactoryInterface $metadataFactory; + private ?ResourceMetadata $resource = null; + + public function __construct(?string $name = null, array $data = [], $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->pathGenerator = static::getContainer()->get('api_platform.path_segment_name_generator'); + $this->metadataFactory = static::getContainer()->get('api_platform.metadata.resource.metadata_factory'); + } + public static function setUpBeforeClass(): void { static::loadFixture(static::getFixtureFiles()); @@ -27,32 +42,32 @@ abstract protected static function getFixtureFiles(): array; abstract protected function getEntityClass(): string; - abstract protected function getApiPath(): string; - abstract protected function getJsonCreationValidation(array $validData): array; abstract protected function getJsonGetValidation(array $expectedData): array; abstract protected function getJsonGetCollectionValidation(): array; - public function createValidDataProvider(): array - { - return []; - } + abstract public function createValidDataProvider(): array; - public function createInvalidDataProvider(): array - { - return []; - } + abstract public function createInvalidDataProvider(): array; + + abstract public function getDataProvider(): array; + + abstract public function deleteDataProvider(): array; - public function getDataProvider(): array + protected function getShortName(): string { - return []; + if (!$this->resource) { + $this->resource = $this->metadataFactory->create($this->getEntityClass()); + } + + return $this->resource->getShortName(); } - public function deleteDataProvider(): array + protected function getApiPath(): string { - return []; + return '/' . $this->pathGenerator->getSegmentName($this->getShortName()); } /** @@ -62,7 +77,16 @@ public function testCreateValidData(array $validData, string $validRegex = null) { $response = $this->requestRest('POST', $this->getApiPath(), $validData); $this->assertResponseStatusCodeSame(201); - $this->assertJsonContains($this->getJsonCreationValidation($validData)); + $shortName = $this->getShortName(); + $this->assertJsonContains( + array_merge( + [ + '@context' => "/contexts/$shortName", + '@type' => $shortName, + ], + $this->getJsonCreationValidation($validData) + ) + ); $this->assertMatchesRegularExpression($validRegex ?? '~^' . $this->getApiPath() . '/\d+$~', $response->toArray()['@id']); $this->assertMatchesResourceItemJsonSchema($this->getEntityClass()); } @@ -104,7 +128,17 @@ public function testGet(int|string $id, array $expectedData, int $statusCode): v $this->assertResponseStatusCodeSame($statusCode); } else { $this->assertResponseIsSuccessful(); - $this->assertJsonContains($this->getJsonGetValidation($expectedData)); + $shortName = $this->getShortName(); + $this->assertJsonContains( + array_merge( + [ + '@context' => "/contexts/$shortName", + '@type' => $shortName, + '@id' => $this->getApiPath() . '/' . $expectedData['id'], + ], + $this->getJsonGetValidation($expectedData) + ) + ); } } @@ -129,6 +163,16 @@ public function testGetCollection(): void { $this->requestRest('GET', $this->getApiPath()); $this->assertResponseIsSuccessful(); - $this->assertJsonContains($this->getJsonGetCollectionValidation()); + $shortName = $this->getShortName(); + $this->assertJsonContains( + array_merge( + [ + '@context' => "/contexts/$shortName", + '@id' => $this->getApiPath(), + '@type' => 'hydra:Collection', + ], + $this->getJsonGetCollectionValidation() + ) + ); } }