Skip to content

Commit a918fa9

Browse files
author
Vitaliy Boyko
committed
graphQl-825: Add downloadable product to Cart with customizable options
1 parent 7cf99d1 commit a918fa9

File tree

6 files changed

+377
-73
lines changed

6 files changed

+377
-73
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
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;
9+
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Framework\ObjectManager\ObjectManager;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\TestFramework\TestCase\GraphQlAbstract;
14+
15+
/**
16+
* Test cases for adding downloadable product with custom options to cart.
17+
*/
18+
class AddDownloadableProductWithCustomOptionsToCartTest extends GraphQlAbstract
19+
{
20+
/**
21+
* @var GetMaskedQuoteIdByReservedOrderId
22+
*/
23+
private $getMaskedQuoteIdByReservedOrderId;
24+
25+
/**
26+
* @var ObjectManager
27+
*/
28+
private $objectManager;
29+
30+
/**
31+
* @var GetCustomOptionsValuesForQueryBySku
32+
*/
33+
private $getCustomOptionsValuesForQueryBySku;
34+
35+
/**
36+
* @inheritdoc
37+
*/
38+
protected function setUp()
39+
{
40+
$this->objectManager = Bootstrap::getObjectManager();
41+
$this->getMaskedQuoteIdByReservedOrderId = $this->objectManager->get(GetMaskedQuoteIdByReservedOrderId::class);
42+
$this->getCustomOptionsValuesForQueryBySku = $this->objectManager->get(GetCustomOptionsValuesForQueryBySku::class);
43+
}
44+
45+
/**
46+
* @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_custom_options.php
47+
* @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
48+
*/
49+
public function testAddDownloadableProductWithOptions()
50+
{
51+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1');
52+
53+
$sku = 'downloadable-product-with-purchased-separately-links';
54+
$qty = 1;
55+
$links = $this->getProductsLinks($sku);
56+
$linkId = key($links);
57+
58+
$customOptionsValues = $this->getCustomOptionsValuesForQueryBySku->execute($sku);
59+
/* Generate customizable options fragment for GraphQl request */
60+
$queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues));
61+
$customizableOptions = "customizable_options: {$queryCustomizableOptionValues}";
62+
63+
$query = $this->getQuery($maskedQuoteId, $qty, $sku, $customizableOptions, $linkId);
64+
65+
$response = $this->graphQlMutation($query);
66+
self::assertArrayHasKey('items', $response['addDownloadableProductsToCart']['cart']);
67+
self::assertCount($qty, $response['addDownloadableProductsToCart']['cart']);
68+
$customizableOptionsOutput = $response['addDownloadableProductsToCart']['cart']['items'][0]['customizable_options'];
69+
$assignedOptionsCount = count($customOptionsValues);
70+
for ($counter = 0; $counter < $assignedOptionsCount; $counter++) {
71+
$expectedValues = $this->buildExpectedValuesArray($customOptionsValues[$counter]['value_string']);
72+
self::assertEquals(
73+
$expectedValues,
74+
$customizableOptionsOutput[$counter]['values']
75+
);
76+
}
77+
}
78+
79+
/**
80+
* @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_custom_options.php
81+
* @magentoApiDataFixture Magento/Checkout/_files/active_quote.php
82+
*
83+
* @expectedException \Exception
84+
* @expectedExceptionMessage The product's required option(s) weren't entered. Make sure the options are entered and try again.
85+
*/
86+
public function testAddDownloadableProductWithMissedRequiredOptionsSet()
87+
{
88+
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1');
89+
90+
$sku = 'downloadable-product-with-purchased-separately-links';
91+
$qty = 1;
92+
$links = $this->getProductsLinks($sku);
93+
$linkId = key($links);
94+
$customizableOptions = '';
95+
96+
$query = $this->getQuery($maskedQuoteId, $qty, $sku, $customizableOptions, $linkId);
97+
98+
$this->graphQlMutation($query);
99+
}
100+
101+
/**
102+
* Function returns array of all product's links
103+
*
104+
* @param string $sku
105+
* @return array
106+
*/
107+
private function getProductsLinks(string $sku) : array
108+
{
109+
$result = [];
110+
$productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
111+
112+
$product = $productRepository->get($sku, false, null, true);
113+
114+
foreach ($product->getDownloadableLinks() as $linkObject) {
115+
$result[$linkObject->getLinkId()] = [
116+
'title' => $linkObject->getTitle(),
117+
'link_type' => null, //deprecated field
118+
'price' => $linkObject->getPrice(),
119+
];
120+
}
121+
122+
return $result;
123+
}
124+
125+
/**
126+
* Build the part of expected response.
127+
*
128+
* @param string $assignedValue
129+
* @return array
130+
*/
131+
private function buildExpectedValuesArray(string $assignedValue) : array
132+
{
133+
$assignedOptionsArray = explode(',', trim($assignedValue, '[]'));
134+
$expectedArray = [];
135+
foreach ($assignedOptionsArray as $assignedOption) {
136+
$expectedArray[] = ['value' => $assignedOption];
137+
}
138+
return $expectedArray;
139+
}
140+
141+
/**
142+
* Returns GraphQl query string
143+
*
144+
* @param string $maskedQuoteId
145+
* @param int $qty
146+
* @param string $sku
147+
* @param string $customizableOptions
148+
* @param $linkId
149+
* @return string
150+
*/
151+
private function getQuery(string $maskedQuoteId, int $qty, string $sku, string $customizableOptions, $linkId): string
152+
{
153+
$query = <<<MUTATION
154+
mutation {
155+
addDownloadableProductsToCart(
156+
input: {
157+
cart_id: "{$maskedQuoteId}",
158+
cart_items: [
159+
{
160+
data: {
161+
quantity: {$qty},
162+
sku: "{$sku}"
163+
},
164+
{$customizableOptions}
165+
downloadable_product_links: [
166+
{
167+
link_id: {$linkId}
168+
}
169+
]
170+
}
171+
]
172+
}
173+
) {
174+
cart {
175+
items {
176+
quantity
177+
... on DownloadableCartItem {
178+
customizable_options {
179+
label
180+
values {
181+
value
182+
}
183+
}
184+
}
185+
}
186+
}
187+
}
188+
}
189+
MUTATION;
190+
return $query;
191+
}
192+
}

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

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ class AddSimpleProductWithCustomOptionsToCartTest extends GraphQlAbstract
2626
*/
2727
private $productCustomOptionsRepository;
2828

29+
/**
30+
* @var GetCustomOptionsValuesForQueryBySku
31+
*/
32+
private $getCustomOptionsValuesForQueryBySku;
33+
2934
/**
3035
* @inheritdoc
3136
*/
@@ -34,6 +39,7 @@ protected function setUp()
3439
$objectManager = Bootstrap::getObjectManager();
3540
$this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class);
3641
$this->productCustomOptionsRepository = $objectManager->get(ProductCustomOptionRepositoryInterface::class);
42+
$this->getCustomOptionsValuesForQueryBySku = $objectManager->get(GetCustomOptionsValuesForQueryBySku::class);
3743
}
3844

3945
/**
@@ -49,7 +55,7 @@ public function testAddSimpleProductWithOptions()
4955
$quantity = 1;
5056
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1');
5157

52-
$customOptionsValues = $this->getCustomOptionsValuesForQuery($sku);
58+
$customOptionsValues = $this->getCustomOptionsValuesForQueryBySku->execute($sku);
5359
/* Generate customizable options fragment for GraphQl request */
5460
$queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues));
5561

@@ -135,41 +141,6 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity, s
135141
QUERY;
136142
}
137143

138-
/**
139-
* Generate an array with test values for customizable options
140-
* based on the option type
141-
*
142-
* @param string $sku
143-
* @return array
144-
*/
145-
private function getCustomOptionsValuesForQuery(string $sku): array
146-
{
147-
$customOptions = $this->productCustomOptionsRepository->getList($sku);
148-
$customOptionsValues = [];
149-
150-
foreach ($customOptions as $customOption) {
151-
$optionType = $customOption->getType();
152-
if ($optionType == 'field' || $optionType == 'area') {
153-
$customOptionsValues[] = [
154-
'id' => (int)$customOption->getOptionId(),
155-
'value_string' => 'test'
156-
];
157-
} elseif ($optionType == 'drop_down') {
158-
$optionSelectValues = $customOption->getValues();
159-
$customOptionsValues[] = [
160-
'id' => (int)$customOption->getOptionId(),
161-
'value_string' => reset($optionSelectValues)->getOptionTypeId()
162-
];
163-
} elseif ($optionType == 'multiple') {
164-
$customOptionsValues[] = [
165-
'id' => (int)$customOption->getOptionId(),
166-
'value_string' => '[' . implode(',', array_keys($customOption->getValues())) . ']'
167-
];
168-
}
169-
}
170-
return $customOptionsValues;
171-
}
172-
173144
/**
174145
* Build the part of expected response.
175146
*

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

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ class AddVirtualProductWithCustomOptionsToCartTest extends GraphQlAbstract
2626
*/
2727
private $productCustomOptionsRepository;
2828

29+
/**
30+
* @var GetCustomOptionsValuesForQueryBySku
31+
*/
32+
private $getCustomOptionsValuesForQueryBySku;
33+
2934
/**
3035
* @inheritdoc
3136
*/
@@ -34,6 +39,7 @@ protected function setUp()
3439
$objectManager = Bootstrap::getObjectManager();
3540
$this->getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class);
3641
$this->productCustomOptionsRepository = $objectManager->get(ProductCustomOptionRepositoryInterface::class);
42+
$this->getCustomOptionsValuesForQueryBySku = $objectManager->get(GetCustomOptionsValuesForQueryBySku::class);
3743
}
3844

3945
/**
@@ -49,7 +55,7 @@ public function testAddVirtualProductWithOptions()
4955
$quantity = 1;
5056
$maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1');
5157

52-
$customOptionsValues = $this->getCustomOptionsValuesForQuery($sku);
58+
$customOptionsValues = $this->getCustomOptionsValuesForQueryBySku->execute($sku);
5359
/* Generate customizable options fragment for GraphQl request */
5460
$queryCustomizableOptionValues = preg_replace('/"([^"]+)"\s*:\s*/', '$1:', json_encode($customOptionsValues));
5561

@@ -135,42 +141,6 @@ private function getQuery(string $maskedQuoteId, string $sku, float $quantity, s
135141
QUERY;
136142
}
137143

138-
/**
139-
* Generate an array with test values for customizable options
140-
* based on the option type
141-
*
142-
* @param string $sku
143-
* @return array
144-
*/
145-
private function getCustomOptionsValuesForQuery(string $sku): array
146-
{
147-
$customOptions = $this->productCustomOptionsRepository->getList($sku);
148-
$customOptionsValues = [];
149-
150-
foreach ($customOptions as $customOption) {
151-
$optionType = $customOption->getType();
152-
if ($optionType == 'field' || $optionType == 'area') {
153-
$customOptionsValues[] = [
154-
'id' => (int)$customOption->getOptionId(),
155-
'value_string' => 'test'
156-
];
157-
} elseif ($optionType == 'drop_down') {
158-
$optionSelectValues = $customOption->getValues();
159-
$customOptionsValues[] = [
160-
'id' => (int)$customOption->getOptionId(),
161-
'value_string' => reset($optionSelectValues)->getOptionTypeId()
162-
];
163-
} elseif ($optionType == 'multiple') {
164-
$customOptionsValues[] = [
165-
'id' => (int)$customOption->getOptionId(),
166-
'value_string' => '[' . implode(',', array_keys($customOption->getValues())) . ']'
167-
];
168-
}
169-
}
170-
171-
return $customOptionsValues;
172-
}
173-
174144
/**
175145
* Build the part of expected response.
176146
*

0 commit comments

Comments
 (0)