From ed5dd4d3f47ea7534bb8fe1018b0d6718cb5f99a Mon Sep 17 00:00:00 2001 From: Patrick McLain Date: Tue, 16 Apr 2019 23:55:19 -0400 Subject: [PATCH 1/2] Add end to end checkout tests Tests checkout flow for customer and guest. --- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ++++++++++++++++++ 1 file changed, 623 insertions(+) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php new file mode 100644 index 0000000000000..0354356d6927c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php @@ -0,0 +1,623 @@ +graphQlMutation($this->buildCreateCustomerMutation($email)); + $authHeader = $this->createAuthHeader($email); + + $cartId = $this->createEmptyCart($authHeader); + $cart = $this->configureQuote($cartId, $authHeader); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + $this->assertNotEmpty($orderId); + + $order = $this->getOrderFromHistory($orderId, $authHeader); + $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); + //TODO: Make additional assertions when order properties are added + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutAsGuest() + { + $email = 'e2e_2@example.com'; + $cartId = $this->createEmptyCart(); + $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); + $this->configureQuote($cartId); + + $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); + $orderId = $placeOrderResult['placeOrder']['order']['order_id']; + + $this->assertNotEmpty($orderId); + } + + /** + * Configures cart with order placement requirements + * + * @param string $cartId + * @param array $headers + * @return array + */ + private function configureQuote(string $cartId, array $headers = []): array + { + $expectedTotal = 5.99; + $expectedQty = 1; + + $sku = $this->getSku($headers); + $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); + $cart = $addToCartResult['addSimpleProductsToCart']['cart']; + $this->assertGrandTotal($expectedTotal, $cart); + + $address = $this->setShippingAddress($cartId, $headers); + $shippingMethod = $this->extractFirstAvailableShippingMethod($address); + + $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); + $expectedTotal += $shippingMethod['amount']; + $this->assertGrandTotal($expectedTotal, $cart); + $this->assertSelectedShippingMethod($shippingMethod, $cart); + + $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); + $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; + $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); + + $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); + $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; + $this->assertPaymentMethod($paymentMethod, $cart); + $this->assertGrandTotal($expectedTotal, $cart); + + return $cart; + } + + /** + * Generates customer authentication header for restricted requests + * + * @param string $email + * @return array + */ + private function createAuthHeader(string $email): array + { + $result = $this->graphQlMutation($this->buildLoginMutation($email)); + $token = $result['generateCustomerToken']['token']; + + return ['Authorization' => 'Bearer ' . $token]; + } + + /** + * Creates empty cart for customer or guest + * + * @param array $auth + * @return string + */ + private function createEmptyCart(array $auth = []): string + { + $query = <<graphQlMutation($query, [], '', $auth); + + return $result['createEmptyCart']; + } + + /** + * Get first SKU returned by catalog search + * + * @param array $auth + * @return string + */ + private function getSku(array $auth): string + { + $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); + $items = $result['products']['items']; + $item = current($items); + + return $item['sku']; + } + + /** + * Set cart shipping address + * + * @param string $cartId + * @param array $auth + * @return array + */ + private function setShippingAddress(string $cartId, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); + $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; + + return current($addresses); + } + + /** + * Set cart shipping method + * + * @param string $cartId + * @param array $method + * @param array $address + * @param array $auth + * @return array + */ + private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array + { + $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); + + return $result['setShippingMethodsOnCart']['cart']; + } + + /** + * Get order from history by increment id + * + * @param string $orderId + * @param array $auth + * @return array + */ + private function getOrderFromHistory(string $orderId, array $auth): array + { + $query = <<graphQlQuery($query, [], '', $auth); + $orders = $result['customerOrders']['items']; + + foreach ($orders as $order) { + if ($order['increment_id'] === $orderId) { + return $order; + } + } + + $this->fail(sprintf('No order with increment_id: %s', $orderId)); + } + + /** + * Get first shipping method available from address + * @param array $address + * @return array + */ + private function extractFirstAvailableShippingMethod(array $address): array + { + $methods = $address['available_shipping_methods']; + + return current($methods); + } + + /** + * Get first payment method available from cart + * + * @param array $cart + * @return array + */ + private function extractFirstAvailablePaymentMethod(array $cart): array + { + $methods = $cart['available_payment_methods']; + + return current($methods); + } + + /** + * Assert cart grand total + * + * @param float $expected + * @param array $cart + */ + private function assertGrandTotal(float $expected, array $cart): void + { + $this->assertEquals($expected, $cart['prices']['grand_total']['value']); + } + + /** + * Assert cart payment method + * @param array $method + * @param array $cart + */ + private function assertPaymentMethod(array $method, array $cart): void + { + $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); + } + + /** + * Assert cart shipping method + * + * @param array $expectedMethod + * @param array $cart + */ + private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void + { + $address = current($cart['shipping_addresses']); + $selectedMethod = $address['selected_shipping_method']; + + $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); + $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); + } + + /** + * Build createCustomer mutation + * + * @param string $email + * @return string + */ + private function buildCreateCustomerMutation(string $email): string + { + return << Date: Fri, 19 Apr 2019 13:06:35 -0500 Subject: [PATCH 2/2] GraphQL-604: [Test coverage] End to tests for customer checkout workflow --- .../Quote/Customer/CheckoutEndToEndTest.php | 530 +++++++++++++++ .../Quote/Customer/CreateEmptyCartTest.php | 34 +- .../Quote/Customer/EndToEndCheckoutTest.php | 623 ------------------ .../GraphQl/Quote/Customer/PlaceOrderTest.php | 1 - .../Quote/Guest/CheckoutEndToEndTest.php | 441 +++++++++++++ .../Quote/Guest/CreateEmptyCartTest.php | 34 +- 6 files changed, 989 insertions(+), 674 deletions(-) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CheckoutEndToEndTest.php diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php new file mode 100644 index 0000000000000..8592a986c5dce --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CheckoutEndToEndTest.php @@ -0,0 +1,530 @@ +registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->customerRepository = Bootstrap::getObjectManager()->get(CustomerRepositoryInterface::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $this->createCustomer(); + $token = $this->loginCustomer(); + $this->headers = ['Authorization' => 'Bearer ' . $token]; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $orderId = $this->placeOrder($cartId); + $this->checkOrderInHistory($orderId); + } + + /** + * @return void + */ + private function createCustomer(): void + { + $query = <<graphQlMutation($query); + } + + /** + * @return string + */ + private function loginCustomer(): string + { + $query = <<graphQlMutation($query); + self::assertArrayHasKey('generateCustomerToken', $response); + self::assertArrayHasKey('token', $response['generateCustomerToken']); + self::assertNotEmpty($response['generateCustomerToken']['token']); + + return $response['generateCustomerToken']['token']; + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<graphQlMutation($query, [], '', $this->headers); + } + + /** + * @param string $cartId + * @return string + */ + private function placeOrder(string $cartId): string + { + $query = <<graphQlMutation($query, [], '', $this->headers); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + + return $response['placeOrder']['order']['order_id']; + } + + /** + * @param string $orderId + * @return void + */ + private function checkOrderInHistory(string $orderId): void + { + $query = <<graphQlQuery($query, [], '', $this->headers); + self::assertArrayHasKey('customerOrders', $response); + self::assertArrayHasKey('items', $response['customerOrders']); + self::assertCount(1, $response['customerOrders']['items']); + + $order = current($response['customerOrders']['items']); + self::assertArrayHasKey('increment_id', $order); + self::assertEquals($orderId, $order['increment_id']); + + self::assertArrayHasKey('grand_total', $order); + } + + public function tearDown() + { + $this->deleteCustomer(); + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteCustomer(): void + { + $email = 'customer@example.com'; + try { + $customer = $this->customerRepository->get($email); + } catch (\Exception $exception) { + return; + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + $this->customerRepository->delete($customer); + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php index fc66e4647e576..56ef78811dd1f 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CreateEmptyCartTest.php @@ -8,9 +8,8 @@ namespace Magento\GraphQl\Quote\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -32,38 +31,27 @@ class CreateEmptyCartTest extends GraphQlAbstract private $customerTokenService; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -79,7 +67,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertEquals(1, $guestCart->getCustomer()->getId()); @@ -138,15 +125,12 @@ private function getHeaderMapWithCustomerToken( public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown(); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php deleted file mode 100644 index 0354356d6927c..0000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/EndToEndCheckoutTest.php +++ /dev/null @@ -1,623 +0,0 @@ -graphQlMutation($this->buildCreateCustomerMutation($email)); - $authHeader = $this->createAuthHeader($email); - - $cartId = $this->createEmptyCart($authHeader); - $cart = $this->configureQuote($cartId, $authHeader); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId), [], '', $authHeader); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - $this->assertNotEmpty($orderId); - - $order = $this->getOrderFromHistory($orderId, $authHeader); - $this->assertEquals($cart['prices']['grand_total']['value'], $order['grand_total']); - //TODO: Make additional assertions when order properties are added - } - - /** - * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php - */ - public function testCheckoutAsGuest() - { - $email = 'e2e_2@example.com'; - $cartId = $this->createEmptyCart(); - $this->graphQlMutation($this->buildSetGuestEmailOnCartMutation($cartId, $email)); - $this->configureQuote($cartId); - - $placeOrderResult = $this->graphQlMutation($this->buildPlaceOrderMutation($cartId)); - $orderId = $placeOrderResult['placeOrder']['order']['order_id']; - - $this->assertNotEmpty($orderId); - } - - /** - * Configures cart with order placement requirements - * - * @param string $cartId - * @param array $headers - * @return array - */ - private function configureQuote(string $cartId, array $headers = []): array - { - $expectedTotal = 5.99; - $expectedQty = 1; - - $sku = $this->getSku($headers); - $addToCartResult = $this->graphQlMutation($this->buildAddToCartMutation($cartId, $expectedQty, $sku), [], '', $headers); - $cart = $addToCartResult['addSimpleProductsToCart']['cart']; - $this->assertGrandTotal($expectedTotal, $cart); - - $address = $this->setShippingAddress($cartId, $headers); - $shippingMethod = $this->extractFirstAvailableShippingMethod($address); - - $cart = $this->setShippingMethod($cartId, $shippingMethod, $address, $headers); - $expectedTotal += $shippingMethod['amount']; - $this->assertGrandTotal($expectedTotal, $cart); - $this->assertSelectedShippingMethod($shippingMethod, $cart); - - $setBillingAddressResult = $this->graphQlMutation($this->buildSetNewBillingAddressMutation($cartId), [], '', $headers); - $cart = $setBillingAddressResult['setBillingAddressOnCart']['cart']; - $paymentMethod = $this->extractFirstAvailablePaymentMethod($cart); - - $setPaymentResult = $this->graphQlMutation($this->buildSetPaymentMethodMutation($cartId, $paymentMethod), [], '', $headers); - $cart = $setPaymentResult['setPaymentMethodOnCart']['cart']; - $this->assertPaymentMethod($paymentMethod, $cart); - $this->assertGrandTotal($expectedTotal, $cart); - - return $cart; - } - - /** - * Generates customer authentication header for restricted requests - * - * @param string $email - * @return array - */ - private function createAuthHeader(string $email): array - { - $result = $this->graphQlMutation($this->buildLoginMutation($email)); - $token = $result['generateCustomerToken']['token']; - - return ['Authorization' => 'Bearer ' . $token]; - } - - /** - * Creates empty cart for customer or guest - * - * @param array $auth - * @return string - */ - private function createEmptyCart(array $auth = []): string - { - $query = <<graphQlMutation($query, [], '', $auth); - - return $result['createEmptyCart']; - } - - /** - * Get first SKU returned by catalog search - * - * @param array $auth - * @return string - */ - private function getSku(array $auth): string - { - $result = $this->graphQlQuery($this->buildProductSearchQuery('simple'), [], '', $auth); - $items = $result['products']['items']; - $item = current($items); - - return $item['sku']; - } - - /** - * Set cart shipping address - * - * @param string $cartId - * @param array $auth - * @return array - */ - private function setShippingAddress(string $cartId, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetNewShippingAddressMutation($cartId), [], '', $auth); - $addresses = $result['setShippingAddressesOnCart']['cart']['shipping_addresses']; - - return current($addresses); - } - - /** - * Set cart shipping method - * - * @param string $cartId - * @param array $method - * @param array $address - * @param array $auth - * @return array - */ - private function setShippingMethod(string $cartId, array $method, array $address, array $auth): array - { - $result = $this->graphQlMutation($this->buildSetShippingMethodMutation($cartId, $method, $address), [], '', $auth); - - return $result['setShippingMethodsOnCart']['cart']; - } - - /** - * Get order from history by increment id - * - * @param string $orderId - * @param array $auth - * @return array - */ - private function getOrderFromHistory(string $orderId, array $auth): array - { - $query = <<graphQlQuery($query, [], '', $auth); - $orders = $result['customerOrders']['items']; - - foreach ($orders as $order) { - if ($order['increment_id'] === $orderId) { - return $order; - } - } - - $this->fail(sprintf('No order with increment_id: %s', $orderId)); - } - - /** - * Get first shipping method available from address - * @param array $address - * @return array - */ - private function extractFirstAvailableShippingMethod(array $address): array - { - $methods = $address['available_shipping_methods']; - - return current($methods); - } - - /** - * Get first payment method available from cart - * - * @param array $cart - * @return array - */ - private function extractFirstAvailablePaymentMethod(array $cart): array - { - $methods = $cart['available_payment_methods']; - - return current($methods); - } - - /** - * Assert cart grand total - * - * @param float $expected - * @param array $cart - */ - private function assertGrandTotal(float $expected, array $cart): void - { - $this->assertEquals($expected, $cart['prices']['grand_total']['value']); - } - - /** - * Assert cart payment method - * @param array $method - * @param array $cart - */ - private function assertPaymentMethod(array $method, array $cart): void - { - $this->assertEquals($method['code'], $cart['selected_payment_method']['code']); - } - - /** - * Assert cart shipping method - * - * @param array $expectedMethod - * @param array $cart - */ - private function assertSelectedShippingMethod(array $expectedMethod, array $cart): void - { - $address = current($cart['shipping_addresses']); - $selectedMethod = $address['selected_shipping_method']; - - $this->assertEquals($expectedMethod['carrier_code'], $selectedMethod['carrier_code']); - $this->assertEquals($expectedMethod['method_code'], $selectedMethod['method_code']); - } - - /** - * Build createCustomer mutation - * - * @param string $email - * @return string - */ - private function buildCreateCustomerMutation(string $email): string - { - return <<registry = $objectManager->get(Registry::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); + $this->orderCollectionFactory = $objectManager->get(CollectionFactory::class); + $this->orderRepository = $objectManager->get(OrderRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Catalog/_files/products_with_layered_navigation_attribute.php + */ + public function testCheckoutWorkflow() + { + $qty = 2; + + $sku = $this->findProduct(); + $cartId = $this->createEmptyCart(); + $this->setGuestEmailOnCart($cartId); + $this->addProductToCart($cartId, $qty, $sku); + + $this->setBillingAddress($cartId); + $shippingAddress = $this->setShippingAddress($cartId); + + $shippingMethod = current($shippingAddress['available_shipping_methods']); + $paymentMethod = $this->setShippingMethod($cartId, $shippingAddress['address_id'], $shippingMethod); + $this->setPaymentMethod($cartId, $paymentMethod); + + $this->placeOrder($cartId); + } + + /** + * @return string + */ + private function findProduct(): string + { + $query = <<graphQlQuery($query); + self::assertArrayHasKey('products', $response); + self::assertArrayHasKey('items', $response['products']); + self::assertCount(1, $response['products']['items']); + + $product = current($response['products']['items']); + self::assertArrayHasKey('sku', $product); + self::assertNotEmpty($product['sku']); + + return $product['sku']; + } + + /** + * @return string + */ + private function createEmptyCart(): string + { + $query = <<graphQlMutation($query); + self::assertArrayHasKey('createEmptyCart', $response); + self::assertNotEmpty($response['createEmptyCart']); + + return $response['createEmptyCart']; + } + + /** + * @param string $cartId + * @return void + */ + private function setGuestEmailOnCart(string $cartId): void + { + $query = <<graphQlMutation($query); + } + + /** + * @param string $cartId + * @param float $qty + * @param string $sku + * @return void + */ + private function addProductToCart(string $cartId, float $qty, string $sku): void + { + $query = <<graphQlMutation($query); + } + + /** + * @param string $cartId + * @param array $auth + * @return array + */ + private function setBillingAddress(string $cartId): void + { + $query = <<graphQlMutation($query); + } + + /** + * @param string $cartId + * @return array + */ + private function setShippingAddress(string $cartId): array + { + $query = <<graphQlMutation($query); + self::assertArrayHasKey('setShippingAddressesOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + self::assertArrayHasKey('shipping_addresses', $response['setShippingAddressesOnCart']['cart']); + self::assertCount(1, $response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + + $shippingAddress = current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']); + self::assertArrayHasKey('address_id', $shippingAddress); + self::assertNotEmpty($shippingAddress['address_id']); + self::assertArrayHasKey('available_shipping_methods', $shippingAddress); + self::assertCount(1, $shippingAddress['available_shipping_methods']); + + $availableShippingMethod = current($shippingAddress['available_shipping_methods']); + self::assertArrayHasKey('carrier_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['carrier_code']); + + self::assertArrayHasKey('method_code', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['method_code']); + + self::assertArrayHasKey('amount', $availableShippingMethod); + self::assertNotEmpty($availableShippingMethod['amount']); + + return $shippingAddress; + } + + /** + * @param string $cartId + * @param int $addressId + * @param array $method + * @return array + */ + private function setShippingMethod(string $cartId, int $addressId, array $method): array + { + $query = <<graphQlMutation($query); + self::assertArrayHasKey('setShippingMethodsOnCart', $response); + self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); + self::assertArrayHasKey('available_payment_methods', $response['setShippingMethodsOnCart']['cart']); + self::assertCount(1, $response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + + $availablePaymentMethod = current($response['setShippingMethodsOnCart']['cart']['available_payment_methods']); + self::assertArrayHasKey('code', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['code']); + self::assertArrayHasKey('title', $availablePaymentMethod); + self::assertNotEmpty($availablePaymentMethod['title']); + + return $availablePaymentMethod; + } + + /** + * @param string $cartId + * @param array $method + * @return void + */ + private function setPaymentMethod(string $cartId, array $method): void + { + $query = <<graphQlMutation($query); + } + + /** + * @param string $cartId + * @return void + */ + private function placeOrder(string $cartId): void + { + $query = <<graphQlMutation($query); + self::assertArrayHasKey('placeOrder', $response); + self::assertArrayHasKey('order', $response['placeOrder']); + self::assertArrayHasKey('order_id', $response['placeOrder']['order']); + self::assertNotEmpty($response['placeOrder']['order']['order_id']); + } + + public function tearDown() + { + $this->deleteQuote(); + $this->deleteOrder(); + parent::tearDown(); + } + + /** + * @return void + */ + private function deleteQuote(): void + { + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { + $this->quoteResource->delete($quote); + + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quote->getId()) + ->delete(); + } + } + + /** + * @return void + */ + private function deleteOrder() + { + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', true); + + $orderCollection = $this->orderCollectionFactory->create(); + foreach ($orderCollection as $order) { + $this->orderRepository->delete($order); + } + $this->registry->unregister('isSecureArea'); + $this->registry->register('isSecureArea', false); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php index adb2879e186b1..ddce2cfbffbcb 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CreateEmptyCartTest.php @@ -7,9 +7,8 @@ namespace Magento\GraphQl\Quote\Guest; -use Magento\Quote\Model\QuoteFactory; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\QuoteIdMaskFactory; +use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory as QuoteCollectionFactory; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; use Magento\TestFramework\TestCase\GraphQlAbstract; @@ -26,37 +25,26 @@ class CreateEmptyCartTest extends GraphQlAbstract private $guestCartRepository; /** - * @var QuoteResource - */ - private $quoteResource; - - /** - * @var QuoteFactory + * @var QuoteCollectionFactory */ - private $quoteFactory; + private $quoteCollectionFactory; /** - * @var MaskedQuoteIdToQuoteIdInterface + * @var QuoteResource */ - private $maskedQuoteIdToQuoteId; + private $quoteResource; /** * @var QuoteIdMaskFactory */ private $quoteIdMaskFactory; - /** - * @var string - */ - private $maskedQuoteId; - protected function setUp() { $objectManager = Bootstrap::getObjectManager(); $this->guestCartRepository = $objectManager->get(GuestCartRepositoryInterface::class); + $this->quoteCollectionFactory = $objectManager->get(QuoteCollectionFactory::class); $this->quoteResource = $objectManager->get(QuoteResource::class); - $this->quoteFactory = $objectManager->get(QuoteFactory::class); - $this->maskedQuoteIdToQuoteId = $objectManager->get(MaskedQuoteIdToQuoteIdInterface::class); $this->quoteIdMaskFactory = $objectManager->get(QuoteIdMaskFactory::class); } @@ -69,7 +57,6 @@ public function testCreateEmptyCart() self::assertNotEmpty($response['createEmptyCart']); $guestCart = $this->guestCartRepository->get($response['createEmptyCart']); - $this->maskedQuoteId = $response['createEmptyCart']; self::assertNotNull($guestCart->getId()); self::assertNull($guestCart->getCustomer()->getId()); @@ -110,15 +97,12 @@ private function getQuery(): string public function tearDown() { - if (null !== $this->maskedQuoteId) { - $quoteId = $this->maskedQuoteIdToQuoteId->execute($this->maskedQuoteId); - - $quote = $this->quoteFactory->create(); - $this->quoteResource->load($quote, $quoteId); + $quoteCollection = $this->quoteCollectionFactory->create(); + foreach ($quoteCollection as $quote) { $this->quoteResource->delete($quote); $quoteIdMask = $this->quoteIdMaskFactory->create(); - $quoteIdMask->setQuoteId($quoteId) + $quoteIdMask->setQuoteId($quote->getId()) ->delete(); } parent::tearDown();