Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.

Commit 46d3839

Browse files
🔃 [Magento Community Engineering] Community Contributions - GraphQL
Accepted Community Pull Requests: - #443: GraphQL-196 Added swatch data to the configurable product option values (by @sergiy-v) - #1077: magento/graphql-ce#: [Test coverage]. Mutation: applyCouponToCart. Cover exception - Required parameter "coupon_code" is missing (by @atwixfirster) - #1073: #1054: Add e-mail address validation to customer data validation for GraphQL (by @vasylmalanka) - #1076: #1068: [Test Coverage] Extend test coverage for RemoveItemFromCart (by @atwixfirster) Fixed GitHub Issues: - #196: Swatches: expose Hex color code and swatch images (reported by @misha-kotov) has been fixed in #443 by @sergiy-v in 2.3-develop branch Related commits: 1. 9c4d685 2. bdb506e 3. cebac81 4. a1d671b 5. 4e2743b 6. 6dd69a5 7. fe79669 8. e6e0b71 9. 06bbaaf 10. 1e0e401 11. 931d0c5
2 parents fdd5bde + 4141ed8 commit 46d3839

File tree

16 files changed

+733
-16
lines changed

16 files changed

+733
-16
lines changed

app/code/Magento/CustomerGraphQl/Model/Customer/ValidateCustomerData.php

+19-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
namespace Magento\CustomerGraphQl\Model\Customer;
99

1010
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
use Magento\Framework\Validator\EmailAddress as EmailAddressValidator;
1112

1213
/**
13-
* Class ValidateCustomerData
14+
* Customer data validation used during customer account creation and updating
1415
*/
1516
class ValidateCustomerData
1617
{
@@ -21,14 +22,23 @@ class ValidateCustomerData
2122
*/
2223
private $getAllowedCustomerAttributes;
2324

25+
/**
26+
* @var EmailAddressValidator
27+
*/
28+
private $emailAddressValidator;
29+
2430
/**
2531
* ValidateCustomerData constructor.
2632
*
2733
* @param GetAllowedCustomerAttributes $getAllowedCustomerAttributes
34+
* @param EmailAddressValidator $emailAddressValidator
2835
*/
29-
public function __construct(GetAllowedCustomerAttributes $getAllowedCustomerAttributes)
30-
{
36+
public function __construct(
37+
GetAllowedCustomerAttributes $getAllowedCustomerAttributes,
38+
EmailAddressValidator $emailAddressValidator
39+
) {
3140
$this->getAllowedCustomerAttributes = $getAllowedCustomerAttributes;
41+
$this->emailAddressValidator = $emailAddressValidator;
3242
}
3343

3444
/**
@@ -59,5 +69,11 @@ public function execute(array $customerData): void
5969
__('Required parameters are missing: %1', [implode(', ', $errorInput)])
6070
);
6171
}
72+
73+
if (isset($customerData['email']) && !$this->emailAddressValidator->isValid($customerData['email'])) {
74+
throw new GraphQlInputException(
75+
__('"%1" is not a valid email address.', $customerData['email'])
76+
);
77+
}
6278
}
6379
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider;
9+
10+
use Magento\Swatches\Helper\Data as SwatchData;
11+
use Magento\Swatches\Helper\Media as SwatchesMedia;
12+
use Magento\Swatches\Model\Swatch;
13+
14+
/**
15+
* Data provider for options swatches.
16+
*/
17+
class SwatchDataProvider
18+
{
19+
/**
20+
* @var SwatchData
21+
*/
22+
private $swatchHelper;
23+
24+
/**
25+
* @var SwatchesMedia
26+
*/
27+
private $swatchMediaHelper;
28+
29+
/**
30+
* SwatchDataProvider constructor.
31+
*
32+
* @param SwatchData $swatchHelper
33+
* @param SwatchesMedia $swatchMediaHelper
34+
*/
35+
public function __construct(
36+
SwatchData $swatchHelper,
37+
SwatchesMedia $swatchMediaHelper
38+
) {
39+
$this->swatchHelper = $swatchHelper;
40+
$this->swatchMediaHelper = $swatchMediaHelper;
41+
}
42+
43+
/**
44+
* Returns swatch data by option ID.
45+
*
46+
* @param string $optionId
47+
* @return array|null
48+
*/
49+
public function getData(string $optionId): ?array
50+
{
51+
$swatches = $this->swatchHelper->getSwatchesByOptionsId([$optionId]);
52+
if (!isset($swatches[$optionId]['type'], $swatches[$optionId]['value'])) {
53+
return null;
54+
}
55+
$type = (int)$swatches[$optionId]['type'];
56+
$value = $swatches[$optionId]['value'];
57+
$data = ['value' => $value, 'type' => $type];
58+
if ($type === Swatch::SWATCH_TYPE_VISUAL_IMAGE) {
59+
$data['thumbnail'] = $this->swatchMediaHelper->getSwatchAttributeImage(
60+
Swatch::SWATCH_THUMBNAIL_NAME,
61+
$value
62+
);
63+
}
64+
return $data;
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\ResolverInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13+
use Magento\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider\SwatchDataProvider;
14+
15+
/**
16+
* Class SwatchData
17+
*
18+
* Product swatch data resolver, used for GraphQL request processing
19+
*/
20+
class SwatchData implements ResolverInterface
21+
{
22+
/**
23+
* @var SwatchDataProvider
24+
*/
25+
private $swatchDataProvider;
26+
27+
/**
28+
* SwatchData constructor.
29+
*
30+
* @param SwatchDataProvider $swatchDataProvider
31+
*/
32+
public function __construct(
33+
SwatchDataProvider $swatchDataProvider
34+
) {
35+
$this->swatchDataProvider = $swatchDataProvider;
36+
}
37+
38+
/**
39+
* @inheritdoc
40+
*/
41+
public function resolve(
42+
Field $field,
43+
$context,
44+
ResolveInfo $info,
45+
array $value = null,
46+
array $args = null
47+
) {
48+
return $this->swatchDataProvider->getData($value['value_index']);
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface;
12+
use Magento\Swatches\Model\Swatch;
13+
14+
/**
15+
* Resolver for swatch data interface.
16+
*/
17+
class SwatchDataTypeResolver implements TypeResolverInterface
18+
{
19+
/**
20+
* @inheritdoc
21+
*/
22+
public function resolveType(array $data): string
23+
{
24+
switch ($data['type']) {
25+
case Swatch::SWATCH_TYPE_TEXTUAL:
26+
return 'TextSwatchData';
27+
case Swatch::SWATCH_TYPE_VISUAL_COLOR:
28+
return 'ColorSwatchData';
29+
case Swatch::SWATCH_TYPE_VISUAL_IMAGE:
30+
return 'ImageSwatchData';
31+
default:
32+
throw new LocalizedException(__('Unsupported swatch type'));
33+
}
34+
}
35+
}

app/code/Magento/SwatchesGraphQl/etc/graphql/di.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
</argument>
1717
</arguments>
1818
</type>
19-
</config>
19+
</config>

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

+21-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,24 @@ type SwatchLayerFilterItem implements LayerFilterItemInterface, SwatchLayerFilte
2626
type SwatchData {
2727
type: String @doc(description: "Type of swatch filter item: 1 - text, 2 - image")
2828
value: String @doc(description: "Value for swatch item (text or image link)")
29-
}
29+
}
30+
31+
type ConfigurableProductOptionsValues {
32+
swatch_data: SwatchDataInterface @doc(description: "Swatch data for configurable product option") @resolver(class: "Magento\\SwatchesGraphQl\\Model\\Resolver\\Product\\Options\\SwatchData")
33+
}
34+
35+
interface SwatchDataInterface @typeResolver(class: "Magento\\SwatchesGraphQl\\Model\\Resolver\\Product\\Options\\SwatchDataTypeResolver") {
36+
value: String @doc(description: "Value of swatch item (HEX color code, image link or textual value)")
37+
}
38+
39+
type ImageSwatchData implements SwatchDataInterface {
40+
thumbnail: String @doc(description: "Thumbnail swatch image URL")
41+
}
42+
43+
type TextSwatchData implements SwatchDataInterface {
44+
45+
}
46+
47+
type ColorSwatchData implements SwatchDataInterface {
48+
49+
}

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

+32-11
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,25 @@ public function testCreateCustomerIfEmailMissed()
172172
}
173173

174174
/**
175-
* @expectedException \Exception
176-
* @expectedExceptionMessage "Email" is not a valid email address.
175+
* @dataProvider invalidEmailAddressDataProvider
176+
*
177+
* @param string $email
178+
* @throws \Exception
177179
*/
178-
public function testCreateCustomerIfEmailIsNotValid()
180+
public function testCreateCustomerIfEmailIsNotValid(string $email)
179181
{
180-
$newFirstname = 'Richard';
181-
$newLastname = 'Rowe';
182-
$currentPassword = 'test123#';
183-
$newEmail = 'email';
182+
$firstname = 'Richard';
183+
$lastname = 'Rowe';
184+
$password = 'test123#';
184185

185186
$query = <<<QUERY
186187
mutation {
187188
createCustomer(
188189
input: {
189-
firstname: "{$newFirstname}"
190-
lastname: "{$newLastname}"
191-
email: "{$newEmail}"
192-
password: "{$currentPassword}"
190+
firstname: "{$firstname}"
191+
lastname: "{$lastname}"
192+
email: "{$email}"
193+
password: "{$password}"
193194
is_subscribed: true
194195
}
195196
) {
@@ -203,9 +204,29 @@ public function testCreateCustomerIfEmailIsNotValid()
203204
}
204205
}
205206
QUERY;
207+
$this->expectExceptionMessage('"' . $email . '" is not a valid email address.');
206208
$this->graphQlMutation($query);
207209
}
208210

211+
/**
212+
* @return array
213+
*/
214+
public function invalidEmailAddressDataProvider(): array
215+
{
216+
return [
217+
['plainaddress'],
218+
219+
['#@%^%#$@#$@#.com'],
220+
['@example.com'],
221+
['Joe Smith <[email protected]>'],
222+
['email.example.com'],
223+
['email@[email protected]'],
224+
['[email protected] (Joe Smith)'],
225+
['email@example'],
226+
['“email”@example.com'],
227+
];
228+
}
229+
209230
/**
210231
* @expectedException \Exception
211232
* @expectedExceptionMessage Field "test123" is not defined by type CustomerInput.

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

+18
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ public function testApplyCouponToAnotherCustomerCart()
128128
$this->graphQlMutation($query, [], '', $this->getHeaderMap('[email protected]'));
129129
}
130130

131+
/**
132+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
133+
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
134+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php
135+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php
136+
*
137+
* @expectedException \Exception
138+
* @expectedExceptionMessage Required parameter "coupon_code" is missing
139+
*/
140+
public function testApplyEmptyCouponCodeToCustomerCart()
141+
{
142+
$couponCode = '';
143+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
144+
$query = $this->getQuery($maskedQuoteId, $couponCode);
145+
146+
$this->graphQlMutation($query);
147+
}
148+
131149
/**
132150
* @magentoApiDataFixture Magento/Customer/_files/customer.php
133151
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php

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

+36
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,42 @@ public function testRemoveItemFromAnotherCustomerCart()
155155
$this->graphQlMutation($query, [], '', $this->getHeaderMap('[email protected]'));
156156
}
157157

158+
/**
159+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
160+
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
161+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php
162+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php
163+
*
164+
* @expectedException \Exception
165+
* @expectedExceptionMessage Required parameter "cart_id" is missing
166+
*/
167+
public function testWithoutRequiredCartIdParameter()
168+
{
169+
$maskedQuoteId = '';
170+
$itemId = $this->getQuoteItemIdByReservedQuoteIdAndSku->execute('test_quote', 'simple_product');
171+
172+
$query = $this->getQuery($maskedQuoteId, $itemId);
173+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
174+
}
175+
176+
/**
177+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
178+
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
179+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php
180+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php
181+
*
182+
* @expectedException \Exception
183+
* @expectedExceptionMessage Required parameter "cart_item_id" is missing.
184+
*/
185+
public function testWithoutRequiredCartItemIdParameter()
186+
{
187+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
188+
$itemId = 0;
189+
190+
$query = $this->getQuery($maskedQuoteId, $itemId);
191+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
192+
}
193+
158194
/**
159195
* @param string $maskedQuoteId
160196
* @param int $itemId

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/ApplyCouponToCartTest.php

+17
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,23 @@ public function testApplyCouponToCustomerCart()
100100
$this->graphQlMutation($query);
101101
}
102102

103+
/**
104+
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
105+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php
106+
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php
107+
*
108+
* @expectedException \Exception
109+
* @expectedExceptionMessage Required parameter "coupon_code" is missing
110+
*/
111+
public function testApplyEmptyCouponCodeToCart()
112+
{
113+
$couponCode = '';
114+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote');
115+
$query = $this->getQuery($maskedQuoteId, $couponCode);
116+
117+
$this->graphQlMutation($query);
118+
}
119+
103120
/**
104121
* @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php
105122
* @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php

0 commit comments

Comments
 (0)