diff --git a/Test/Integration/Frontend/Insights/EventsTest.php b/Test/Integration/Frontend/Insights/EventsTest.php new file mode 100644 index 000000000..ae01ac717 --- /dev/null +++ b/Test/Integration/Frontend/Insights/EventsTest.php @@ -0,0 +1,206 @@ +objectManager = Bootstrap::getObjectManager(); + + $this->cartManagement = $this->objectManager->get(GuestCartManagementInterface::class); + $this->checkoutSession = $this->objectManager->get(CheckoutSession::class); + $this->quoteIdMaskFactory = $this->objectManager->get(QuoteIdMaskFactory::class); + $this->eventProcessor = $this->objectManager->get(EventProcessor::class); + + /** @var StoreManager $storeManager */ + $this->storeManager = $this->objectManager->get(StoreManager::class); + + $this->insightsClient = $this->getMockBuilder(InsightsClient::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->eventProcessor->setInsightsClient($this->insightsClient); + $this->eventProcessor->setAnonymousUserToken(self::TOKEN); + $this->eventProcessor->setStoreManager($this->storeManager); + } + + /** + * @param Order $order + * @param bool $withQueryID + * @param string $eventName + * @return array[] + */ + protected function generateConversionEvent(Order $order, bool $withQueryID = true, string $eventName = self::PLACED_ORDER_EVENT): array + { + $event = [ + EventProcessorInterface::EVENT_KEY_SUBTYPE => self::EVENT_SUBTYPE_PURCHASE, + EventProcessorInterface::EVENT_KEY_OBJECT_IDS => [], + EventProcessorInterface::EVENT_KEY_OBJECT_DATA => [], + EventProcessorInterface::EVENT_KEY_CURRENCY => 'USD', + EventProcessorInterface::EVENT_KEY_VALUE => 0, + 'eventType' => self::EVENT_TYPE_CONVERSION, + 'eventName' => $eventName, + 'index' => self::INDEX, + 'userToken' => self::TOKEN, + ]; + + if ($withQueryID) { + $event[EventProcessorInterface::EVENT_KEY_QUERY_ID] = ''; + } + + foreach ($order->getItems() as $item) { + $event[EventProcessorInterface::EVENT_KEY_OBJECT_IDS][] = $item->getProductId(); + $event[EventProcessorInterface::EVENT_KEY_OBJECT_DATA][] = [ + 'price' => $item->getPrice(), + 'discount' => $item->getDiscountAmount(), + 'quantity' => $item->getQtyOrdered() + ]; + $event[EventProcessorInterface::EVENT_KEY_VALUE] += $item->getPrice() * $item->getQtyOrdered(); + } + + return ['events' => [$event]]; + } + + /** + * @param Order $order + * @param bool $withQueryID + * @return void + */ + protected function assertOrderPurchaseEvent(Order $order, bool $withQueryID = true): void + { + $args = [$this->generateConversionEvent($order, $withQueryID), []]; + + $this->insightsClient + ->expects(self::once()) + ->method('pushEvents') + ->with(...$args) + ->willReturn([]); + + $this->eventProcessor->convertPurchase( + self::PLACED_ORDER_EVENT, + self::INDEX, + $order + ); + } + + /** + * Gets order entity by increment id. + * + * @param string $incrementId + * @return OrderInterface + */ + protected function getOrder(string $incrementId): OrderInterface + { + /** @var SearchCriteriaBuilder $searchCriteriaBuilder */ + $searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class); + $searchCriteria = $searchCriteriaBuilder->addFilter('increment_id', $incrementId) + ->create(); + + /** @var OrderRepositoryInterface $repository */ + $repository = $this->objectManager->get(OrderRepositoryInterface::class); + $items = $repository->getList($searchCriteria) + ->getItems(); + + return array_pop($items); + } + + /** + * @magentoDataFixture Magento/Sales/_files/guest_quote_with_addresses.php + */ + public function testQuoteToOrder() + { + /** @var Quote $quote */ + $quote = $this->objectManager->create(Quote::class); + $quote->load('guest_quote', 'reserved_order_id'); + + $this->checkoutSession->setQuoteId($quote->getId()); + + /** @var QuoteIdMask $quoteIdMask */ + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->load($quote->getId(), 'quote_id'); + $cartId = $quoteIdMask->getMaskedId(); + + /** @var GuestCartManagementInterface $cartManagement */ + $orderId = $this->cartManagement->placeOrder($cartId); + /** @var Order $order */ + $order = $this->objectManager->get(OrderRepository::class)->get($orderId); + + // GrandTotal takes shipping into account + $this->assertEquals(15, $order->getGrandTotal()); + $this->assertOrderPurchaseEvent($order, false); + } + + /** + * @magentoDataFixture Algolia_AlgoliaSearch::Test/Integration/Frontend/Insights/_files/order_with_two_order_items.php + */ + public function testOrderWithTwoOrderItems() + { + /** @var Order $order */ + $order = $this->getOrder('100000001'); + + $this->assertOrderPurchaseEvent($order); + } +} diff --git a/Test/Integration/Frontend/Insights/_files/address_data.php b/Test/Integration/Frontend/Insights/_files/address_data.php new file mode 100644 index 000000000..f7dd8cb52 --- /dev/null +++ b/Test/Integration/Frontend/Insights/_files/address_data.php @@ -0,0 +1,19 @@ + 'CA', + 'region_id' => '12', + 'postcode' => '11111', + 'company' => 'Test Company', + 'lastname' => 'lastname', + 'firstname' => 'firstname', + 'street' => 'street', + 'city' => 'Los Angeles', + 'email' => 'admin@example.com', + 'telephone' => '11111111', + 'country_id' => 'US' +]; diff --git a/Test/Integration/Frontend/Insights/_files/order_with_two_order_items.php b/Test/Integration/Frontend/Insights/_files/order_with_two_order_items.php new file mode 100644 index 000000000..25d33c20d --- /dev/null +++ b/Test/Integration/Frontend/Insights/_files/order_with_two_order_items.php @@ -0,0 +1,99 @@ +requireDataFixture('Magento/Customer/_files/customer.php'); +Resolver::getInstance()->requireDataFixture('Algolia_AlgoliaSearch::Test/Integration/Frontend/Insights//_files/products.php'); + +$objectManager = Bootstrap::getObjectManager(); +$addressData = include __DIR__ . '/address_data.php'; +/** @var CustomerRegistry $customerRegistry */ +$customerRegistry = $objectManager->create(CustomerRegistry::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = $objectManager->create(ProductRepositoryInterface::class); +$customer = $customerRegistry->retrieve(1); +$product = $productRepository->get('simple'); +$customDesignProduct = $productRepository->get('custom-design-simple-product'); +/** @var OrderAddressInterfaceFactory $addressFactory */ +$addressFactory = $objectManager->get(OrderAddressInterfaceFactory::class); +/** @var OrderPaymentInterfaceFactory $paymentFactory */ +$paymentFactory = $objectManager->get(OrderPaymentInterfaceFactory::class); +/** @var OrderInterfaceFactory $orderFactory */ +$orderFactory = $objectManager->get(OrderInterfaceFactory::class); +/** @var OrderItemInterfaceFactory $orderItemFactory */ +$orderItemFactory = $objectManager->get(OrderItemInterfaceFactory::class); +/** @var StoreManagerInterface $storeManager */ +$storeManager = $objectManager->get(StoreManagerInterface::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); + +$billingAddress = $addressFactory->create(['data' => $addressData]); +$billingAddress->setAddressType(Address::TYPE_BILLING); +$shippingAddress = $addressFactory->create(['data' => $addressData]); +$shippingAddress->setAddressType(Address::TYPE_SHIPPING); +$payment = $paymentFactory->create(); +$payment->setMethod('checkmo')->setAdditionalInformation( + [ + 'last_trans_id' => '11122', + 'metadata' => [ + 'type' => 'free', + 'fraudulent' => false, + ] + ] +); + +$defaultStoreId = $storeManager->getStore('default')->getId(); +$order = $orderFactory->create(); +$order->setIncrementId('100000001') + ->setState(Order::STATE_PROCESSING) + ->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)) + ->setSubtotal(20) + ->setGrandTotal(20) + ->setBaseSubtotal(20) + ->setBaseGrandTotal(20) + ->setCustomerIsGuest(false) + ->setCustomerId($customer->getId()) + ->setCustomerEmail($customer->getEmail()) + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setStoreId($defaultStoreId) + ->setPayment($payment); + +$orderItem = $orderItemFactory->create(); +$orderItem->setProductId($product->getId()) + ->setQtyOrdered(5) + ->setBasePrice($product->getPrice()) + ->setPrice($product->getPrice()) + ->setRowTotal($product->getPrice()) + ->setProductType($product->getTypeId()) + ->setName($product->getName()) + ->setSku($product->getSku()); +$order->addItem($orderItem); + +$orderItem = $orderItemFactory->create(); +$orderItem->setProductId($customDesignProduct->getId()) + ->setQtyOrdered(5) + ->setBasePrice($customDesignProduct->getPrice()) + ->setPrice($customDesignProduct->getPrice()) + ->setRowTotal($customDesignProduct->getPrice()) + ->setProductType($customDesignProduct->getTypeId()) + ->setName($customDesignProduct->getName()) + ->setSku($customDesignProduct->getSku()); +$order->addItem($orderItem); +$orderRepository->save($order); diff --git a/Test/Integration/Frontend/Insights/_files/order_with_two_order_items_rollback.php b/Test/Integration/Frontend/Insights/_files/order_with_two_order_items_rollback.php new file mode 100644 index 000000000..0dcf8b015 --- /dev/null +++ b/Test/Integration/Frontend/Insights/_files/order_with_two_order_items_rollback.php @@ -0,0 +1,37 @@ +get(Registry::class); +/** @var OrderRepositoryInterface $orderRepository */ +$orderRepository = $objectManager->get(OrderRepositoryInterface::class); +/** @var CollectionFactory $orderCollectionFactory */ +$orderCollectionFactory = $objectManager->get(CollectionFactory::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); +$order = $orderCollectionFactory->create() + ->addFieldToFilter(OrderInterface::INCREMENT_ID, '100000001') + ->setPageSize(1) + ->getFirstItem(); +if ($order->getId()) { + $orderRepository->delete($order); +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); + +Resolver::getInstance()->requireDataFixture('Magento/Customer/_files/customer_rollback.php'); +Resolver::getInstance()->requireDataFixture('Algolia_AlgoliaSearch::Test/Integration/Frontend/Insights/_files/products_rollback.php'); diff --git a/Test/Integration/Frontend/Insights/_files/products.php b/Test/Integration/Frontend/Insights/_files/products.php new file mode 100644 index 000000000..348701a99 --- /dev/null +++ b/Test/Integration/Frontend/Insights/_files/products.php @@ -0,0 +1,38 @@ +create(\Magento\Catalog\Model\Product::class); +$product + ->setTypeId('simple') + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product') + ->setSku('simple') + ->setPrice(10) + ->setMetaTitle('meta title') + ->setMetaKeyword('meta keyword') + ->setMetaDescription('meta description') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 22, 'is_in_stock' => 1]) + ->setQty(22) + ->save(); + +$customDesignProduct = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Catalog\Model\Product::class, ['data' => $product->getData()]); + +$customDesignProduct->setUrlKey('custom-design-simple-product') + ->setId(2) + ->setRowId(2) + ->setName('Custom Design Simple Product') + ->setSku('custom-design-simple-product') + ->setCustomDesign('Magento/blank') + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 24, 'is_in_stock' => 1]) + ->setQty(24) + ->save(); diff --git a/Test/Integration/Frontend/Insights/_files/products_rollback.php b/Test/Integration/Frontend/Insights/_files/products_rollback.php new file mode 100644 index 000000000..af25ead39 --- /dev/null +++ b/Test/Integration/Frontend/Insights/_files/products_rollback.php @@ -0,0 +1,38 @@ +get(\Magento\Framework\Registry::class); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** + * @var Magento\Catalog\Api\ProductRepositoryInterface $productRepository + */ +$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); +try { + $product = $productRepository->get('simple', false, null, true); + $productRepository->delete($product); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + //Product already removed +} + +try { + $customDesignProduct = $productRepository->get('custom-design-simple-product', false, null, true); + $productRepository->delete($customDesignProduct); +} catch (\Magento\Framework\Exception\NoSuchEntityException $e) { + //Product already removed +} + +/** @var \Magento\CatalogInventory\Model\StockRegistryStorage $stockRegistryStorage */ +$stockRegistryStorage = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->get(\Magento\CatalogInventory\Model\StockRegistryStorage::class); +$stockRegistryStorage->clean(); + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false);