diff --git a/composer.json b/composer.json index f374e9d..446e4a5 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "beberlei/porpaginas": "^1.0" }, "require-dev": { + "symfony/symfony": "~3.2, <3.3", "behat/behat": "^3.2", "behat/mink": "^1.7", "behat/mink-browserkit-driver": "^1.3", @@ -36,7 +37,8 @@ "php-http/guzzle6-adapter": "^1.1", "phpspec/phpspec": "^3.2", "phpunit/phpunit": "^5.6", - "behat/mink-selenium2-driver": "^1.3" + "behat/mink-selenium2-driver": "^1.3", + "lakion/api-test-case": "^1.1" }, "config": { "bin-dir": "bin" diff --git a/features/shop/product/searching/filtering_list_of_products_by_channel.feature b/features/shop/product/searching/filtering_list_of_products_by_channel.feature index 48b20de..2669e57 100644 --- a/features/shop/product/searching/filtering_list_of_products_by_channel.feature +++ b/features/shop/product/searching/filtering_list_of_products_by_channel.feature @@ -5,12 +5,12 @@ Feature: Filtering list of products by channels I want to be able to filter the products Background: - Given the store has a product "Banana T-Shirt" priced at "$100" in "tablets" channel - And the store also has a product "Star Wars T-Shirt" priced at "$150" in "mobile" channel - And the store also has a product "LOTR T-Shirt" priced at "$300" in "mobile" channel - And the store also has a product "Breaking Bad T-Shirt" priced at "$50" in "mobile" channel - And the store also has a product "Westworld T-Shirt" priced at "$1000" in "europe" channel - And the store also has a product "Orange T-Shirt" priced at "$1000" in "europe" channel + Given the store has a product "Banana T-Shirt" priced at "$100" in "Tablets" channel + And the store also has a product "Star Wars T-Shirt" priced at "$150" in "Mobile" channel + And the store also has a product "LOTR T-Shirt" priced at "$300" in "Mobile" channel + And the store also has a product "Breaking Bad T-Shirt" priced at "$50" in "Mobile" channel + And the store also has a product "Westworld T-Shirt" priced at "$1000" in "Europe" channel + And the store also has a product "Orange T-Shirt" priced at "$1000" in "Europe" channel @domain Scenario: Filtering products by mobile channel diff --git a/features/shop/product/searching/filtering_list_of_products_by_price_range_and_channel.feature b/features/shop/product/searching/filtering_list_of_products_by_price_range_and_channel.feature index acc18e1..7ccab93 100644 --- a/features/shop/product/searching/filtering_list_of_products_by_price_range_and_channel.feature +++ b/features/shop/product/searching/filtering_list_of_products_by_price_range_and_channel.feature @@ -5,12 +5,12 @@ Feature: Filtering list of products by channels and price I want to be able to filter the products Background: - Given the store has a product "Banana T-Shirt" priced at "$100" in "tablets" channel - And the store also has a product "Star Wars T-Shirt" priced at "$150" in "mobile" channel - And the store also has a product "LOTR T-Shirt" priced at "$300" in "mobile" channel - And the store also has a product "Breaking Bad T-Shirt" priced at "$50" in "mobile" channel - And the store also has a product "Westworld T-Shirt" priced at "$1000" in "europe" channel - And the store also has a product "Orange T-Shirt" priced at "$1000" in "europe" channel + Given the store has a product "Banana T-Shirt" priced at "$100" in "Tablets" channel + And the store also has a product "Star Wars T-Shirt" priced at "$150" in "Mobile" channel + And the store also has a product "LOTR T-Shirt" priced at "$300" in "Mobile" channel + And the store also has a product "Breaking Bad T-Shirt" priced at "$50" in "Mobile" channel + And the store also has a product "Westworld T-Shirt" priced at "$1000" in "Europe" channel + And the store also has a product "Orange T-Shirt" priced at "$1000" in "Europe" channel @domain Scenario: Filtering products by mobile channel and price range diff --git a/spec/Document/AttributeSpec.php b/spec/Document/AttributeSpec.php index d98c7b2..8f70a2d 100644 --- a/spec/Document/AttributeSpec.php +++ b/spec/Document/AttributeSpec.php @@ -2,7 +2,6 @@ namespace spec\Sylius\ElasticSearchPlugin\Document; -use ONGR\ElasticsearchBundle\Collection\Collection; use Sylius\ElasticSearchPlugin\Document\Attribute; use PhpSpec\ObjectBehavior; diff --git a/spec/Document/AttributeValueSpec.php b/spec/Document/AttributeValueSpec.php index 8ae2ca1..c3f3bab 100644 --- a/spec/Document/AttributeValueSpec.php +++ b/spec/Document/AttributeValueSpec.php @@ -5,7 +5,6 @@ use Sylius\ElasticSearchPlugin\Document\Attribute; use Sylius\ElasticSearchPlugin\Document\AttributeValue; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; final class AttributeValueSpec extends ObjectBehavior { @@ -28,11 +27,4 @@ function it_has_attribute() $this->getAttribute()->shouldReturn($attribute); } - - function it_has_code() - { - $this->setCode('red'); - - $this->getCode()->shouldReturn('red'); - } } diff --git a/spec/Document/ImageSpec.php b/spec/Document/ImageSpec.php new file mode 100644 index 0000000..7ace190 --- /dev/null +++ b/spec/Document/ImageSpec.php @@ -0,0 +1,28 @@ +shouldHaveType(Image::class); + } + + function it_has_code() + { + $this->setCode('abc'); + + $this->getCode()->shouldReturn('abc'); + } + + function it_has_path() + { + $this->setPath('/abc'); + + $this->getPath()->shouldReturn('/abc'); + } +} diff --git a/spec/Document/ProductSpec.php b/spec/Document/ProductSpec.php index 5124b3e..d5f4fef 100644 --- a/spec/Document/ProductSpec.php +++ b/spec/Document/ProductSpec.php @@ -6,7 +6,7 @@ use Sylius\ElasticSearchPlugin\Document\Price; use Sylius\ElasticSearchPlugin\Document\Product; use PhpSpec\ObjectBehavior; -use Sylius\ElasticSearchPlugin\Document\TaxonCode; +use Sylius\ElasticSearchPlugin\Document\Taxon; final class ProductSpec extends ObjectBehavior { @@ -58,20 +58,20 @@ function it_has_price() $this->getPrice()->shouldReturn($price); } - function it_has_main_taxon_code() + function it_has_main_taxon() { - $taxonCode = new TaxonCode(); - $this->setMainTaxonCode($taxonCode); + $taxon = new Taxon(); + $this->setMainTaxon($taxon); - $this->getMainTaxonCode()->shouldReturn($taxonCode); + $this->getMainTaxon()->shouldReturn($taxon); } - function it_has_taxon_codes() + function it_has_taxons() { - $taxonCodes = new Collection(); - $this->setTaxonCodes($taxonCodes); + $taxons = new Collection(); + $this->setTaxons($taxons); - $this->getTaxonCodes()->shouldReturn($taxonCodes); + $this->getTaxons()->shouldReturn($taxons); } function it_has_attributes() @@ -81,4 +81,19 @@ function it_has_attributes() $this->getAttributeValues()->shouldReturn($attributeValues); } + + function it_has_slug() + { + $this->setSlug('/mug'); + + $this->getSlug()->shouldReturn('/mug'); + } + + function it_has_images() + { + $images = new Collection(); + $this->setImages($images); + + $this->getImages()->shouldReturn($images); + } } diff --git a/spec/Document/TaxonCodeSpec.php b/spec/Document/TaxonCodeSpec.php deleted file mode 100644 index 83d0f65..0000000 --- a/spec/Document/TaxonCodeSpec.php +++ /dev/null @@ -1,22 +0,0 @@ -shouldHaveType(TaxonCode::class); - } - - function it_has_value() - { - $this->setValue('mug'); - - $this->getValue()->shouldReturn('mug'); - } -} diff --git a/spec/Document/TaxonSpec.php b/spec/Document/TaxonSpec.php new file mode 100644 index 0000000..65989a1 --- /dev/null +++ b/spec/Document/TaxonSpec.php @@ -0,0 +1,51 @@ +shouldHaveType(Taxon::class); + } + + function it_has_code() + { + $this->setCode('mug'); + + $this->getCode()->shouldReturn('mug'); + } + + function it_has_slug() + { + $this->setSlug('/mug'); + + $this->getSlug()->shouldReturn('/mug'); + } + + function it_has_position() + { + $this->setPosition(1); + + $this->getPosition()->shouldReturn(1); + } + + function it_has_images() + { + $images = new Collection(); + $this->setImages($images); + + $this->getImages()->shouldReturn($images); + } + + function it_has_description() + { + $this->setDescription('Lorem ipsum'); + + $this->getDescription()->shouldReturn('Lorem ipsum'); + } +} diff --git a/spec/EventListener/ProductPublisherSpec.php b/spec/EventListener/ProductPublisherSpec.php index 366ec20..668dc62 100644 --- a/spec/EventListener/ProductPublisherSpec.php +++ b/spec/EventListener/ProductPublisherSpec.php @@ -2,7 +2,9 @@ namespace spec\Sylius\ElasticSearchPlugin\EventListener; -use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\Event\OnFlushEventArgs; +use Doctrine\ORM\UnitOfWork; use SimpleBus\Message\Bus\MessageBus; use Sylius\Component\Core\Model\ProductInterface; use Sylius\ElasticSearchPlugin\Event\ProductCreated; @@ -22,35 +24,52 @@ function it_is_initializable() $this->shouldHaveType(ProductPublisher::class); } - function it_publishes_product_event(MessageBus $eventBus, LifecycleEventArgs $event, ProductInterface $product) - { + function it_publishes_product_event( + MessageBus $eventBus, + OnFlushEventArgs $event, + ProductInterface $product, + EntityManager $entityManager, + UnitOfWork $unitOfWork + ) { $product->isSimple()->willReturn(true); - $event->getEntity()->willReturn($product); + $event->getEntityManager()->willReturn($entityManager); + $entityManager->getUnitOfWork()->willReturn($unitOfWork); + $unitOfWork->getScheduledEntityInsertions()->willReturn([$product]); $eventBus->handle(ProductCreated::occur($product->getWrappedObject()))->shouldBeCalled(); - $this->postPersist($event); + $this->onFlush($event); } - function it_does_not_publish_product_event_if_entity_is_not_a_product(MessageBus $eventBus, LifecycleEventArgs $event) - { - $event->getEntity()->willReturn(new \stdClass()); + function it_does_not_publish_product_event_if_entity_is_not_a_product( + MessageBus $eventBus, + OnFlushEventArgs $event, + EntityManager $entityManager, + UnitOfWork $unitOfWork + ) { + $event->getEntityManager()->willReturn($entityManager); + $entityManager->getUnitOfWork()->willReturn($unitOfWork); + $unitOfWork->getScheduledEntityInsertions()->willReturn([new \stdClass()]); $eventBus->handle(Argument::any())->shouldNotBeCalled(); - $this->postPersist($event); + $this->onFlush($event); } function it_does_not_publish_product_event_if_entity_is_not_a_simple_product( MessageBus $eventBus, - LifecycleEventArgs $event, + OnFlushEventArgs $event, + EntityManager $entityManager, + UnitOfWork $unitOfWork, ProductInterface $product ) { + $event->getEntityManager()->willReturn($entityManager); + $entityManager->getUnitOfWork()->willReturn($unitOfWork); + $unitOfWork->getScheduledEntityInsertions()->willReturn([$product]); $product->isSimple()->willReturn(false); - $event->getEntity()->willReturn($product); $eventBus->handle(Argument::any())->shouldNotBeCalled(); - $this->postPersist($event); + $this->onFlush($event); } } diff --git a/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php b/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php index acba83f..ac3025b 100644 --- a/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php +++ b/spec/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactorySpec.php @@ -25,7 +25,7 @@ function it_is_query_factory() function it_creates_query() { - $this->create(['taxon_code' => 'mugs'])->shouldBeLike(new TermQuery('main_taxon_code.value', 'mugs')); + $this->create(['taxon_code' => 'mugs'])->shouldBeLike(new TermQuery('main_taxon.code', 'mugs')); } function it_cannot_create_query_if_there_is_no_required_parameters() diff --git a/src/Controller/ImageItemView.php b/src/Controller/ImageItemView.php new file mode 100644 index 0000000..10fe8aa --- /dev/null +++ b/src/Controller/ImageItemView.php @@ -0,0 +1,16 @@ +restViewHandler = $restViewHandler; $this->searchEngine = $searchEngine; + $this->productListViewFactory = $productListViewFactory; } /** @@ -60,8 +68,12 @@ public function __invoke(Request $request) $criteria = Criteria::fromQueryParameters(Product::class, $content); $result = $this->searchEngine->match($criteria); - $page = $result->take($criteria->paginating()->offset(), $criteria->paginating()->itemsPerPage()); - return $this->restViewHandler->handle(View::create($page, Response::HTTP_OK)); + return $this->restViewHandler->handle( + View::create( + $this->productListViewFactory->createFromSearchResultAndPaginating($result, $criteria->paginating()), + Response::HTTP_OK + ) + ); } } diff --git a/src/Controller/TaxonItemView.php b/src/Controller/TaxonItemView.php new file mode 100644 index 0000000..3be4b52 --- /dev/null +++ b/src/Controller/TaxonItemView.php @@ -0,0 +1,38 @@ +code; - } - - /** - * @param string $code - */ - public function setCode($code) - { - $this->code = $code; - } - /** * @return string */ diff --git a/src/Document/Image.php b/src/Document/Image.php new file mode 100644 index 0000000..5719109 --- /dev/null +++ b/src/Document/Image.php @@ -0,0 +1,57 @@ +code; + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * @param string $path + */ + public function setPath($path) + { + $this->path = $path; + } +} diff --git a/src/Document/Product.php b/src/Document/Product.php index eb435b3..32576ce 100644 --- a/src/Document/Product.php +++ b/src/Document/Product.php @@ -13,7 +13,7 @@ final class Product /** * @var string * - * @ElasticSearch\Id() + * @ElasticSearch\Property(type="keyword") */ private $code; @@ -34,6 +34,13 @@ final class Product */ private $name; + /** + * @var string + * + * @ElasticSearch\Property(type="keyword") + */ + private $slug; + /** * @var string * @@ -63,18 +70,18 @@ final class Product private $price; /** - * @var TaxonCode + * @var Taxon * - * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:TaxonCode") + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:Taxon") */ - private $mainTaxonCode; + private $mainTaxon; /** * @var Collection * - * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:TaxonCode", multiple=true) + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:Taxon", multiple=true) */ - private $taxonCodes; + private $taxons; /** * @var Collection @@ -83,6 +90,13 @@ final class Product */ private $attributeValues; + /** + * @var Collection + * + * @ElasticSearch\Embedded(class="SyliusElasticSearchPlugin:Image", multiple=true) + */ + private $images; + /** * @var \DateTime * @@ -93,7 +107,8 @@ final class Product public function __construct() { $this->attributeValues = new Collection(); - $this->taxonCodes = new Collection(); + $this->taxons = new Collection(); + $this->images = new Collection(); } /** @@ -128,6 +143,22 @@ public function setName($name) $this->name = $name; } + /** + * @return string + */ + public function getSlug() + { + return $this->slug; + } + + /** + * @param string $slug + */ + public function setSlug($slug) + { + $this->slug = $slug; + } + /** * @return string */ @@ -193,35 +224,35 @@ public function setPrice(Price $price) } /** - * @return TaxonCode + * @return Taxon */ - public function getMainTaxonCode() + public function getMainTaxon() { - return $this->mainTaxonCode; + return $this->mainTaxon; } /** - * @param TaxonCode $mainTaxonCode + * @param Taxon $mainTaxon */ - public function setMainTaxonCode(TaxonCode $mainTaxonCode) + public function setMainTaxon(Taxon $mainTaxon) { - $this->mainTaxonCode = $mainTaxonCode; + $this->mainTaxon = $mainTaxon; } /** * @return Collection */ - public function getTaxonCodes() + public function getTaxons() { - return $this->taxonCodes; + return $this->taxons; } /** - * @param Collection $taxonCodes + * @param Collection $taxons */ - public function setTaxonCodes(Collection $taxonCodes) + public function setTaxons(Collection $taxons) { - $this->taxonCodes = $taxonCodes; + $this->taxons = $taxons; } /** @@ -240,6 +271,22 @@ public function setAttributeValues(Collection $attributeValues) $this->attributeValues = $attributeValues; } + /** + * @return Collection + */ + public function getImages() + { + return $this->images; + } + + /** + * @param Collection $images + */ + public function setImages(Collection $images) + { + $this->images = $images; + } + /** * @return \DateTime */ diff --git a/src/Document/Taxon.php b/src/Document/Taxon.php new file mode 100644 index 0000000..2d27ae0 --- /dev/null +++ b/src/Document/Taxon.php @@ -0,0 +1,133 @@ +children = new Collection(); + $this->images = new Collection(); + } + + /** + * @return string + */ + public function getCode() + { + return $this->code; + } + + /** + * @param string $code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * @return string + */ + public function getSlug() + { + return $this->slug; + } + + /** + * @param string $slug + */ + public function setSlug($slug) + { + $this->slug = $slug; + } + + /** + * @return int + */ + public function getPosition() + { + return $this->position; + } + + /** + * @param int $position + */ + public function setPosition($position) + { + $this->position = $position; + } + + /** + * @return Collection + */ + public function getImages() + { + return $this->images; + } + + /** + * @param Collection $images + */ + public function setImages(Collection $images) + { + $this->images = $images; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $description + */ + public function setDescription($description) + { + $this->description = $description; + } +} diff --git a/src/Document/TaxonCode.php b/src/Document/TaxonCode.php deleted file mode 100644 index 744a16d..0000000 --- a/src/Document/TaxonCode.php +++ /dev/null @@ -1,34 +0,0 @@ -value = $value; - } - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } -} diff --git a/src/EventListener/ProductPublisher.php b/src/EventListener/ProductPublisher.php index 1fcc351..149ea14 100644 --- a/src/EventListener/ProductPublisher.php +++ b/src/EventListener/ProductPublisher.php @@ -2,7 +2,8 @@ namespace Sylius\ElasticSearchPlugin\EventListener; -use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\Event\OnFlushEventArgs; +use Doctrine\ORM\Event\PostFlushEventArgs; use SimpleBus\Message\Bus\MessageBus; use Sylius\Component\Core\Model\ProductInterface; use Sylius\ElasticSearchPlugin\Event\ProductCreated; @@ -23,14 +24,15 @@ public function __construct(MessageBus $eventBus) } /** - * @param LifecycleEventArgs $event + * @param OnFlushEventArgs $event */ - public function postPersist(LifecycleEventArgs $event) + public function onFlush(OnFlushEventArgs $event) { - $product = $event->getEntity(); - if ($product instanceof ProductInterface) { - if ($product->isSimple()) { - $this->eventBus->handle(ProductCreated::occur($product)); + $scheduledInsertions = $event->getEntityManager()->getUnitOfWork()->getScheduledEntityInsertions(); + + foreach ($scheduledInsertions as $entity) { + if ($entity instanceof ProductInterface && $entity->isSimple()) { + $this->eventBus->handle(ProductCreated::occur($entity)); } } } diff --git a/src/Exception/UnsupportedFactoryMethodException.php b/src/Exception/UnsupportedFactoryMethodException.php new file mode 100644 index 0000000..35154fc --- /dev/null +++ b/src/Exception/UnsupportedFactoryMethodException.php @@ -0,0 +1,11 @@ +isSimple()) { - throw new \InvalidArgumentException(sprintf( - 'Cannot create elastic search model from configurable product "%s" via this method.', - $syliusProduct->getCode() - )); + throw new UnsupportedFactoryMethodException( + __METHOD__, + sprintf( + 'Cannot create elastic search model from configurable product "%s".', + $syliusProduct->getCode() + ) + ); } /** @var ProductVariantInterface $productVariant */ @@ -46,7 +52,7 @@ public function createFromSyliusSimpleProductModel(ProductInterface $syliusProdu /** @var ProductTranslationInterface|TranslationInterface $productTranslation */ $productTranslation = $syliusProduct->getTranslation($locale->getCode()); - $channelPrice = $productVariant->getChannelPricingForChannel($channel); + $channelPrice = $this->getChannelPricingForChannelFromProductVariant($productVariant, $channel); $syliusProductAttributes = $syliusProduct->getAttributesByLocale( $locale->getCode(), $channel->getDefaultLocale()->getCode() @@ -55,33 +61,59 @@ public function createFromSyliusSimpleProductModel(ProductInterface $syliusProdu $product = new Product(); $price = new Price(); - $taxonCode = new TaxonCode(); - $taxonCode->setValue($syliusProduct->getMainTaxon()->getCode()); + $taxon = new Taxon(); + $taxon->setCode($syliusProduct->getMainTaxon()->getCode()); + $taxon->setSlug($syliusProduct->getMainTaxon()->getSlug()); + $taxon->setDescription($syliusProduct->getMainTaxon()->getDescription()); $price->setAmount($channelPrice->getPrice()); $price->setCurrency($channel->getBaseCurrency()->getCode()); $product->setLocaleCode($locale->getCode()); + $product->setSlug($productTranslation->getSlug()); $product->setName($productTranslation->getName()); $product->setDescription($productTranslation->getDescription()); $product->setChannelCode($channel->getCode()); $product->setPrice($price); $product->setCode($syliusProduct->getCode()); $product->setCreatedAt($syliusProduct->getCreatedAt()); - $product->setMainTaxonCode($taxonCode); + $product->setMainTaxon($taxon); - $productTaxonCodes = []; + $productImages = []; + $syliusProductImages = $syliusProduct->getImages(); + foreach ($syliusProductImages as $syliusProductImage) { + $productImage = new Image(); + $productImage->setPath($syliusProductImage->getPath()); + $productImage->setCode($syliusProductImage->getType()); + $productImages[] = $productImage; + } + $product->setImages(new Collection($productImages)); + + $productTaxons = []; foreach ($syliusProductTaxons as $syliusProductTaxon) { - $productTaxonCode = new TaxonCode(); - $productTaxonCode->setValue($syliusProductTaxon->getTaxon()->getCode()); - $productTaxonCodes[] = $productTaxonCode; + $productTaxon = new Taxon(); + $productTaxon->setCode($syliusProductTaxon->getTaxon()->getCode()); + $productTaxon->setSlug($syliusProductTaxon->getTaxon()->getSlug()); + $productTaxon->setPosition($syliusProductTaxon->getTaxon()->getPosition()); + $productTaxon->setDescription($syliusProductTaxon->getTaxon()->getDescription()); + + $productTaxonImages = []; + $syliusTaxonImages = $syliusProductTaxon->getTaxon()->getImages(); + foreach ($syliusTaxonImages as $syliusTaxonImage) { + $productTaxonImage = new Image(); + $productTaxonImage->setPath($syliusTaxonImage->getPath()); + $productTaxonImage->setCode($syliusTaxonImage->getType()); + $productTaxonImages[] = $productTaxonImage; + } + $productTaxon->setImages(new Collection($productTaxonImages)); + + $productTaxons[] = $productTaxon; } - $product->setTaxonCodes(new Collection($productTaxonCodes)); + $product->setTaxons(new Collection($productTaxons)); $productAttributeValues = []; foreach ($syliusProductAttributes as $syliusProductAttributeValue) { $productAttributeValue = new AttributeValue(); - $productAttributeValue->setCode($syliusProductAttributeValue->getCode()); $productAttributeValue->setValue($syliusProductAttributeValue->getValue()); $attribute = new Attribute(); @@ -96,4 +128,25 @@ public function createFromSyliusSimpleProductModel(ProductInterface $syliusProdu return $product; } + + /** + * @param ProductVariantInterface $productVariant + * @param ChannelInterface $channel + * + * @return ChannelPricingInterface|null + */ + private function getChannelPricingForChannelFromProductVariant( + ProductVariantInterface $productVariant, + ChannelInterface $channel + ) { + $channelPricings = $productVariant->getChannelPricings(); + + foreach ($channelPricings as $channelPricing) { + if ($channelPricing->getChannelCode() === $channel->getCode()) { + return $channelPricing; + } + } + + return null; + } } diff --git a/src/Factory/ProductListViewFactory.php b/src/Factory/ProductListViewFactory.php new file mode 100644 index 0000000..c2b33d0 --- /dev/null +++ b/src/Factory/ProductListViewFactory.php @@ -0,0 +1,97 @@ +fromArrayResult($result, $paginating); + } + + /** + * @param ArrayResult $result + * @param Paginating $paginating + * + * @return ProductListView + */ + private function fromArrayResult(ArrayResult $result, Paginating $paginating) + { + $partialResult = $result->take($paginating->offset(), $paginating->itemsPerPage()); + $productListView = new ProductListView(); + $productListView->page = $partialResult->getCurrentPage(); + $productListView->limit = $paginating->itemsPerPage(); + $productListView->total = $partialResult->totalCount(); + $productListView->pages = (int) ceil($partialResult->totalCount() / $paginating->itemsPerPage()); + foreach ($partialResult as $item) { + $productListItemView = new ProductListItemView(); + $productListItemView->images = $this->provideAttribute('images', $item, []); + $productListItemView->slug = $this->provideAttribute('slug', $item, null); + $productListItemView->name = $this->provideAttribute('name', $item, null); + $productListItemView->code = $this->provideAttribute('code', $item, null); + $productListItemView->taxons = $this->provideAttribute('taxons', $item, []); + $productListItemView->localeCode = $this->provideAttribute('locale_code', $item, null); + $productListItemView->channelCode = $this->provideAttribute('channel_code', $item, null); + $productListItemView->mainTaxon = $this->provideAttribute('main_taxon', $item, null); + + $productListItemView->attributes = $this->provideAttribute('attribute_values', $item, []); + + $priceView = new PriceView(); + $priceView->current = $this->provideAttribute( + 'amount', + $this->provideAttribute('price', $item, []), + null + ); + $priceView->currency = $this->provideAttribute( + 'currency', + $this->provideAttribute('price', $item, []), + null + ); + + $productVariantItemView = new ProductVariantItemView(); + $productVariantItemView->price = $priceView; + $productVariantItemView->code = $this->provideAttribute('code', $item, null); + $productVariantItemView->images = $this->provideAttribute('images', $item, []); + $productVariantItemView->name = $this->provideAttribute('name', $item, null); + + $productListItemView->variants = [$productVariantItemView]; + + $productListView->items[] = $productListItemView; + } + + return $productListView; + } + + /** + * @param string $key + * @param array $item + * @param string|array $default + * + * @return string|array + */ + private function provideAttribute($key, array $item, $default) + { + return isset($item[$key]) ? $item[$key] : $default; + } +} diff --git a/src/Factory/ProductListViewFactoryInterface.php b/src/Factory/ProductListViewFactoryInterface.php new file mode 100644 index 0000000..24d749f --- /dev/null +++ b/src/Factory/ProductListViewFactoryInterface.php @@ -0,0 +1,18 @@ + - + @@ -24,5 +24,7 @@ + + diff --git a/src/Resources/config/services/controller.xml b/src/Resources/config/services/controller.xml index abfbc3b..30f2a99 100644 --- a/src/Resources/config/services/controller.xml +++ b/src/Resources/config/services/controller.xml @@ -8,6 +8,7 @@ + diff --git a/src/Search/Elastic/Factory/Query/ProductInChannelQueryFactory.php b/src/Search/Elastic/Factory/Query/ProductInChannelQueryFactory.php index 2cee10b..8de034e 100644 --- a/src/Search/Elastic/Factory/Query/ProductInChannelQueryFactory.php +++ b/src/Search/Elastic/Factory/Query/ProductInChannelQueryFactory.php @@ -20,6 +20,6 @@ public function create(array $parameters = []) throw new MissingQueryParameterException('channel_code', get_class($this)); } - return new TermQuery('channel_code', strtolower($parameters['channel_code'])); + return new TermQuery('channel_code', $parameters['channel_code']); } } diff --git a/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php b/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php index 326348a..46dbbc3 100644 --- a/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php +++ b/src/Search/Elastic/Factory/Query/ProductInMainTaxonQueryFactory.php @@ -19,6 +19,6 @@ public function create(array $parameters = []) throw new MissingQueryParameterException('taxon_code', get_class($this)); } - return new TermQuery('main_taxon_code.value', strtolower($parameters['taxon_code'])); + return new TermQuery('main_taxon.code', $parameters['taxon_code']); } } diff --git a/tests/Application/app/config/config.yml b/tests/Application/app/config/config.yml index 7d13272..4db993d 100644 --- a/tests/Application/app/config/config.yml +++ b/tests/Application/app/config/config.yml @@ -1,5 +1,5 @@ parameters: - locale: "en_US" + locale: "en_GB" secret: "Three can keep a secret, if two of them are dead." imports: @@ -24,6 +24,7 @@ framework: default_locale: "%locale%" trusted_proxies: ~ session: + storage_id: session.storage.mock_file handler_id: ~ test: ~ diff --git a/tests/Behat/Context/Setup/ProductContext.php b/tests/Behat/Context/Setup/ProductContext.php index 6c5512a..dbf8e9e 100644 --- a/tests/Behat/Context/Setup/ProductContext.php +++ b/tests/Behat/Context/Setup/ProductContext.php @@ -16,7 +16,7 @@ use ONGR\ElasticsearchBundle\Service\Manager; use Sylius\ElasticSearchPlugin\Document\Price; use Sylius\ElasticSearchPlugin\Document\Product; -use Sylius\ElasticSearchPlugin\Document\TaxonCode; +use Sylius\ElasticSearchPlugin\Document\Taxon; final class ProductContext implements Context { @@ -38,18 +38,18 @@ public function __construct(Manager $manager) */ public function theStoreHasAboutMugsAndStickers($mugsNumber, $stickersNumber, $booksNumber) { - $mugsTaxonCode = new TaxonCode(); - $mugsTaxonCode->setValue('mugs'); + $mugsTaxon = new Taxon(); + $mugsTaxon->setCode('mugs'); - $stickersTaxonCode = new TaxonCode(); - $stickersTaxonCode->setValue('stickers'); + $stickersTaxon = new Taxon(); + $stickersTaxon->setCode('stickers'); - $booksTaxonCode = new TaxonCode(); - $booksTaxonCode->setValue('books'); + $booksTaxon = new Taxon(); + $booksTaxon->setCode('books'); - $this->generateProductsInTaxon($mugsNumber, $mugsTaxonCode); - $this->generateProductsInTaxon($stickersNumber, $stickersTaxonCode); - $this->generateProductsInTaxon($booksNumber, $booksTaxonCode); + $this->generateProductsInTaxon($mugsNumber, $mugsTaxon); + $this->generateProductsInTaxon($stickersNumber, $stickersTaxon); + $this->generateProductsInTaxon($booksNumber, $booksTaxon); } /** @@ -67,13 +67,13 @@ public function storeHasAProductPricedAt($productName, $price = 100, $channelCod /** * @param int $howMany - * @param TaxonCode $taxonCode + * @param Taxon $taxonCode */ - private function generateProductsInTaxon($howMany, TaxonCode $taxonCode) + private function generateProductsInTaxon($howMany, Taxon $taxonCode) { for ($i = 0; $i < $howMany; $i++) { $product = new Product(); - $product->setMainTaxonCode($taxonCode); + $product->setMainTaxon($taxonCode); $product->setCode(uniqid()); $this->manager->persist($product); } diff --git a/tests/Controller/SearchControllerApiTest.php b/tests/Controller/SearchControllerApiTest.php new file mode 100644 index 0000000..702d530 --- /dev/null +++ b/tests/Controller/SearchControllerApiTest.php @@ -0,0 +1,62 @@ +loadFixturesFromFile('shop.yml'); + + $this->client->request('GET', '/shop-api/products', [], [], ['ACCEPT' => 'application/json'], '{}'); + + $response = $this->client->getResponse(); + + $this->assertResponse($response, 'product_list_page', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_shows_paginated_product_list_by_mugs() + { + $this->loadFixturesFromFile('shop.yml'); + + $this->client->request('GET', '/shop-api/products', [], [], ['ACCEPT' => 'application/json'], '{ "taxon_code": "MUG" }'); + + $response = $this->client->getResponse(); + + $this->assertResponse($response, 'mugs_list_page', Response::HTTP_OK); + } + + /** + * @test + */ + public function it_shows_paginated_product_list_by_en_gb_channel() + { + $this->loadFixturesFromFile('shop.yml'); + + $this->client->request('GET', '/shop-api/products', [], [], ['ACCEPT' => 'application/json'], '{ "channel_code": "WEB_GB" }'); + + $response = $this->client->getResponse(); + + $this->assertResponse($response, 'product_list_page_by_en_gb_channel', Response::HTTP_OK); + } + + /** + * @before + */ + protected function purgeElasticSearch() + { + $elasticSearchManager = static::$sharedKernel->getContainer()->get('es.manager.default'); + $elasticSearchManager->dropAndCreateIndex(); + } +} diff --git a/tests/DataFixtures/ORM/shop.yml b/tests/DataFixtures/ORM/shop.yml new file mode 100644 index 0000000..1235d40 --- /dev/null +++ b/tests/DataFixtures/ORM/shop.yml @@ -0,0 +1,327 @@ +Sylius\Component\Core\Model\Channel: + gb_web_channel: + code: "WEB_GB" + name: "Great Britain Channel" + hostname: "localhost" + description: "Lorem ipsum" + baseCurrency: "@pound" + defaultLocale: "@locale_en_gb" + locales: ["@locale_en_gb", "@locale_de_de"] + color: "black" + enabled: true + taxCalculationStrategy: "order_items_based" + de_web_channel: + code: "WEB_DE" + name: "Deutch Channel" + hostname: "localhost" + description: "Lorem ipsum" + baseCurrency: "@euro" + defaultLocale: "@locale_de_de" + locales: ["@locale_de_de"] + color: "blue" + enabled: true + taxCalculationStrategy: "order_items_based" + +Sylius\Component\Currency\Model\Currency: + pound: + code: GBP + euro: + code: EUR + +Sylius\Component\Locale\Model\Locale: + locale_en_gb: + code: en_GB + locale_de_de: + code: de_DE + +Sylius\Component\Core\Model\Product: + mug: + code: "LOGAN_MUG_CODE" + channels: ["@gb_web_channel"] + currentLocale: "en_GB" + currentTranslation: "@en_gb_mug_product_translation" + translations: ["@en_gb_mug_product_translation", "@de_de_mug_product_translation"] + mainTaxon: "@mug_taxon" + productTaxons: ["@mug_product_taxon"] + attributes: + - "@en_gb_mug_holiday_collection_value" + - "@de_de_mug_holiday_collection_value" + - "@en_gb_mug_holiday_material_value" + - "@de_de_mug_holiday_material_value" + variants: ["@mug_variant"] + t_shirt: + code: "LOGAN_T_SHIRT_CODE" + channels: ["@gb_web_channel"] + currentLocale: "en_GB" + currentTranslation: "@t_shirt_translation" + mainTaxon: "@t_shirt_taxon" + productTaxons: ["@t_shirt_product_taxon"] + variants: ["@t_shirt_small"] + +Sylius\Component\Core\Model\ProductTranslation: + en_gb_mug_product_translation: + slug: "logan-mug" + locale: "en_GB" + name: "Logan Mug" + description: + translatable: "@mug" + de_de_mug_product_translation: + slug: "logan-becher" + locale: "de_DE" + name: "Logan Becher" + description: + translatable: "@mug" + t_shirt_translation: + slug: "logan-t-shirt" + locale: "en_GB" + name: "Logan T-Shirt" + description: + translatable: "@t_shirt" + +Sylius\Component\Core\Model\ProductVariant: + mug_variant: + code: "LOGAN_MUG_CODE" + product: "@mug" + currentLocale: "en_GB" + currentTranslation: "@en_gb_mug_variant_translation" + translations: ["@en_gb_mug_variant_translation", "@de_de_mug_variant_translation"] + channelPricings: + WEB_GB: "@gb_mug_web_channel_pricing" + t_shirt_small: + code: "SMALL_LOGAN_T_SHIRT_CODE" + product: "@t_shirt" + currentLocale: "en_GB" + currentTranslation: "@small_t_shirt_translation" + channelPricings: + WEB_GB: "@gb_small_t_shirt_web_channel_pricing" + +Sylius\Component\Product\Model\ProductVariantTranslation: + en_gb_mug_variant_translation: + locale: "en_GB" + name: "Logan Mug" + translatable: "@mug_variant" + de_de_mug_variant_translation: + locale: "de_DE" + name: "Logan Becher" + translatable: "@mug_variant" + small_t_shirt_translation: + locale: "en_GB" + name: "Small Logan T-Shirt" + translatable: "@t_shirt_small" + +Sylius\Component\Core\Model\ChannelPricing: + gb_mug_web_channel_pricing: + channelCode: "WEB_GB" + price: 1999 + gb_small_t_shirt_web_channel_pricing: + channelCode: "WEB_GB" + price: 1999 + +Sylius\Component\Core\Model\Taxon: + category_taxon: + code: "CATEGORY" + currentLocale: "en_GB" + currentTranslation: "@en_gb_category_translation" + translations: ["@en_gb_category_translation", "@de_de_category_translation"] + children: ["@mug_taxon", "@hat_taxon", "@t_shirt_taxon"] + mug_taxon: + code: "MUG" + currentLocale: "en_GB" + currentTranslation: "@en_gb_mug_taxon_translation" + translations: ["@en_gb_mug_taxon_translation", "@de_de_mug_taxon_translation"] + parent: "@category_taxon" + root: "@category_taxon" + hat_taxon: + code: "HAT" + currentLocale: "en_GB" + currentTranslation: "@en_gb_hat_translation" + translations: ["@en_gb_hat_translation", "@de_de_hat_translation"] + parent: "@category_taxon" + root: "@category_taxon" + t_shirt_taxon: + code: "T_SHIRTS" + currentLocale: "en_GB" + currentTranslation: "@en_gb_t_shirt_taxon_translation" + translations: ["@en_gb_t_shirt_taxon_translation", "@de_de_t_shirt_taxon_translation"] + children: ["@men_t_shirt_taxon", "@women_t_shirt_taxon"] + parent: "@category_taxon" + root: "@category_taxon" + men_t_shirt_taxon: + code: "MEN_T_SHIRTS" + currentLocale: "en_GB" + currentTranslation: "@en_gb_men_t_shirt_translation" + translations: ["@en_gb_men_t_shirt_translation", "@de_de_men_t_shirt_translation"] + parent: "@t_shirt_taxon" + root: "@category_taxon" + women_t_shirt_taxon: + code: "WOMEN_T_SHIRTS" + currentLocale: "en_GB" + currentTranslation: "@en_gb_women_t_shirt_translation" + translations: ["@en_gb_women_t_shirt_translation", "@de_de_women_t_shirt_translation"] + parent: "@t_shirt_taxon" + root: "@category_taxon" + brand_taxon: + code: "BRAND" + currentLocale: "en_GB" + currentTranslation: "@en_gb_brand_translation" + translations: ["@en_gb_brand_translation", "@de_de_brand_translation"] + +Sylius\Component\Taxonomy\Model\TaxonTranslation: + en_gb_category_translation: + slug: "categories" + locale: "en_GB" + name: "Categories" + description: + translatable: "@category_taxon" + en_gb_mug_taxon_translation: + slug: "mugs" + locale: "en_GB" + name: "Mugs" + description: + translatable: "@mug_taxon" + en_gb_hat_translation: + slug: "hats" + locale: "en_GB" + name: "Hats" + description: + translatable: "@hat_taxon" + en_gb_t_shirt_taxon_translation: + slug: "t-shirts" + locale: "en_GB" + name: "T-Shirts" + description: + translatable: "@t_shirt_taxon" + en_gb_men_t_shirt_translation: + slug: "men-t-shirts" + locale: "en_GB" + name: "Men T-Shirts" + description: + translatable: "@men_t_shirt_taxon" + en_gb_women_t_shirt_translation: + slug: "women-t-shirts" + locale: "en_GB" + name: "Women T-Shirts" + description: + translatable: "@women_t_shirt_taxon" + en_gb_brand_translation: + slug: "brands" + locale: "en_GB" + name: "Brands" + description: + translatable: "@brand_taxon" + de_de_category_translation: + slug: "kategorien" + locale: "de_DE" + name: "Kategorien" + description: + translatable: "@category_taxon" + de_de_mug_taxon_translation: + slug: "tassen" + locale: "de_DE" + name: "Tassen" + description: + translatable: "@mug_taxon" + de_de_hat_translation: + slug: "hute" + locale: "de_DE" + name: "Hüte" + description: + translatable: "@hat_taxon" + de_de_t_shirt_taxon_translation: + slug: "t-shirts" + locale: "de_DE" + name: "T-Shirts" + description: + translatable: "@t_shirt_taxon" + de_de_men_t_shirt_translation: + slug: "männer-t-shirts" + locale: "de_DE" + name: "Männer T-Shirts" + description: + translatable: "@men_t_shirt_taxon" + de_de_women_t_shirt_translation: + slug: "frauen-t-shirts" + locale: "de_DE" + name: "Frauen T-Shirts" + description: + translatable: "@women_t_shirt_taxon" + de_de_brand_translation: + slug: "marken" + locale: "de_DE" + name: "Marken" + description: + translatable: "@brand_taxon" + +Sylius\Component\Core\Model\ProductTaxon: + mug_product_taxon: + product: "@mug" + taxon: "@mug_taxon" + t_shirt_product_taxon: + product: "@t_shirt" + taxon: "@t_shirt_taxon" + mug_brand_taxon: + product: "@mug" + taxon: "@brand_taxon" + t_shirt_brand_taxon: + product: "@t_shirt" + taxon: "@brand_taxon" + +Sylius\Component\Product\Model\ProductAttributeTranslation: + mug_collection_de_de_translation: + locale: "de_DE" + name: "Becher Sammlung" + translatable: "@mug_collection" + mug_material_de_de_translation: + locale: "de_DE" + name: "Becher Material" + translatable: "@mug_material" + mug_collection_en_gb_translation: + locale: "en_GB" + name: "Mug collection" + translatable: "@mug_collection" + mug_material_en_gb_translation: + locale: "en_GB" + name: "Mug material" + translatable: "@mug_material" + +Sylius\Component\Product\Model\ProductAttribute: + mug_collection: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "MUG_COLLECTION_CODE" + type: "text" + storage_type: "text" + translations: + - "@mug_collection_en_gb_translation" + - "@mug_collection_de_de_translation" + mug_material: + fallbackLocale: "en_GB" + currentLocale: "en_GB" + code: "MUG_MATERIAL_CODE" + type: "text" + storage_type: "text" + translations: + - "@mug_material_en_gb_translation" + - "@mug_material_de_de_translation" + +Sylius\Component\Product\Model\ProductAttributeValue: + en_gb_mug_holiday_collection_value: + subject: "@mug" + attribute: "@mug_collection" + localeCode: "en_GB" + text: "HOLIDAY COLLECTION" + de_de_mug_holiday_collection_value: + subject: "@mug" + attribute: "@mug_collection" + localeCode: "de_DE" + text: "FEIERTAGSKOLLEKTION" + en_gb_mug_holiday_material_value: + subject: "@mug" + attribute: "@mug_material" + localeCode: "en_GB" + text: "Wood" + de_de_mug_holiday_material_value: + subject: "@mug" + attribute: "@mug_material" + localeCode: "de_DE" + text: "Holz" diff --git a/tests/Factory/ProductFactoryTest.php b/tests/Factory/ProductFactoryTest.php index f0b2668..b2f30fd 100644 --- a/tests/Factory/ProductFactoryTest.php +++ b/tests/Factory/ProductFactoryTest.php @@ -9,7 +9,7 @@ use Sylius\Component\Core\Model\Product as SyliusProduct; use Sylius\Component\Core\Model\ProductTaxon; use Sylius\Component\Core\Model\ProductVariant; -use Sylius\Component\Core\Model\Taxon; +use Sylius\Component\Core\Model\Taxon as SyliusTaxon; use Sylius\Component\Currency\Model\Currency; use Sylius\Component\Locale\Model\Locale; use Sylius\Component\Product\Model\ProductAttribute; @@ -17,7 +17,8 @@ use Sylius\ElasticSearchPlugin\Document\Attribute; use Sylius\ElasticSearchPlugin\Document\AttributeValue; use Sylius\ElasticSearchPlugin\Document\Product; -use Sylius\ElasticSearchPlugin\Document\TaxonCode; +use Sylius\ElasticSearchPlugin\Document\Taxon; +use Sylius\ElasticSearchPlugin\Exception\UnsupportedFactoryMethodException; use Sylius\ElasticSearchPlugin\Factory\ProductFactory; final class ProductFactoryTest extends \PHPUnit_Framework_TestCase @@ -34,12 +35,12 @@ public function it_creates_new_empty_product_document() $this->assertEquals(null, $product->getCode()); $this->assertEquals(null, $product->getName()); $this->assertEquals(null, $product->getLocaleCode()); - $this->assertEquals(new Collection, $product->getAttributeValues()); + $this->assertEquals(new Collection(), $product->getAttributeValues()); $this->assertEquals(null, $product->getPrice()); $this->assertEquals(null, $product->getChannelCode()); $this->assertEquals(null, $product->getCreatedAt()); $this->assertEquals(null, $product->getDescription()); - $this->assertEquals(new Collection, $product->getTaxonCodes()); + $this->assertEquals(new Collection(), $product->getTaxons()); } /** @@ -59,8 +60,11 @@ public function it_creates_product_document_from_sylius_product_model() $syliusProductAttributeValue->setAttribute($syliusProductAttribute); $syliusProductAttributeValue->setValue('red'); - $syliusTaxon = new Taxon(); + $syliusTaxon = new SyliusTaxon(); + $syliusTaxon->setCurrentLocale('en_US'); $syliusTaxon->setCode('tree'); + $syliusTaxon->setSlug('/tree'); + $syliusTaxon->setDescription('Lorem ipsum'); $syliusProductTaxon = new ProductTaxon(); $syliusLocale = new Locale(); @@ -92,6 +96,7 @@ public function it_creates_product_document_from_sylius_product_model() $syliusProduct->setCreatedAt($createdAt); $syliusProduct->setCurrentLocale('en_US'); $syliusProduct->setName('Banana'); + $syliusProduct->setSlug('/banana'); $syliusProduct->setDescription('Lorem ipsum'); $syliusProduct->setCode('banana'); $syliusProduct->addAttribute($syliusProductAttributeValue); @@ -104,11 +109,17 @@ public function it_creates_product_document_from_sylius_product_model() $syliusChannel ); - $taxonCode = new TaxonCode(); - $taxonCode->setValue('tree'); + $taxon = new Taxon(); + $taxon->setCode('tree'); + $taxon->setPosition(0); + $taxon->setSlug('/tree'); + $taxon->setDescription('Lorem ipsum'); - $productTaxonCode = new TaxonCode(); - $productTaxonCode->setValue('tree'); + $productTaxon = new Taxon(); + $productTaxon->setCode('tree'); + $productTaxon->setSlug('/tree'); + $productTaxon->setPosition(0); + $productTaxon->setDescription('Lorem ipsum'); $productAttribute = new Attribute(); $productAttribute->setCode('red'); @@ -116,7 +127,6 @@ public function it_creates_product_document_from_sylius_product_model() $productAttributeValue = new AttributeValue(); $productAttributeValue->setValue('red'); - $productAttributeValue->setCode('red'); $productAttributeValue->setAttribute($productAttribute); $this->assertEquals('banana', $product->getCode()); @@ -132,19 +142,20 @@ public function it_creates_product_document_from_sylius_product_model() $this->assertEquals('USD', $product->getPrice()->getCurrency()); $this->assertEquals('en_US', $product->getLocaleCode()); $this->assertEquals('mobile', $product->getChannelCode()); + $this->assertEquals('/banana', $product->getSlug()); + $this->assertEquals('Banana', $product->getName()); $this->assertEquals($createdAt, $product->getCreatedAt()); $this->assertEquals('Lorem ipsum', $product->getDescription()); - $this->assertEquals($taxonCode, $product->getMainTaxonCode()); - $this->assertEquals(new Collection([$productTaxonCode]), $product->getTaxonCodes()); + $this->assertEquals($taxon, $product->getMainTaxon()); + $this->assertEquals(new Collection([$productTaxon]), $product->getTaxons()); } /** * @test - * - * @expectedException \InvalidArgumentException */ public function it_cannot_create_product_document_from_configurable_product() { + $this->expectException(UnsupportedFactoryMethodException::class); $factory = new ProductFactory(); $syliusProduct = new SyliusProduct(); diff --git a/tests/Responses/Expected/mugs_list_page.json b/tests/Responses/Expected/mugs_list_page.json new file mode 100644 index 0000000..39e9fa6 --- /dev/null +++ b/tests/Responses/Expected/mugs_list_page.json @@ -0,0 +1,108 @@ +{ + "page": 1, + "limit": 10, + "total": 2, + "pages": 1, + "items": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "slug": "logan-becher", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "FEIERTAGSKOLLEKTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Holz", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "slug": "logan-mug", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "HOLIDAY COLLECTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Wood", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + } + ] +} diff --git a/tests/Responses/Expected/product_list_page.json b/tests/Responses/Expected/product_list_page.json new file mode 100644 index 0000000..dbf80fd --- /dev/null +++ b/tests/Responses/Expected/product_list_page.json @@ -0,0 +1,175 @@ +{ + "page": 1, + "limit": 10, + "total": 4, + "pages": 1, + "items": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "slug": "logan-becher", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "FEIERTAGSKOLLEKTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Holz", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "slug": "logan-mug", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "HOLIDAY COLLECTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Wood", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", + "slug": "logan-t-shirt", + "taxons": [ + { + "code": "T_SHIRTS", + "slug": "t-shirts", + "position": 2, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "T_SHIRTS", + "slug": "t-shirts", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_T_SHIRT_CODE", + "taxons": [ + { + "code": "T_SHIRTS", + "slug": "t-shirts", + "position": 2, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_T_SHIRT_CODE", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "T_SHIRTS", + "slug": "t-shirts", + "images": [], + "description": "@string@" + } + } + ] +} diff --git a/tests/Responses/Expected/product_list_page_by_en_gb_channel.json b/tests/Responses/Expected/product_list_page_by_en_gb_channel.json new file mode 100644 index 0000000..dbf80fd --- /dev/null +++ b/tests/Responses/Expected/product_list_page_by_en_gb_channel.json @@ -0,0 +1,175 @@ +{ + "page": 1, + "limit": 10, + "total": 4, + "pages": 1, + "items": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "slug": "logan-becher", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Becher", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "FEIERTAGSKOLLEKTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Holz", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "slug": "logan-mug", + "taxons": [ + { + "code": "MUG", + "slug": "mugs", + "position": 0, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_MUG_CODE", + "name": "Logan Mug", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [ + { + "value": "HOLIDAY COLLECTION", + "attribute": { + "code": "MUG_COLLECTION_CODE", + "name": "Mug collection" + } + }, + { + "value": "Wood", + "attribute": { + "code": "MUG_MATERIAL_CODE", + "name": "Mug material" + } + } + ], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "MUG", + "slug": "mugs", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", + "slug": "logan-t-shirt", + "taxons": [ + { + "code": "T_SHIRTS", + "slug": "t-shirts", + "position": 2, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_T_SHIRT_CODE", + "name": "Logan T-Shirt", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "en_GB", + "mainTaxon": { + "code": "T_SHIRTS", + "slug": "t-shirts", + "images": [], + "description": "@string@" + } + }, + { + "code": "LOGAN_T_SHIRT_CODE", + "taxons": [ + { + "code": "T_SHIRTS", + "slug": "t-shirts", + "position": 2, + "images": [], + "description": "@string@" + } + ], + "variants": [ + { + "code": "LOGAN_T_SHIRT_CODE", + "price": { + "current": 1999, + "currency": "GBP" + }, + "images": [] + } + ], + "attributes": [], + "images": [], + "channelCode": "WEB_GB", + "localeCode": "de_DE", + "mainTaxon": { + "code": "T_SHIRTS", + "slug": "t-shirts", + "images": [], + "description": "@string@" + } + } + ] +}