Skip to content

Commit d3c7d49

Browse files
authored
ENGCOM-4769: [Checkout coverage] setGuestEmailOnCart mutation #564
2 parents af6820c + 692ee87 commit d3c7d49

File tree

11 files changed

+651
-37
lines changed

11 files changed

+651
-37
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Query\ResolverInterface;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\Quote\Model\Quote;
15+
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
16+
17+
/**
18+
* @inheritdoc
19+
*/
20+
class CartEmail implements ResolverInterface
21+
{
22+
/**
23+
* @var GetCartForUser
24+
*/
25+
private $getCartForUser;
26+
27+
/**
28+
* @param GetCartForUser $getCartForUser
29+
*/
30+
public function __construct(
31+
GetCartForUser $getCartForUser
32+
) {
33+
$this->getCartForUser = $getCartForUser;
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
40+
{
41+
if (!isset($value['model'])) {
42+
throw new LocalizedException(__('"model" value should be specified'));
43+
}
44+
/** @var Quote $cart */
45+
$cart = $value['model'];
46+
47+
return $cart->getCustomerEmail();
48+
}
49+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\Exception\CouldNotSaveException;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Query\ResolverInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\Framework\Validator\EmailAddress as EmailAddressValidator;
17+
use Magento\Quote\Api\CartRepositoryInterface;
18+
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
19+
20+
/**
21+
* @inheritdoc
22+
*/
23+
class SetGuestEmailOnCart implements ResolverInterface
24+
{
25+
/**
26+
* @var CartRepositoryInterface
27+
*/
28+
private $cartRepository;
29+
30+
/**
31+
* @var GetCartForUser
32+
*/
33+
private $getCartForUser;
34+
35+
/**
36+
* @var EmailAddressValidator
37+
*/
38+
private $emailValidator;
39+
40+
/**
41+
* @param GetCartForUser $getCartForUser
42+
* @param CartRepositoryInterface $cartRepository
43+
* @param EmailAddressValidator $emailValidator
44+
*/
45+
public function __construct(
46+
GetCartForUser $getCartForUser,
47+
CartRepositoryInterface $cartRepository,
48+
EmailAddressValidator $emailValidator
49+
) {
50+
$this->getCartForUser = $getCartForUser;
51+
$this->cartRepository = $cartRepository;
52+
$this->emailValidator = $emailValidator;
53+
}
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
59+
{
60+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
61+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
62+
}
63+
$maskedCartId = $args['input']['cart_id'];
64+
65+
if (!isset($args['input']['email']) || empty($args['input']['email'])) {
66+
throw new GraphQlInputException(__('Required parameter "email" is missing'));
67+
}
68+
69+
if (false === $this->emailValidator->isValid($args['input']['email'])) {
70+
throw new GraphQlInputException(__('Invalid email format'));
71+
}
72+
$email = $args['input']['email'];
73+
74+
$currentUserId = $context->getUserId();
75+
76+
if ($currentUserId !== 0) {
77+
throw new GraphQlInputException(__('The request is not allowed for logged in customers'));
78+
}
79+
80+
$cart = $this->getCartForUser->execute($maskedCartId, $currentUserId);
81+
$cart->setCustomerEmail($email);
82+
83+
try {
84+
$this->cartRepository->save($cart);
85+
} catch (CouldNotSaveException $e) {
86+
throw new LocalizedException(__($e->getMessage()), $e);
87+
}
88+
89+
return [
90+
'cart' => [
91+
'model' => $cart,
92+
],
93+
];
94+
}
95+
}

app/code/Magento/QuoteGraphQl/etc/schema.graphqls

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Mutation {
1717
setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart")
1818
setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart")
1919
setPaymentMethodOnCart(input: SetPaymentMethodOnCartInput): SetPaymentMethodOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentMethodOnCart")
20+
setGuestEmailOnCart(input: SetGuestEmailOnCartInput): SetGuestEmailOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetGuestEmailOnCart")
2021
placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder")
2122
}
2223

@@ -129,6 +130,11 @@ input PaymentMethodInput {
129130
purchase_order_number: String @doc(description:"Purchase order number")
130131
}
131132

133+
input SetGuestEmailOnCartInput {
134+
cart_id: String!
135+
email: String!
136+
}
137+
132138
type CartPrices {
133139
grand_total: Money
134140
subtotal_including_tax: Money
@@ -169,6 +175,7 @@ type PlaceOrderOutput {
169175
type Cart {
170176
items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems")
171177
applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon")
178+
email: String @resolver (class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartEmail")
172179
shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses")
173180
billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress")
174181
available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods")
@@ -272,6 +279,10 @@ type RemoveItemFromCartOutput {
272279
cart: Cart!
273280
}
274281

282+
type SetGuestEmailOnCartOutput {
283+
cart: Cart!
284+
}
285+
275286
type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") {
276287
customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions")
277288
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Quote\Customer;
9+
10+
use Magento\GraphQl\Quote\GetMaskedQuoteIdByReservedOrderId;
11+
use Magento\Integration\Api\CustomerTokenServiceInterface;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\TestFramework\TestCase\GraphQlAbstract;
14+
15+
/**
16+
* Test for getting email from cart
17+
*/
18+
class GetCartEmailTest extends GraphQlAbstract
19+
{
20+
/**
21+
* @var GetMaskedQuoteIdByReservedOrderId
22+
*/
23+
private $getMaskedQuoteIdByReservedOrderId;
24+
25+
/**
26+
* @var CustomerTokenServiceInterface
27+
*/
28+
private $customerTokenService;
29+
30+
protected function setUp()
31+
{
32+
$objectManager = Bootstrap::getObjectManager();
33+
$this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class);
34+
$this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class);
35+
}
36+
37+
/**
38+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
39+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php
40+
*/
41+
public function testGetCartEmail()
42+
{
43+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
44+
45+
$query = $this->getQuery($maskedQuoteId);
46+
$response = $this->graphQlQuery($query, [], '', $this->getHeaderMap());
47+
48+
$this->assertArrayHasKey('cart', $response);
49+
$this->assertArrayHasKey('email', $response['cart']);
50+
$this->assertEquals('[email protected]', $response['cart']['email']);
51+
}
52+
53+
/**
54+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
55+
* @expectedException \Exception
56+
* @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
57+
*/
58+
public function testGetCartEmailFromNonExistentCart()
59+
{
60+
$maskedQuoteId = 'non_existent_masked_id';
61+
$query = $this->getQuery($maskedQuoteId);
62+
63+
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
64+
}
65+
66+
/**
67+
* _security
68+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
69+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php
70+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/set_guest_email.php
71+
*/
72+
public function testGetEmailFromGuestCart()
73+
{
74+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
75+
$query = $this->getQuery($maskedQuoteId);
76+
77+
$this->expectExceptionMessage(
78+
"The current user cannot perform operations on cart \"{$maskedQuoteId}\""
79+
);
80+
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
81+
}
82+
83+
/**
84+
* _security
85+
* @magentoApiDataFixture Magento/Customer/_files/three_customers.php
86+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php
87+
*/
88+
public function testGetEmailFromAnotherCustomerCart()
89+
{
90+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
91+
$query = $this->getQuery($maskedQuoteId);
92+
93+
$this->expectExceptionMessage(
94+
"The current user cannot perform operations on cart \"{$maskedQuoteId}\""
95+
);
96+
$this->graphQlMutation($query, [], '', $this->getHeaderMap('[email protected]'));
97+
}
98+
99+
/**
100+
* @param string $maskedQuoteId
101+
* @return string
102+
*/
103+
private function getQuery(string $maskedQuoteId): string
104+
{
105+
return <<<QUERY
106+
{
107+
cart(cart_id:"$maskedQuoteId") {
108+
email
109+
}
110+
}
111+
QUERY;
112+
}
113+
114+
/**
115+
* @param string $username
116+
* @param string $password
117+
* @return array
118+
*/
119+
private function getHeaderMap(string $username = '[email protected]', string $password = 'password'): array
120+
{
121+
$customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password);
122+
$headerMap = ['Authorization' => 'Bearer ' . $customerToken];
123+
return $headerMap;
124+
}
125+
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetBillingAddressOnCartTest.php

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,24 @@ public function testSetBillingAddressWithoutRequiredParameters(string $input, st
493493
$this->graphQlMutation($query);
494494
}
495495

496+
/**
497+
* @return array
498+
*/
499+
public function dataProviderSetWithoutRequiredParameters(): array
500+
{
501+
return [
502+
'missed_billing_address' => [
503+
'cart_id: "cart_id_value"',
504+
'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!'
505+
. ' was not provided.',
506+
],
507+
'missed_cart_id' => [
508+
'billing_address: {}',
509+
'Required parameter "cart_id" is missing'
510+
]
511+
];
512+
}
513+
496514
/**
497515
* @magentoApiDataFixture Magento/Customer/_files/customer.php
498516
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
@@ -536,24 +554,6 @@ public function testSetNewBillingAddressWithRedundantStreetLine()
536554
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
537555
}
538556

539-
/**
540-
* @return array
541-
*/
542-
public function dataProviderSetWithoutRequiredParameters(): array
543-
{
544-
return [
545-
'missed_billing_address' => [
546-
'cart_id: "cart_id_value"',
547-
'Field SetBillingAddressOnCartInput.billing_address of required type BillingAddressInput!'
548-
. ' was not provided.',
549-
],
550-
'missed_cart_id' => [
551-
'billing_address: {}',
552-
'Required parameter "cart_id" is missing'
553-
]
554-
];
555-
}
556-
557557
/**
558558
* Verify the all the whitelisted fields for a New Address Object
559559
*

0 commit comments

Comments
 (0)