diff --git a/config/services.xml b/config/services.xml
index c007c44a..c50f636a 100644
--- a/config/services.xml
+++ b/config/services.xml
@@ -132,6 +132,11 @@
+
+
+
+
+
diff --git a/phpstan.neon b/phpstan.neon
index c8aab8e1..e9be45f6 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -22,3 +22,5 @@ parameters:
message: '/Cannot call method trans\(\) on Symfony\\Contracts\\Translation\\TranslatorInterface\|null\./'
path: src/Controller/ProductEnqueueController
+ # Move alias here when global alias are supported also on Psalm: https://github.com/vimeo/psalm/discussions/5376
+ typeAliases:
diff --git a/src/AttributeOptions/Importer.php b/src/AttributeOptions/Importer.php
index 0c67bf6b..092fef14 100644
--- a/src/AttributeOptions/Importer.php
+++ b/src/AttributeOptions/Importer.php
@@ -10,14 +10,22 @@
use DateTime;
use Sylius\Component\Attribute\AttributeType\SelectAttributeType;
use Sylius\Component\Product\Model\ProductAttributeInterface;
+use Sylius\Component\Product\Model\ProductOptionInterface;
+use Sylius\Component\Product\Model\ProductOptionTranslationInterface;
+use Sylius\Component\Product\Model\ProductOptionValueInterface;
+use Sylius\Component\Product\Model\ProductOptionValueTranslationInterface;
+use Sylius\Component\Product\Repository\ProductOptionRepositoryInterface;
+use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
+use Sylius\Component\Resource\Translation\Provider\TranslationLocaleProviderInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Webgriffe\SyliusAkeneoPlugin\Event\IdentifiersModifiedSinceSearchBuilderBuiltEvent;
use Webgriffe\SyliusAkeneoPlugin\ImporterInterface;
+use Webmozart\Assert\Assert;
/**
- * @phpstan-type AkeneoAttribute array{code: string, type: string}
- * @phpstan-type AkeneoAttributeOption array{_links: array, code: string, attribute: string, sort_order: int, labels: array}
+ * @psalm-type AkeneoAttribute array{code: string, type: string}
+ * @psalm-type AkeneoAttributeOption array{_links: array, code: string, attribute: string, sort_order: int, labels: array}
*/
final class Importer implements ImporterInterface
{
@@ -27,12 +35,47 @@ final class Importer implements ImporterInterface
/**
* @param RepositoryInterface $attributeRepository
+ * @param ?FactoryInterface $productOptionValueTranslationFactory
+ * @param ?FactoryInterface $productOptionValueFactory
+ * @param ?FactoryInterface $productOptionTranslationFactory
*/
public function __construct(
private AkeneoPimClientInterface $apiClient,
private RepositoryInterface $attributeRepository,
private EventDispatcherInterface $eventDispatcher,
+ private ?ProductOptionRepositoryInterface $optionRepository = null,
+ private ?TranslationLocaleProviderInterface $translationLocaleProvider = null,
+ private ?FactoryInterface $productOptionValueTranslationFactory = null,
+ private ?FactoryInterface $productOptionValueFactory = null,
+ private ?FactoryInterface $productOptionTranslationFactory = null,
) {
+ if ($this->optionRepository === null) {
+ trigger_deprecation(
+ 'webgriffe/sylius-akeneo-plugin',
+ 'v2.2.0',
+ 'Not passing a "%s" instance to "%s" constructor is deprecated and will not be possible anymore in the next major version.',
+ ProductOptionRepositoryInterface::class,
+ self::class,
+ );
+ }
+ if ($this->translationLocaleProvider === null) {
+ trigger_deprecation(
+ 'webgriffe/sylius-akeneo-plugin',
+ 'v2.2.0',
+ 'Not passing a "%s" instance to "%s" constructor is deprecated and will not be possible anymore in the next major version.',
+ TranslationLocaleProviderInterface::class,
+ self::class,
+ );
+ }
+ if ($this->productOptionValueTranslationFactory === null) {
+ trigger_deprecation(
+ 'webgriffe/sylius-akeneo-plugin',
+ 'v2.2.0',
+ 'Not passing a "%s" instance to "%s" constructor is deprecated and will not be possible anymore in the next major version.',
+ FactoryInterface::class,
+ self::class,
+ );
+ }
}
public function getAkeneoEntity(): string
@@ -44,8 +87,18 @@ public function import(string $identifier): void
{
$attribute = $this->attributeRepository->findOneBy(['code' => $identifier]);
if (null !== $attribute && $attribute->getType() === SelectAttributeType::TYPE) {
- $this->importAttribute($identifier, $attribute);
+ $this->importAttributeConfiguration($identifier, $attribute);
+ }
+ $optionRepository = $this->optionRepository;
+ if (!$optionRepository instanceof ProductOptionRepositoryInterface) {
+ return;
+ }
+ $option = $optionRepository->findOneBy(['code' => $identifier]);
+ if (!$option instanceof ProductOptionInterface) {
+ return;
}
+ $this->updateProductOption($option);
+ $this->importOptionValues($identifier, $option);
}
/**
@@ -64,7 +117,10 @@ public function getIdentifiersModifiedSince(DateTime $sinceDate): array
/** @var ResourceCursorInterface $akeneoAttributes */
$akeneoAttributes = $this->apiClient->getAttributeApi()->all(50, ['search' => $searchBuilder->getFilters()]);
- return $this->filterBySyliusAttributeCodes($akeneoAttributes);
+ return array_merge(
+ $this->filterBySyliusAttributeCodes($akeneoAttributes),
+ $this->filterSyliusOptionCodes($akeneoAttributes),
+ );
}
/**
@@ -97,21 +153,38 @@ private function filterBySyliusAttributeCodes(ResourceCursorInterface $akeneoAtt
return $attributeCodes;
}
- private function importAttribute(string $attributeCode, ProductAttributeInterface $attribute): void
+ /**
+ * Return the list of Akeneo attribute codes whose code is used as a code for a Sylius attribute
+ *
+ * @param ResourceCursorInterface $akeneoAttributes
+ *
+ * @return string[]
+ */
+ private function filterSyliusOptionCodes(ResourceCursorInterface $akeneoAttributes): array
{
- $attributeOptionsOrdered = [];
- /** @var ResourceCursorInterface $attributeOptions */
- $attributeOptions = $this->apiClient->getAttributeOptionApi()->all($attributeCode);
- foreach ($attributeOptions as $attributeOption) {
- $attributeOptionsOrdered[] = $attributeOption;
+ $productOptionRepository = $this->optionRepository;
+ if (!$productOptionRepository instanceof ProductOptionRepositoryInterface) {
+ return [];
}
- usort(
- $attributeOptionsOrdered,
- static fn (array $option1, array $option2): int => $option1['sort_order'] <=> $option2['sort_order'],
+ $akeneoAttributeCodes = [];
+ foreach ($akeneoAttributes as $akeneoAttribute) {
+ $akeneoAttributeCodes[] = $akeneoAttribute['code'];
+ }
+ $syliusOptions = $productOptionRepository->findByCodes($akeneoAttributeCodes);
+
+ return array_map(
+ static fn (ProductOptionInterface $option): string => (string) $option->getCode(),
+ $syliusOptions,
);
+ }
+
+ private function importAttributeConfiguration(string $attributeCode, ProductAttributeInterface $attribute): void
+ {
/** @var array{choices: array>, multiple: bool, min: ?int, max: ?int} $configuration */
$configuration = $attribute->getConfiguration();
- $configuration['choices'] = $this->convertAkeneoAttributeOptionsIntoSyliusChoices($attributeOptionsOrdered);
+ $configuration['choices'] = $this->convertAkeneoAttributeOptionsIntoSyliusChoices(
+ $this->getSortedAkeneoAttributeOptionsByAttributeCode($attributeCode),
+ );
$attribute->setConfiguration($configuration);
$this->attributeRepository->add($attribute);
@@ -126,9 +199,106 @@ private function convertAkeneoAttributeOptionsIntoSyliusChoices(array $attribute
{
$choices = [];
foreach ($attributeOptions as $attributeOption) {
- $choices[$attributeOption['code']] = $attributeOption['labels'];
+ $attributeOptionLabelsNotNull = array_filter(
+ $attributeOption['labels'],
+ static fn (?string $label): bool => $label !== null,
+ );
+ $choices[$attributeOption['code']] = $attributeOptionLabelsNotNull;
}
return $choices;
}
+
+ private function importOptionValues(string $attributeCode, ProductOptionInterface $option): void
+ {
+ $attributeOptions = $this->getSortedAkeneoAttributeOptionsByAttributeCode($attributeCode);
+
+ foreach ($attributeOptions as $attributeOption) {
+ $optionValueCode = $attributeCode . '_' . $attributeOption['code'];
+ $optionValue = null;
+ foreach ($option->getValues() as $value) {
+ if ($value->getCode() === $optionValueCode) {
+ $optionValue = $value;
+
+ break;
+ }
+ }
+ if ($optionValue === null) {
+ // We can assume that if we are here is because the option repository has been injected, so event this factory should be!
+ $productOptionValueFactory = $this->productOptionValueFactory;
+ Assert::isInstanceOf($productOptionValueFactory, FactoryInterface::class);
+ $optionValue = $productOptionValueFactory->createNew();
+ // TODO handle translations
+ $optionValue->setCode($optionValueCode);
+ $option->addValue($optionValue);
+ }
+
+ // We can assume that if we are here is because the option repository has been injected, so event these services should be!
+ $translationLocaleProvider = $this->translationLocaleProvider;
+ Assert::isInstanceOf($translationLocaleProvider, TranslationLocaleProviderInterface::class);
+ $definedLocalesCodes = $translationLocaleProvider->getDefinedLocalesCodes();
+
+ $productOptionValueTranslationFactory = $this->productOptionValueTranslationFactory;
+ Assert::isInstanceOf($productOptionValueTranslationFactory, FactoryInterface::class);
+
+ foreach ($attributeOption['labels'] as $localeCode => $label) {
+ if (!in_array($localeCode, $definedLocalesCodes, true)) {
+ continue;
+ }
+ $optionValueTranslation = $optionValue->getTranslation($localeCode);
+ if ($optionValueTranslation->getLocale() !== $localeCode) {
+ $optionValueTranslation = $productOptionValueTranslationFactory->createNew();
+ $optionValueTranslation->setLocale($localeCode);
+ }
+ $optionValueTranslation->setValue($label ?? $optionValue->getCode());
+ if (!$optionValue->hasTranslation($optionValueTranslation)) {
+ $optionValue->addTranslation($optionValueTranslation);
+ }
+ }
+ }
+ }
+
+ /**
+ * @return array
+ */
+ private function getSortedAkeneoAttributeOptionsByAttributeCode(string $attributeCode): array
+ {
+ $attributeOptionsOrdered = [];
+ /** @var ResourceCursorInterface $attributeOptions */
+ $attributeOptions = $this->apiClient->getAttributeOptionApi()->all($attributeCode);
+ foreach ($attributeOptions as $attributeOption) {
+ $attributeOptionsOrdered[] = $attributeOption;
+ }
+ usort(
+ $attributeOptionsOrdered,
+ static fn (array $option1, array $option2): int => $option1['sort_order'] <=> $option2['sort_order'],
+ );
+
+ return $attributeOptionsOrdered;
+ }
+
+ private function updateProductOption(ProductOptionInterface $productOption): void
+ {
+ // TODO: Update also the position of the option? The problem is that this position is on family variant entity!
+ $productOptionCode = $productOption->getCode();
+ Assert::notNull($productOptionCode);
+
+ // We can assume that if we are here is because the option repository has been injected, so event this factory should be!
+ $productOptionTranslationFactory = $this->productOptionTranslationFactory;
+ Assert::isInstanceOf($productOptionTranslationFactory, FactoryInterface::class);
+
+ $attributeResponse = $this->apiClient->getAttributeApi()->get($productOptionCode);
+ foreach ($attributeResponse['labels'] as $locale => $label) {
+ $productOptionTranslation = $productOption->getTranslation($locale);
+ if ($productOptionTranslation->getLocale() === $locale) {
+ $productOptionTranslation->setName($label);
+
+ continue;
+ }
+ $newProductOptionTranslation = $productOptionTranslationFactory->createNew();
+ $newProductOptionTranslation->setLocale($locale);
+ $newProductOptionTranslation->setName($label);
+ $productOption->addTranslation($newProductOptionTranslation);
+ }
+ }
}
diff --git a/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_retaining_sort_order.yaml b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_to_sylius_attribute_retaining_sort_order.yaml
similarity index 100%
rename from tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_retaining_sort_order.yaml
rename to tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_to_sylius_attribute_retaining_sort_order.yaml
diff --git a/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_to_sylius_option.yaml b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_to_sylius_option.yaml
new file mode 100644
index 00000000..c3c3b495
--- /dev/null
+++ b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_import_all_options_from_akeneo_to_sylius_option.yaml
@@ -0,0 +1,9 @@
+Sylius\Component\Locale\Model\Locale:
+ en_US:
+ code: "en_US"
+ it_IT:
+ code: "it_IT"
+
+Sylius\Component\Product\Model\ProductOption:
+ size:
+ code: 'size'
diff --git a/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes.yaml b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes_or_sylius_product_options.yaml
similarity index 71%
rename from tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes.yaml
rename to tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes_or_sylius_product_options.yaml
index d7467039..f57c393a 100644
--- a/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes.yaml
+++ b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes_or_sylius_product_options.yaml
@@ -5,7 +5,11 @@ Sylius\Component\Locale\Model\Locale:
code: "it_IT"
Sylius\Component\Product\Model\ProductAttribute:
- finitura:
+ material:
code: 'material'
type: 'select'
storageType: 'json'
+
+Sylius\Component\Product\Model\ProductOption:
+ size:
+ code: 'size'
diff --git a/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_updates_all_options_from_akeneo_to_sylius_option.yaml b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_updates_all_options_from_akeneo_to_sylius_option.yaml
new file mode 100644
index 00000000..7133fb57
--- /dev/null
+++ b/tests/DataFixtures/ORM/resources/Importer/AttributeOptions/it_updates_all_options_from_akeneo_to_sylius_option.yaml
@@ -0,0 +1,54 @@
+Sylius\Component\Locale\Model\Locale:
+ en_US:
+ code: 'en_US'
+ it_IT:
+ code: 'it_IT'
+
+Sylius\Component\Product\Model\ProductOption:
+ size:
+ code: 'size'
+ translations:
+ - '@size_en_US'
+ - '@size_it_IT'
+
+Sylius\Component\Product\Model\ProductOptionTranslation:
+ size_en_US:
+ name: 'Format'
+ locale: 'en_US'
+ translatable: '@size'
+ size_it_IT:
+ name: 'Formato'
+ locale: 'it_IT'
+ translatable: '@size'
+
+Sylius\Component\Product\Model\ProductOptionValue:
+ small:
+ code: 'size_small'
+ option: '@size'
+ translations:
+ - '@small_it_IT'
+ - '@small_en_US'
+ large:
+ code: 'size_large'
+ option: '@size'
+ translations:
+ - '@large_it_IT'
+ - '@large_en_US'
+
+Sylius\Component\Product\Model\ProductOptionValueTranslation:
+ small_it_IT:
+ value: 'S'
+ locale: 'it_IT'
+ translatable: '@small'
+ small_en_US:
+ value: 'S'
+ locale: 'en_US'
+ translatable: '@small'
+ large_it_IT:
+ value: 'L'
+ locale: 'it_IT'
+ translatable: '@large'
+ large_en_US:
+ value: 'L'
+ locale: 'en_US'
+ translatable: '@large'
diff --git a/tests/InMemory/Client/Api/InMemoryAttributeOptionApi.php b/tests/InMemory/Client/Api/InMemoryAttributeOptionApi.php
index fd484abf..3d1f65f4 100644
--- a/tests/InMemory/Client/Api/InMemoryAttributeOptionApi.php
+++ b/tests/InMemory/Client/Api/InMemoryAttributeOptionApi.php
@@ -62,7 +62,7 @@ public function __construct(private ArrayIterator $iterator, private int $pageSi
{
}
- public function current()
+ public function current(): mixed
{
return $this->iterator->current();
}
diff --git a/tests/Integration/AttributeOptions/ImporterTest.php b/tests/Integration/AttributeOptions/ImporterTest.php
index 6d0c7c13..99bc715c 100644
--- a/tests/Integration/AttributeOptions/ImporterTest.php
+++ b/tests/Integration/AttributeOptions/ImporterTest.php
@@ -7,6 +7,9 @@
use DateTime;
use Fidry\AliceDataFixtures\Persistence\PurgeMode;
use Sylius\Component\Product\Model\ProductAttributeInterface;
+use Sylius\Component\Product\Model\ProductOptionInterface;
+use Sylius\Component\Product\Model\ProductOptionValueInterface;
+use Sylius\Component\Product\Repository\ProductOptionRepositoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Tests\Webgriffe\SyliusAkeneoPlugin\DataFixtures\DataFixture;
@@ -23,15 +26,25 @@ final class ImporterTest extends KernelTestCase
private RepositoryInterface $attributeRepository;
+ private ProductOptionRepositoryInterface $optionRepository;
+
protected function setUp(): void
{
self::bootKernel();
$this->importer = self::getContainer()->get('webgriffe_sylius_akeneo.attribute_options.importer');
$fixtureLoader = self::getContainer()->get('fidry_alice_data_fixtures.loader.doctrine');
$this->attributeRepository = self::getContainer()->get('sylius.repository.product_attribute');
+ $this->optionRepository = self::getContainer()->get('sylius.repository.product_option');
InMemoryAttributeApi::addResource(new Attribute('material', AttributeType::SIMPLE_SELECT));
InMemoryAttributeApi::addResource(new Attribute('text_attribute', AttributeType::TEXT));
+ InMemoryAttributeApi::addResource(Attribute::create('size', [
+ 'type' => AttributeType::SIMPLE_SELECT,
+ 'labels' => [
+ 'en_US' => 'Size',
+ 'it_IT' => 'Taglia',
+ ],
+ ]));
InMemoryAttributeOptionApi::addResource(new AttributeOption('cotton', 'material', 5, [
'en_US' => 'cotton',
@@ -53,6 +66,14 @@ protected function setUp(): void
'en_US' => 'leather',
'it_IT' => 'cuoio',
]));
+ InMemoryAttributeOptionApi::addResource(new AttributeOption('small', 'size', 1, [
+ 'en_US' => 'Small',
+ 'it_IT' => 'Piccola',
+ ]));
+ InMemoryAttributeOptionApi::addResource(new AttributeOption('large', 'size', 2, [
+ 'en_US' => 'Large',
+ 'it_IT' => 'Grande',
+ ]));
$ORMResourceFixturePath = DataFixture::path . '/ORM/resources/Importer/AttributeOptions/' . $this->getName() . '.yaml';
if (file_exists($ORMResourceFixturePath)) {
@@ -92,7 +113,7 @@ public function it_does_nothing_if_attribute_is_not_a_select_attribute(): void
/**
* @test
*/
- public function it_import_all_options_from_akeneo_retaining_sort_order(): void
+ public function it_import_all_options_from_akeneo_to_sylius_attribute_retaining_sort_order(): void
{
$this->importer->import('material');
@@ -115,10 +136,72 @@ public function it_import_all_options_from_akeneo_retaining_sort_order(): void
/**
* @test
*/
- public function it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes(): void
+ public function it_import_all_options_from_akeneo_to_sylius_option(): void
+ {
+ $this->importer->import('size');
+
+ $option = $this->optionRepository->findOneBy(['code' => 'size']);
+ $this->assertInstanceOf(ProductOptionInterface::class, $option);
+ $this->assertEquals('Size', $option->getTranslation('en_US')->getName());
+ $this->assertEquals('Taglia', $option->getTranslation('it_IT')->getName());
+ $optionValues = $option->getValues();
+ $this->assertCount(2, $optionValues);
+
+ $smallOptionValues = $optionValues->filter(static fn (ProductOptionValueInterface $optionValue): bool => $optionValue->getCode() === 'size_small');
+ $this->assertCount(1, $smallOptionValues);
+ $smallOptionValue = $smallOptionValues->first();
+ $this->assertInstanceOf(ProductOptionValueInterface::class, $smallOptionValue);
+ $this->assertCount(2, $smallOptionValue->getTranslations());
+ $this->assertEquals('Small', $smallOptionValue->getTranslation('en_US')->getValue());
+ $this->assertEquals('Piccola', $smallOptionValue->getTranslation('it_IT')->getValue());
+
+ $smallOptionValues = $optionValues->filter(static fn (ProductOptionValueInterface $optionValue): bool => $optionValue->getCode() === 'size_large');
+ $this->assertCount(1, $smallOptionValues);
+ $smallOptionValue = $smallOptionValues->first();
+ $this->assertInstanceOf(ProductOptionValueInterface::class, $smallOptionValue);
+ $this->assertCount(2, $smallOptionValue->getTranslations());
+ $this->assertEquals('Large', $smallOptionValue->getTranslation('en_US')->getValue());
+ $this->assertEquals('Grande', $smallOptionValue->getTranslation('it_IT')->getValue());
+ }
+
+ /**
+ * @test
+ */
+ public function it_updates_all_options_from_akeneo_to_sylius_option(): void
+ {
+ $this->importer->import('size');
+
+ $option = $this->optionRepository->findOneBy(['code' => 'size']);
+ $this->assertInstanceOf(ProductOptionInterface::class, $option);
+ $this->assertEquals('Size', $option->getTranslation('en_US')->getName());
+ $this->assertEquals('Taglia', $option->getTranslation('it_IT')->getName());
+ $optionValues = $option->getValues();
+ $this->assertCount(2, $optionValues);
+
+ $smallOptionValues = $optionValues->filter(static fn (ProductOptionValueInterface $optionValue): bool => $optionValue->getCode() === 'size_small');
+ $this->assertCount(1, $smallOptionValues);
+ $smallOptionValue = $smallOptionValues->first();
+ $this->assertInstanceOf(ProductOptionValueInterface::class, $smallOptionValue);
+ $this->assertCount(2, $smallOptionValue->getTranslations());
+ $this->assertEquals('Small', $smallOptionValue->getTranslation('en_US')->getValue());
+ $this->assertEquals('Piccola', $smallOptionValue->getTranslation('it_IT')->getValue());
+
+ $smallOptionValues = $optionValues->filter(static fn (ProductOptionValueInterface $optionValue): bool => $optionValue->getCode() === 'size_large');
+ $this->assertCount(1, $smallOptionValues);
+ $smallOptionValue = $smallOptionValues->first();
+ $this->assertInstanceOf(ProductOptionValueInterface::class, $smallOptionValue);
+ $this->assertCount(2, $smallOptionValue->getTranslations());
+ $this->assertEquals('Large', $smallOptionValue->getTranslation('en_US')->getValue());
+ $this->assertEquals('Grande', $smallOptionValue->getTranslation('it_IT')->getValue());
+ }
+
+ /**
+ * @test
+ */
+ public function it_returns_all_simple_select_and_multiselect_attributes_identifiers_that_are_also_sylius_select_attributes_or_sylius_product_options(): void
{
$identifiers = $this->importer->getIdentifiersModifiedSince(new DateTime());
- $this->assertEquals(['material'], $identifiers);
+ $this->assertEquals(['material', 'size'], $identifiers);
}
}