diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php new file mode 100644 index 000000000000..d3de86702b96 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php @@ -0,0 +1,65 @@ +addressRepository = $addressRepository; + } + + /** + * Get customer address. Throws exception if customer is not owner of address + * + * @param int $addressId + * @param int $customerId + * @return AddressInterface + * @throws GraphQlAuthorizationException + * @throws GraphQlNoSuchEntityException + * @throws LocalizedException + */ + public function execute(int $addressId, int $customerId): AddressInterface + { + try { + $customerAddress = $this->addressRepository->getById($addressId); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException( + __('Could not find a address with ID "%address_id"', ['address_id' => $addressId]) + ); + } + + if ((int)$customerAddress->getCustomerId() !== $customerId) { + throw new GraphQlAuthorizationException( + __( + 'The current user cannot use address with ID "%address_id"', + ['address_id' => $addressId] + ) + ); + } + return $customerAddress; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 97b1ed09decc..5d3125ae13ef 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -7,7 +7,6 @@ namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\Customer\Api\Data\AddressInterface; use Magento\CustomerGraphQl\Model\Customer\CheckCustomerAccount; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; @@ -26,11 +25,6 @@ class SetBillingAddressOnCart */ private $billingAddressManagement; - /** - * @var AddressRepositoryInterface - */ - private $addressRepository; - /** * @var Address */ @@ -41,26 +35,40 @@ class SetBillingAddressOnCart */ private $checkCustomerAccount; + /** + * @var GetCustomerAddress + */ + private $getCustomerAddress; + /** * @param BillingAddressManagementInterface $billingAddressManagement * @param AddressRepositoryInterface $addressRepository * @param Address $addressModel * @param CheckCustomerAccount $checkCustomerAccount + * @param GetCustomerAddress $getCustomerAddress */ public function __construct( BillingAddressManagementInterface $billingAddressManagement, AddressRepositoryInterface $addressRepository, Address $addressModel, - CheckCustomerAccount $checkCustomerAccount + CheckCustomerAccount $checkCustomerAccount, + GetCustomerAddress $getCustomerAddress ) { $this->billingAddressManagement = $billingAddressManagement; $this->addressRepository = $addressRepository; $this->addressModel = $addressModel; $this->checkCustomerAccount = $checkCustomerAccount; + $this->getCustomerAddress = $getCustomerAddress; } /** - * @inheritdoc + * Set billing address for a specified shopping cart + * + * @param ContextInterface $context + * @param CartInterface $cart + * @param array $billingAddress + * @return void + * @throws GraphQlInputException */ public function execute(ContextInterface $context, CartInterface $cart, array $billingAddress): void { @@ -88,9 +96,7 @@ public function execute(ContextInterface $context, CartInterface $cart, array $b $billingAddress = $this->addressModel->addData($addressInput); } else { $this->checkCustomerAccount->execute($context->getUserId(), $context->getUserType()); - - /** @var AddressInterface $customerAddress */ - $customerAddress = $this->addressRepository->getById($customerAddressId); + $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$context->getUserId()); $billingAddress = $this->addressModel->importCustomerAddressData($customerAddress); } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php index b9fd5c7807d2..e6b18fc88a27 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php @@ -7,14 +7,12 @@ namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\Customer\Api\Data\AddressInterface; use Magento\CustomerGraphQl\Model\Customer\CheckCustomerAccount; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Quote\Api\Data\CartInterface; use Magento\Quote\Model\Quote\Address; use Magento\Quote\Model\ShippingAddressManagementInterface; -use Magento\Customer\Api\AddressRepositoryInterface; /** * Set single shipping address for a specified shopping cart @@ -26,11 +24,6 @@ class SetShippingAddressOnCart implements SetShippingAddressesOnCartInterface */ private $shippingAddressManagement; - /** - * @var AddressRepositoryInterface - */ - private $addressRepository; - /** * @var Address */ @@ -41,26 +34,36 @@ class SetShippingAddressOnCart implements SetShippingAddressesOnCartInterface */ private $checkCustomerAccount; + /** + * @var GetCustomerAddress + */ + private $getCustomerAddress; + /** * @param ShippingAddressManagementInterface $shippingAddressManagement - * @param AddressRepositoryInterface $addressRepository * @param Address $addressModel * @param CheckCustomerAccount $checkCustomerAccount + * @param GetCustomerAddress $getCustomerAddress */ public function __construct( ShippingAddressManagementInterface $shippingAddressManagement, - AddressRepositoryInterface $addressRepository, Address $addressModel, - CheckCustomerAccount $checkCustomerAccount + CheckCustomerAccount $checkCustomerAccount, + GetCustomerAddress $getCustomerAddress ) { $this->shippingAddressManagement = $shippingAddressManagement; - $this->addressRepository = $addressRepository; $this->addressModel = $addressModel; $this->checkCustomerAccount = $checkCustomerAccount; + $this->getCustomerAddress = $getCustomerAddress; } /** * @inheritdoc + * + * @param ContextInterface $context + * @param CartInterface $cart + * @param array $shippingAddresses + * @throws GraphQlInputException */ public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddresses): void { @@ -87,9 +90,7 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s $shippingAddress = $this->addressModel->addData($addressInput); } else { $this->checkCustomerAccount->execute($context->getUserId(), $context->getUserType()); - - /** @var AddressInterface $customerAddress */ - $customerAddress = $this->addressRepository->getById($customerAddressId); + $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$context->getUserId()); $shippingAddress = $this->addressModel->importCustomerAddressData($customerAddress); } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php index b024e7b77af4..ec50bd6ab6ea 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php @@ -12,7 +12,6 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Framework\Stdlib\ArrayManager; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\ShippingAddressManagementInterface; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; use Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCartInterface; @@ -24,11 +23,6 @@ */ class SetShippingAddressesOnCart implements ResolverInterface { - /** - * @var MaskedQuoteIdToQuoteIdInterface - */ - private $maskedQuoteIdToQuoteId; - /** * @var ShippingAddressManagementInterface */ @@ -50,20 +44,17 @@ class SetShippingAddressesOnCart implements ResolverInterface private $setShippingAddressesOnCart; /** - * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId * @param ShippingAddressManagementInterface $shippingAddressManagement * @param GetCartForUser $getCartForUser * @param ArrayManager $arrayManager * @param SetShippingAddressesOnCartInterface $setShippingAddressesOnCart */ public function __construct( - MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, ShippingAddressManagementInterface $shippingAddressManagement, GetCartForUser $getCartForUser, ArrayManager $arrayManager, SetShippingAddressesOnCartInterface $setShippingAddressesOnCart ) { - $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; $this->shippingAddressManagement = $shippingAddressManagement; $this->getCartForUser = $getCartForUser; $this->arrayManager = $arrayManager; @@ -76,16 +67,16 @@ public function __construct( public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { $shippingAddresses = $this->arrayManager->get('input/shipping_addresses', $args); - $maskedCartId = $this->arrayManager->get('input/cart_id', $args); + $maskedCartId = (string) $this->arrayManager->get('input/cart_id', $args); if (!$maskedCartId) { throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); } + if (!$shippingAddresses) { throw new GraphQlInputException(__('Required parameter "shipping_addresses" is missing')); } - $maskedCartId = $args['input']['cart_id']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $this->setShippingAddressesOnCart->execute($context, $cart, $shippingAddresses); diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index c52bd52fb322..f2806f6dd9f0 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -65,8 +65,8 @@ input SetShippingMethodsOnCartInput { input ShippingMethodForAddressInput { cart_address_id: Int! - shipping_carrier_code: String! - shipping_method_code: String! + carrier_code: String! + method_code: String! } type SetBillingAddressOnCartOutput { @@ -117,7 +117,7 @@ type CartAddress { country: CartAddressCountry telephone: String address_type: AdressTypeEnum - selected_shipping_method: ShippingMethod + selected_shipping_method: SelectedShippingMethod available_shipping_methods: [AvailableShippingMethod] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAdress\\AvailableShippingMethods") items_weight: Float customer_notes: String @@ -139,15 +139,8 @@ type CartAddressCountry { label: String } -type ShippingMethod { - code: String - label: String - free_shipping: Boolean! - error_message: String +type SelectedShippingMethod { amount: Float! - base_amount: Float! - amount_incl_tax: Float! - base_amount_incl_tax: Float! } type AvailableShippingMethod { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetBillingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetBillingAddressOnCartTest.php index 62fae71fa79f..bfe57109d107 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetBillingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetBillingAddressOnCartTest.php @@ -10,7 +10,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\Multishipping\Helper\Data; -use Magento\Quote\Model\Quote; +use Magento\Quote\Model\QuoteFactory; use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; @@ -28,34 +28,35 @@ class SetBillingAddressOnCartTest extends GraphQlAbstract private $quoteResource; /** - * @var Quote + * @var QuoteFactory */ - private $quote; + private $quoteFactory; /** * @var QuoteIdToMaskedQuoteIdInterface */ private $quoteIdToMaskedId; + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ - public function testSetNewGuestBillingAddressOnCart() + public function testSetNewBillingAddressByGuest() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<graphQlQuery($query); } @@ -214,23 +200,9 @@ public function testSetSavedBillingAddressOnCartByGuest() * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @magentoApiDataFixture Magento/Customer/_files/customer.php */ - public function testSetNewRegisteredCustomerBillingAddressOnCart() + public function testSetNewBillingAddressByRegisteredCustomer() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - $headerMap = $this->getHeaderMap(); + $maskedQuoteId = $this->assignQuoteToCustomer(); $query = <<graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -281,23 +253,9 @@ public function testSetNewRegisteredCustomerBillingAddressOnCart() * @magentoApiDataFixture Magento/Customer/_files/customer.php * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php */ - public function testSetSavedRegisteredCustomerBillingAddressOnCart() + public function testSetBillingAddressFromAddressBookByRegisteredCustomer() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - $headerMap = $this->getHeaderMap(); + $maskedQuoteId = $this->assignQuoteToCustomer(); $query = <<graphQlQuery($query, [], '', $headerMap); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response['setBillingAddressOnCart']); $cartResponse = $response['setBillingAddressOnCart']['cart']; @@ -332,6 +290,115 @@ public function testSetSavedRegisteredCustomerBillingAddressOnCart() $this->assertSavedBillingAddressFields($billingAddressResponse); } + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a address with ID "100" + */ + public function testSetNotExistedBillingAddressFromAddressBook() + { + $maskedQuoteId = $this->assignQuoteToCustomer(); + + $query = <<graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php + */ + public function testSetNewBillingAddressAndFromAddressBookAtSameTime() + { + $maskedQuoteId = $this->assignQuoteToCustomer(); + + $query = <<graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/Customer/_files/customer_address.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage The current user cannot use address with ID "1" + */ + public function testSetBillingAddressIfCustomerIsNotOwnerOfAddress() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); + + $query = <<graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); + } + /** * Verify the all the whitelisted fields for a New Address Object * @@ -374,19 +441,44 @@ private function assertSavedBillingAddressFields(array $billingAddressResponse): /** * @param string $username + * @param string $password * @return array */ - private function getHeaderMap(string $username = 'customer@example.com'): array + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array { - $password = 'password'; - /** @var CustomerTokenServiceInterface $customerTokenService */ - $customerTokenService = ObjectManager::getInstance() - ->get(CustomerTokenServiceInterface::class); - $customerToken = $customerTokenService->createCustomerAccessToken($username, $password); + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; return $headerMap; } + /** + * @param string $reversedQuoteId + * @return string + */ + private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + } + + /** + * @param string $reversedQuoteId + * @param int $customerId + * @return string + */ + private function assignQuoteToCustomer( + string $reversedQuoteId = 'test_order_with_simple_product_without_address', + int $customerId = 1 + ): string { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + $quote->setCustomerId($customerId); + $this->quoteResource->save($quote); + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + } + public function tearDown() { /** @var \Magento\Config\Model\ResourceModel\Config $config */ diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php index 5bf5f3e03707..c3685c88ae48 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php @@ -10,7 +10,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Integration\Api\CustomerTokenServiceInterface; use Magento\Multishipping\Helper\Data; -use Magento\Quote\Model\Quote; +use Magento\Quote\Model\QuoteFactory; use Magento\Quote\Model\QuoteIdToMaskedQuoteIdInterface; use Magento\Quote\Model\ResourceModel\Quote as QuoteResource; use Magento\TestFramework\Helper\Bootstrap; @@ -28,34 +28,35 @@ class SetShippingAddressOnCartTest extends GraphQlAbstract private $quoteResource; /** - * @var Quote + * @var QuoteFactory */ - private $quote; + private $quoteFactory; /** * @var QuoteIdToMaskedQuoteIdInterface */ private $quoteIdToMaskedId; + /** + * @var CustomerTokenServiceInterface + */ + private $customerTokenService; + protected function setUp() { $objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); + $this->quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php */ - public function testSetNewGuestShippingAddressOnCart() + public function testSetNewShippingAddressByGuest() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<assertNewShippingAddressFields($shippingAddressResponse); - $this->assertAvailableShippingRates($shippingAddressResponse); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage The current customer isn't authorized. */ - public function testSetSavedShippingAddressOnCartByGuest() + public function testSetShippingAddressFromAddressBookByGuest() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<graphQlQuery($query); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php */ - public function testSetMultipleShippingAddressesOnCartByGuest() + public function testSetNewShippingAddressByRegisteredCustomer() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->assignQuoteToCustomer(); $query = <<get(\Magento\Config\Model\ResourceModel\Config::class); - $config->saveConfig( - Data::XML_PATH_CHECKOUT_MULTIPLE_AVAILABLE, - null, - ScopeConfigInterface::SCOPE_TYPE_DEFAULT, - 0 - ); - /** @var \Magento\Framework\App\Config\ReinitableConfigInterface $config */ - $config = ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ReinitableConfigInterface::class); - $config->reinit(); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); - self::expectExceptionMessage('You cannot specify multiple shipping addresses.'); - $this->graphQlQuery($query); + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + $cartResponse = $response['setShippingAddressesOnCart']['cart']; + self::assertArrayHasKey('shipping_addresses', $cartResponse); + $shippingAddressResponse = current($cartResponse['shipping_addresses']); + $this->assertNewShippingAddressFields($shippingAddressResponse); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php */ - public function testSetSavedAndNewShippingAddressOnCartAtTheSameTime() + public function testSetShippingAddressFromAddressBookByRegisteredCustomer() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->assignQuoteToCustomer(); $query = <<graphQlQuery($query); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); + $cartResponse = $response['setShippingAddressesOnCart']['cart']; + self::assertArrayHasKey('shipping_addresses', $cartResponse); + $shippingAddressResponse = current($cartResponse['shipping_addresses']); + $this->assertSavedShippingAddressFields($shippingAddressResponse); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find a address with ID "100" */ - public function testSetShippingAddressOnCartWithNoAddresses() + public function testSetNotExistedShippingAddressFromAddressBook() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $maskedQuoteId = $this->assignQuoteToCustomer(); + + $query = <<graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage The shipping address must contain either "customer_address_id" or "address". + */ + public function testSetShippingAddressWithoutAddresses() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<graphQlQuery($query); } /** * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php */ - public function testSetNewRegisteredCustomerShippingAddressOnCart() + public function testSetNewShippingAddressAndFromAddressBookAtSameTime() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' + $maskedQuoteId = $this->assignQuoteToCustomer(); + + $query = <<quote->setCustomerId(1); - $this->quoteResource->save($this->quote); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } - $headerMap = $this->getHeaderMap(); + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage You cannot specify multiple shipping addresses. + */ + public function testSetMultipleNewShippingAddresses() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<graphQlQuery($query, [], '', $headerMap); + /** @var \Magento\Config\Model\ResourceModel\Config $config */ + $config = ObjectManager::getInstance()->get(\Magento\Config\Model\ResourceModel\Config::class); + $config->saveConfig( + Data::XML_PATH_CHECKOUT_MULTIPLE_AVAILABLE, + null, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + 0 + ); + /** @var \Magento\Framework\App\Config\ReinitableConfigInterface $config */ + $config = ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ReinitableConfigInterface::class); + $config->reinit(); - self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); - $cartResponse = $response['setShippingAddressesOnCart']['cart']; - self::assertArrayHasKey('shipping_addresses', $cartResponse); - $shippingAddressResponse = current($cartResponse['shipping_addresses']); - $this->assertNewShippingAddressFields($shippingAddressResponse); - $this->assertAvailableShippingRates($shippingAddressResponse); + $this->graphQlQuery($query); } /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/Customer/_files/customer_address.php * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/Customer/_files/customer.php - * @magentoApiDataFixture Magento/Customer/_files/customer_two_addresses.php + * @expectedException \Exception + * @expectedExceptionMessage The current user cannot use address with ID "1" */ - public function testSetSavedRegisteredCustomerShippingAddressOnCart() + public function testSetShippingAddressIfCustomerIsNotOwnerOfAddress() { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - $headerMap = $this->getHeaderMap(); + $maskedQuoteId = $this->getMaskedQuoteIdByReversedQuoteId('test_order_with_simple_product_without_address'); $query = <<graphQlQuery($query, [], '', $headerMap); - self::assertArrayHasKey('cart', $response['setShippingAddressesOnCart']); - $cartResponse = $response['setShippingAddressesOnCart']['cart']; - self::assertArrayHasKey('shipping_addresses', $cartResponse); - $shippingAddressResponse = current($cartResponse['shipping_addresses']); - $this->assertSavedShippingAddressFields($shippingAddressResponse); - $this->assertAvailableShippingRates($shippingAddressResponse); + $this->graphQlQuery($query, [], '', $this->getHeaderMap('customer2@search.example.com')); } /** @@ -503,43 +489,43 @@ private function assertSavedShippingAddressFields(array $shippingAddressResponse } /** - * Verify the expected shipping method is available - * - * @param array $shippingAddressResponse + * @param string $username + * @param string $password + * @return array */ - private function assertAvailableShippingRates(array $shippingAddressResponse): void + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array { - $this->assertArrayHasKey('available_shipping_methods', $shippingAddressResponse); - $rate = current($shippingAddressResponse['available_shipping_methods']); + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } - $assertionMap = [ - ['response_field' => 'amount', 'expected_value' => 5], - ['response_field' => 'base_amount', 'expected_value' => 5], - ['response_field' => 'carrier_code', 'expected_value' => 'flatrate'], - ['response_field' => 'carrier_title', 'expected_value' => 'Flat Rate'], - ['response_field' => 'error_message', 'expected_value' => ''], - ['response_field' => 'method_code', 'expected_value' => 'flatrate'], - ['response_field' => 'method_title', 'expected_value' => 'Fixed'], - ['response_field' => 'price_incl_tax', 'expected_value' => 5], - ['response_field' => 'price_excl_tax', 'expected_value' => 5], - ]; + /** + * @param string $reversedQuoteId + * @return string + */ + private function getMaskedQuoteIdByReversedQuoteId(string $reversedQuoteId): string + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); - $this->assertResponseFields($rate, $assertionMap); + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); } /** - * @param string $username - * @return array + * @param string $reversedQuoteId + * @param int $customerId + * @return string */ - private function getHeaderMap(string $username = 'customer@example.com'): array - { - $password = 'password'; - /** @var CustomerTokenServiceInterface $customerTokenService */ - $customerTokenService = ObjectManager::getInstance() - ->get(CustomerTokenServiceInterface::class); - $customerToken = $customerTokenService->createCustomerAccessToken($username, $password); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - return $headerMap; + private function assignQuoteToCustomer( + string $reversedQuoteId = 'test_order_with_simple_product_without_address', + int $customerId = 1 + ): string { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + $quote->setCustomerId($customerId); + $this->quoteResource->save($quote); + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); } public function tearDown() diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingMethodOnCartTest.php deleted file mode 100644 index 1c6679ee30f2..000000000000 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingMethodOnCartTest.php +++ /dev/null @@ -1,252 +0,0 @@ -quoteResource = $objectManager->create(QuoteResource::class); - $this->quote = $objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSetShippingMethodOnCart() - { - $shippingCarrierCode = 'flatrate'; - $shippingMethodCode = 'flatrate'; - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $shippingAddress = $this->quote->getShippingAddress(); - $shippingAddressId = $shippingAddress->getId(); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $query = $this->prepareMutationQuery( - $maskedQuoteId, - $shippingMethodCode, - $shippingCarrierCode, - $shippingAddressId - ); - - $response = $this->sendRequestWithToken($query); - - self::assertArrayHasKey('setShippingMethodsOnCart', $response); - self::assertArrayHasKey('cart', $response['setShippingMethodsOnCart']); - self::assertEquals($maskedQuoteId, $response['setShippingMethodsOnCart']['cart']['cart_id']); - $addressesInformation = $response['setShippingMethodsOnCart']['cart']['shipping_addresses']; - self::assertCount(1, $addressesInformation); - self::assertEquals( - $addressesInformation[0]['selected_shipping_method']['code'], - $shippingCarrierCode . '_' . $shippingMethodCode - ); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSetShippingMethodWithWrongCartId() - { - $shippingCarrierCode = 'flatrate'; - $shippingMethodCode = 'flatrate'; - $shippingAddressId = '1'; - $maskedQuoteId = 'invalid'; - - $query = $this->prepareMutationQuery( - $maskedQuoteId, - $shippingMethodCode, - $shippingCarrierCode, - $shippingAddressId - ); - - self::expectExceptionMessage("Could not find a cart with ID \"$maskedQuoteId\""); - $this->sendRequestWithToken($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSetNonExistingShippingMethod() - { - $shippingCarrierCode = 'non'; - $shippingMethodCode = 'existing'; - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $shippingAddress = $this->quote->getShippingAddress(); - $shippingAddressId = $shippingAddress->getId(); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $query = $this->prepareMutationQuery( - $maskedQuoteId, - $shippingMethodCode, - $shippingCarrierCode, - $shippingAddressId - ); - - self::expectExceptionMessage("Carrier with such method not found: $shippingCarrierCode, $shippingMethodCode"); - $this->sendRequestWithToken($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSetShippingMethodWithNonExistingAddress() - { - $shippingCarrierCode = 'flatrate'; - $shippingMethodCode = 'flatrate'; - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $shippingAddressId = '-20'; - - $query = $this->prepareMutationQuery( - $maskedQuoteId, - $shippingMethodCode, - $shippingCarrierCode, - $shippingAddressId - ); - - self::expectExceptionMessage('The shipping address is missing. Set the address and try again.'); - $this->sendRequestWithToken($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSetShippingMethodByGuestToCustomerCart() - { - $shippingCarrierCode = 'flatrate'; - $shippingMethodCode = 'flatrate'; - $this->quoteResource->load( - $this->quote, - 'test_order_1', - 'reserved_order_id' - ); - $shippingAddress = $this->quote->getShippingAddress(); - $shippingAddressId = $shippingAddress->getId(); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - - $query = $this->prepareMutationQuery( - $maskedQuoteId, - $shippingMethodCode, - $shippingCarrierCode, - $shippingAddressId - ); - - self::expectExceptionMessage( - "The current user cannot perform operations on cart \"$maskedQuoteId\"" - ); - - $this->graphQlQuery($query); - } - - /** - * Generates query for setting the specified shipping method on cart - * - * @param string $maskedQuoteId - * @param string $shippingMethodCode - * @param string $shippingCarrierCode - * @param string $shippingAddressId - * @return string - */ - private function prepareMutationQuery( - string $maskedQuoteId, - string $shippingMethodCode, - string $shippingCarrierCode, - string $shippingAddressId - ) : string { - return <<customerTokenService->createCustomerAccessToken('customer@example.com', 'password'); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - - return $this->graphQlQuery($query, [], '', $headerMap); - } -}