From 14cfecd911274d9058611d626dfdc18fca4b0c83 Mon Sep 17 00:00:00 2001 From: Lorenzo Ruozzi Date: Mon, 6 Nov 2023 12:21:02 +0100 Subject: [PATCH] Fix option value codes duplicated (#179) --- .../ProductOptionValueHandlerSpec.php | 2 +- .../ProductOptionValueHandler.php | 2 + .../Integration/DataFixtures/DataFixture.php | 10 ++ .../ORM/resources/Product/box.yaml | 40 ++++++++ tests/Integration/Product/ImporterTest.php | 96 +++++++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 tests/Integration/DataFixtures/DataFixture.php create mode 100644 tests/Integration/DataFixtures/ORM/resources/Product/box.yaml diff --git a/spec/ValueHandler/ProductOptionValueHandlerSpec.php b/spec/ValueHandler/ProductOptionValueHandlerSpec.php index 0209d06f..64099f96 100644 --- a/spec/ValueHandler/ProductOptionValueHandlerSpec.php +++ b/spec/ValueHandler/ProductOptionValueHandlerSpec.php @@ -23,7 +23,6 @@ use Sylius\Component\Resource\Repository\RepositoryInterface; use Sylius\Component\Resource\Translation\Provider\TranslationLocaleProviderInterface; use Symfony\Contracts\Translation\TranslatorInterface; -use Webgriffe\SyliusAkeneoPlugin\ApiClientInterface; use Webgriffe\SyliusAkeneoPlugin\ValueHandler\ProductOptionValueHandler; use Webgriffe\SyliusAkeneoPlugin\ValueHandlerInterface; @@ -61,6 +60,7 @@ public function let( ): void { $productVariant->getCode()->willReturn(self::VARIANT_CODE); $productVariant->getProduct()->willReturn($product); + $productVariant->getOptionValues()->willReturn(new ArrayCollection()); $product->getCode()->willReturn(self::PRODUCT_CODE); $product->getOptions()->willReturn(new ArrayCollection([$productOption->getWrappedObject()])); $productOption->getCode()->willReturn(self::OPTION_CODE); diff --git a/src/ValueHandler/ProductOptionValueHandler.php b/src/ValueHandler/ProductOptionValueHandler.php index f645bbd6..a45bd71d 100644 --- a/src/ValueHandler/ProductOptionValueHandler.php +++ b/src/ValueHandler/ProductOptionValueHandler.php @@ -99,6 +99,8 @@ public function handle($productVariant, string $optionCode, array $akeneoValue): /** @var string|array|bool|int $akeneoValueData */ $akeneoValueData = $akeneoValue[0]['data']; + $productVariant->getOptionValues()->clear(); + $productOption = $this->getProductOption($optionCode, $productVariant, $product); /** @var string $attributeType */ diff --git a/tests/Integration/DataFixtures/DataFixture.php b/tests/Integration/DataFixtures/DataFixture.php new file mode 100644 index 00000000..bb64d550 --- /dev/null +++ b/tests/Integration/DataFixtures/DataFixture.php @@ -0,0 +1,10 @@ + + +Sylius\Component\Core\Model\ProductVariant: + box-variant: + code: "BOX_VARIANT" + product: "@box-product" + optionValues: + - "@format-133x32" diff --git a/tests/Integration/Product/ImporterTest.php b/tests/Integration/Product/ImporterTest.php index 338743ba..a8baf0a8 100644 --- a/tests/Integration/Product/ImporterTest.php +++ b/tests/Integration/Product/ImporterTest.php @@ -13,9 +13,22 @@ use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Core\Model\ProductVariantInterface; use Sylius\Component\Core\Repository\ProductRepositoryInterface; +use Sylius\Component\Product\Model\ProductOptionValueInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Component\Filesystem\Filesystem; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\InMemoryAttributeApi; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\InMemoryAttributeOptionApi; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\InMemoryProductApi; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\Model\Attribute; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\Model\AttributeOption; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\Model\AttributeType; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\Api\Model\Product; +use Tests\Webgriffe\SyliusAkeneoPlugin\InMemory\Client\InMemoryAkeneoPimClient; +use Tests\Webgriffe\SyliusAkeneoPlugin\Integration\DataFixtures\DataFixture; use Webgriffe\SyliusAkeneoPlugin\ImporterInterface; +use Webgriffe\SyliusAkeneoPlugin\PriorityValueHandlersResolver; +use Webgriffe\SyliusAkeneoPlugin\Product\Importer; +use Webgriffe\SyliusAkeneoPlugin\ValueHandler\ProductOptionValueHandler; final class ImporterTest extends KernelTestCase { @@ -796,4 +809,87 @@ public function it_enables_product_without_variants_while_importing_a_new_one(): self::assertTrue($product->isEnabled()); self::assertTrue($productVariant->isEnabled()); } + + /** + * @test + * + * @TODO This tests adds also the new in memory implementation of Akeneo API client. + * To use that only on this specific test we have overriden the importer definition. + * Obviously, when the new implementation will be the default one, all this rewrite should be removed! + */ + public function it_does_not_duplicate_product_option_values_when_changed(): void + { + $this->fixtureLoader->load( + [ + DataFixture::path . '/ORM/resources/Locale/en_US.yaml', + DataFixture::path . '/ORM/resources/Product/box.yaml', + ], + [], + [], + PurgeMode::createDeleteMode(), + ); + $akeneoPimClient = new InMemoryAkeneoPimClient(); + $productOptionValueHandler = new ProductOptionValueHandler( + $akeneoPimClient, + self::getContainer()->get('sylius.repository.product_option'), + self::getContainer()->get('sylius.factory.product_option_value'), + self::getContainer()->get('sylius.factory.product_option_value_translation'), + self::getContainer()->get('sylius.repository.product_option_value'), + self::getContainer()->get('sylius.translation_locale_provider'), + self::getContainer()->get('translator'), + ); + $valueHandlersResolver = new PriorityValueHandlersResolver(); + $valueHandlersResolver->add($productOptionValueHandler); + $this->importer = new Importer( + self::getContainer()->get('sylius.factory.product_variant'), + self::getContainer()->get('sylius.repository.product_variant'), + self::getContainer()->get('sylius.repository.product'), + $akeneoPimClient, + $valueHandlersResolver, + self::getContainer()->get('sylius.factory.product'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.taxons_resolver'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.product_options_resolver'), + self::getContainer()->get('event_dispatcher'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.channels_resolver'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.status_resolver'), + self::getContainer()->get('sylius.factory.product_taxon'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.variant_status_resolver'), + self::getContainer()->get('webgriffe_sylius_akeneo.product.validator'), + ); + $akeneoProduct = Product::create('BOX_VARIANT', [ + 'values' => ['format' => [[ + 'locale' => null, + 'scope' => null, + 'data' => '133x48', + ]]], + 'parent' => 'BOX', + ]); + InMemoryProductApi::addResource($akeneoProduct); + $akeneoFormatAttribute = Attribute::create('format', [ + 'type' => AttributeType::SIMPLE_SELECT, + ]); + InMemoryAttributeApi::addResource($akeneoFormatAttribute); + $akeneoFormatAttributeOption = AttributeOption::create( + $akeneoFormatAttribute->getIdentifier(), + '133x48', + 1, + ['en_US' => 'Format 133x48'], + ); + InMemoryAttributeOptionApi::addResource($akeneoFormatAttributeOption); + + $this->importer->import('BOX_VARIANT'); + + /** @var ProductVariantInterface[] $allVariants */ + $allVariants = $this->productVariantRepository->findAll(); + $this->assertCount(1, $allVariants); + $variant = reset($allVariants); + $this->assertInstanceOf(ProductVariantInterface::class, $variant); + $this->assertInstanceOf(ProductInterface::class, $variant->getProduct()); + $this->assertEquals('BOX', $variant->getProduct()->getCode()); + $this->assertCount(1, $variant->getOptionValues()); + $optionValue = $variant->getOptionValues()->first(); + $this->assertInstanceOf(ProductOptionValueInterface::class, $optionValue); + $this->assertEquals('format', $optionValue->getOptionCode()); + $this->assertEquals('Format 133x48', $optionValue->getValue()); + } }