Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
ConfigurableProductViewTest.php
Go to the documentation of this file.
1 <?php
6 declare(strict_types=1);
7 
9 
17 
19 {
23  private $configurableOptions = [];
24 
29  public function testQueryConfigurableProductLinks()
30  {
31  $productSku = 'configurable';
32 
33  $query
34  = <<<QUERY
35 {
36  products(filter: {sku: {eq: "{$productSku}"}}) {
37  items {
38  id
39  attribute_set_id
40  created_at
41  name
42  sku
43  type_id
44  updated_at
45  ... on PhysicalProductInterface {
46  weight
47  }
48  price {
49  minimalPrice {
50  amount {
51  value
52  currency
53  }
54  adjustments {
55  amount {
56  value
57  currency
58  }
59  code
60  description
61  }
62  }
63  maximalPrice {
64  amount {
65  value
66  currency
67  }
68  adjustments {
69  amount {
70  value
71  currency
72  }
73  code
74  description
75  }
76  }
77  regularPrice {
78  amount {
79  value
80  currency
81  }
82  adjustments {
83  amount {
84  value
85  currency
86  }
87  code
88  description
89  }
90  }
91  }
93  configurable_options {
94  id
95  attribute_id
96  label
97  position
98  use_default
99  attribute_code
100  values {
101  value_index
102  label
103  store_label
104  default_label
105  use_default_value
106  }
107  product_id
108  }
109  variants {
110  product {
111  id
112  name
113  sku
114  attribute_set_id
115  ... on PhysicalProductInterface {
116  weight
117  }
118  created_at
119  updated_at
120  price {
121  minimalPrice {
122  amount {
123  value
124  currency
125  }
126  adjustments {
127  amount {
128  value
129  currency
130  }
131  code
132  description
133  }
134  }
135  maximalPrice {
136  amount {
137  value
138  currency
139  }
140  adjustments {
141  amount {
142  value
143  currency
144  }
145  code
146  description
147  }
148  }
149  regularPrice {
150  amount {
151  value
152  currency
153  }
154  adjustments {
155  amount {
156  value
157  currency
158  }
159  code
160  description
161  }
162  }
163  }
164  categories {
165  id
166  }
167  media_gallery_entries {
168  disabled
169  file
170  id
171  label
172  media_type
173  position
174  types
175  content {
176  base64_encoded_data
177  type
178  name
179  }
180  video_content {
181  media_type
182  video_description
183  video_metadata
184  video_provider
185  video_title
186  video_url
187  }
188  }
189  }
190  attributes {
191  label
192  code
193  value_index
194  }
195  }
196  }
197  }
198  }
199 }
200 QUERY;
201 
202  $response = $this->graphQlQuery($query);
203 
208  $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
209  $product = $productRepository->get($productSku, false, null, true);
210 
211  $this->assertArrayHasKey('products', $response);
212  $this->assertArrayHasKey('items', $response['products']);
213  $this->assertEquals(1, count($response['products']['items']));
214  $this->assertArrayHasKey(0, $response['products']['items']);
215  $this->assertBaseFields($product, $response['products']['items'][0]);
216  $this->assertConfigurableProductOptions($response['products']['items'][0]);
217  $this->assertConfigurableVariants($response['products']['items'][0]);
218  }
219 
224  private function assertBaseFields($product, $actualResponse)
225  {
227  $priceInfoFactory = ObjectManager::getInstance()->get(\Magento\Framework\Pricing\PriceInfo\Factory::class);
228  $priceInfo = $priceInfoFactory->create($product);
230  $finalPrice = $priceInfo->getPrice(FinalPrice::PRICE_CODE);
231  $minimalPriceAmount = $finalPrice->getMinimalPrice();
232  $maximalPriceAmount = $finalPrice->getMaximalPrice();
233  $regularPriceAmount = $priceInfo->getPrice(RegularPrice::PRICE_CODE)->getAmount();
235  $metadataPool = ObjectManager::getInstance()->get(MetadataPool::class);
236  // ['product_object_field_name', 'expected_value']
237  $assertionMap = [
238  ['response_field' => 'attribute_set_id', 'expected_value' => $product->getAttributeSetId()],
239  ['response_field' => 'created_at', 'expected_value' => $product->getCreatedAt()],
240  [
241  'response_field' => 'id',
242  'expected_value' => $product->getData(
243  $metadataPool->getMetadata(
244  ProductInterface::class
245  )->getLinkField()
246  )
247  ],
248  ['response_field' => 'name', 'expected_value' => $product->getName()],
249  ['response_field' => 'sku', 'expected_value' => $product->getSku()],
250  ['response_field' => 'type_id', 'expected_value' => $product->getTypeId()],
251  ['response_field' => 'updated_at', 'expected_value' => $product->getUpdatedAt()],
252  ['response_field' => 'weight', 'expected_value' => $product->getWeight()],
253  [
254  'response_field' => 'price',
255  'expected_value' => [
256  'minimalPrice' => [
257  'amount' => [
258  'value' => $minimalPriceAmount->getValue(),
259  'currency' => 'USD'
260  ],
261  'adjustments' => []
262  ],
263  'regularPrice' => [
264  'amount' => [
265  'value' => $maximalPriceAmount->getValue(),
266  'currency' => 'USD'
267  ],
268  'adjustments' => []
269  ],
270  'maximalPrice' => [
271  'amount' => [
272  'value' => $regularPriceAmount->getValue(),
273  'currency' => 'USD'
274  ],
275  'adjustments' => []
276  ],
277  ]
278  ],
279  ];
280 
281  $this->assertResponseFields($actualResponse, $assertionMap);
282  }
283 
291  private function assertConfigurableVariants($actualResponse)
292  {
293  $this->assertNotEmpty(
294  $actualResponse['variants'],
295  "Precondition failed: 'variants' must not be empty"
296  );
297  foreach ($actualResponse['variants'] as $variantKey => $variantArray) {
298  $this->assertNotEmpty($variantArray);
299  $this->assertNotEmpty($variantArray['product']);
300  $this->assertTrue(
301  isset($variantArray['product']['id']),
302  'variant product elements don\'t contain id key'
303  );
304  $indexValue = $variantArray['product']['sku'];
305  unset($variantArray['product']['id']);
306  $this->assertTrue(
307  isset($variantArray['product']['categories']),
308  'variant product doesn\'t contain categories key'
309  );
310  $productRepository = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
312  $childProduct = $productRepository->get($indexValue);
313 
315  $links = $childProduct->getExtensionAttributes()->getCategoryLinks();
316  $this->assertCount(1, $links, "Precondition failed, incorrect number of categories.");
317  $id =$links[0]->getCategoryId();
318 
319  $actualValue
320  = $actualResponse['variants'][$variantKey]['product']['categories'][0];
321  $this->assertEquals($actualValue, ['id' => $id]);
322  unset($variantArray['product']['categories']);
323 
324  $mediaGalleryEntries = $childProduct->getMediaGalleryEntries();
325  $this->assertCount(
326  1,
327  $mediaGalleryEntries,
328  "Precondition failed since there are incorrect number of media gallery entries"
329  );
330  $this->assertTrue(
331  is_array(
332  $actualResponse['variants']
333  [$variantKey]
334  ['product']
335  ['media_gallery_entries']
336  )
337  );
338  $this->assertCount(
339  1,
340  $actualResponse['variants'][$variantKey]['product']['media_gallery_entries'],
341  "there must be 1 record in the media gallery"
342  );
343  $mediaGalleryEntry = $mediaGalleryEntries[0];
344  $this->assertResponseFields(
345  $actualResponse['variants']
346  [$variantKey]
347  ['product']
348  ['media_gallery_entries'][0],
349  [
350  'disabled' => (bool)$mediaGalleryEntry->isDisabled(),
351  'file' => $mediaGalleryEntry->getFile(),
352  'id' => $mediaGalleryEntry->getId(),
353  'label' => $mediaGalleryEntry->getLabel(),
354  'media_type' => $mediaGalleryEntry->getMediaType(),
355  'position' => $mediaGalleryEntry->getPosition()
356  ]
357  );
358  $videoContent = $mediaGalleryEntry->getExtensionAttributes()->getVideoContent();
359  $this->assertResponseFields(
360  $actualResponse['variants']
361  [$variantKey]
362  ['product']
363  ['media_gallery_entries']
364  [0]
365  ['video_content'],
366  [
367  'media_type' =>$videoContent->getMediaType(),
368  'video_description' => $videoContent->getVideoDescription(),
369  'video_metadata' =>$videoContent->getVideoMetadata(),
370  'video_provider' => $videoContent->getVideoProvider(),
371  'video_title' => $videoContent->getVideoTitle(),
372  'video_url' => $videoContent->getVideoUrl()
373  ]
374  );
375  unset($variantArray['product']['media_gallery_entries']);
376 
377  foreach ($variantArray['product'] as $key => $value) {
378  if ($key !== 'price') {
379  $this->assertEquals($value, $childProduct->getData($key));
380  }
381  }
382  //assert prices
383  $this->assertEquals(
384  [
385  'minimalPrice' => [
386  'amount' => [
387  'value' => $childProduct->getFinalPrice(),
388  'currency' => 'USD'
389  ],
390  'adjustments' => []
391  ],
392  'regularPrice' => [
393  'amount' => [
394  'value' => $childProduct->getFinalPrice(),
395  'currency' => 'USD'
396  ],
397  'adjustments' => []
398  ],
399  'maximalPrice' => [
400  'amount' => [
401  'value' => $childProduct->getFinalPrice(),
402  'currency' => 'USD'
403  ],
404  'adjustments' => []
405  ],
406  ],
407  $variantArray['product']['price']
408  );
409  $configurableOptions = $this->getConfigurableOptions();
410  foreach ($variantArray['attributes'] as $attribute) {
411  $hasAssertion = false;
412  foreach ($configurableOptions as $option) {
413  foreach ($option['options'] as $value) {
414  if ((int)$value['value_index'] === (int)$attribute['value_index']) {
415  $this->assertEquals((int)$attribute['value_index'], (int)$value['value_index']);
416  $this->assertEquals($attribute['label'], $value['label']);
417  $hasAssertion = true;
418  }
419  }
420  $this->assertEquals($attribute['code'], $option['attribute_code']);
421  }
422  if (!$hasAssertion) {
423  $this->fail('variant did not contain correct attributes');
424  }
425  }
426  }
427  }
428 
429  private function assertConfigurableProductOptions($actualResponse)
430  {
431  $this->assertNotEmpty(
432  $actualResponse['configurable_options'],
433  "Precondition failed: 'configurable_options' must not be empty"
434  );
435  $configurableAttributeOptions = $this->getConfigurableOptions();
436  $configurableAttributeOption = array_shift($configurableAttributeOptions);
437 
438  $this->assertEquals(
439  $actualResponse['configurable_options'][0]['id'],
440  $configurableAttributeOption['id']
441  );
442  $this->assertEquals(
443  $actualResponse['configurable_options'][0]['use_default'],
444  (bool)$configurableAttributeOption['use_default']
445  );
446  $this->assertEquals(
447  $actualResponse['configurable_options'][0]['attribute_id'],
448  $configurableAttributeOption['attribute_id']
449  );
450  $this->assertEquals(
451  $actualResponse['configurable_options'][0]['label'],
452  $configurableAttributeOption['label']
453  );
454  $this->assertEquals(
455  $actualResponse['configurable_options'][0]['position'],
456  $configurableAttributeOption['position']
457  );
458  $this->assertEquals(
459  $actualResponse['configurable_options'][0]['product_id'],
460  $configurableAttributeOption['product_id']
461  );
462  $this->assertEquals(
463  $actualResponse['configurable_options'][0]['attribute_code'],
464  $configurableAttributeOption['attribute_code']
465  );
466  foreach ($actualResponse['configurable_options'][0]['values'] as $key => $value) {
467  $this->assertEquals(
468  $value['label'],
469  $configurableAttributeOption['options'][$key]['label']
470  );
471  $this->assertEquals(
472  $value['store_label'],
473  $configurableAttributeOption['options'][$key]['store_label']
474  );
475  $this->assertEquals(
476  $value['default_label'],
477  $configurableAttributeOption['options'][$key]['default_label']
478  );
479  $this->assertEquals(
480  $value['use_default_value'],
481  $configurableAttributeOption['options'][$key]['use_default_value']
482  );
483  $this->assertEquals(
484  (int)$value['value_index'],
485  (int)$configurableAttributeOption['options'][$key]['value_index']
486  );
487  }
488  }
489 
490  private function getConfigurableOptions()
491  {
492  if (!empty($this->configurableOptions)) {
493  return $this->configurableOptions;
494  }
495  $productSku = 'configurable';
497  $productRepo = ObjectManager::getInstance()->get(ProductRepositoryInterface::class);
498  $product = $productRepo->get($productSku);
499  $configurableAttributeOptions = $product->getExtensionAttributes()->getConfigurableProductOptions();
500  $configurableAttributeOptionsData = [];
501  foreach ($configurableAttributeOptions as $option) {
502  $configurableAttributeOptionsData[$option->getId()] = $option->getData();
503  $configurableAttributeOptionsData[$option->getId()]['id'] = $option->getId();
504  $configurableAttributeOptionsData[$option->getId()]['attribute_code']
505  = $option->getProductAttribute()->getAttributeCode();
506  unset($configurableAttributeOptionsData[$option->getId()]['values']);
507  foreach ($option->getValues() as $value) {
508  $configurableAttributeOptionsData[$option->getId()]['values'][$value->getId()] = $value->getData();
509  $configurableAttributeOptionsData[$option->getId()]['values'][$value->getId()]['label']
510  = $value->getLabel();
511  }
512  }
513 
514  return $this->configurableOptions = $configurableAttributeOptionsData;
515  }
516 }
$response
Definition: 404.php:11
$block setTitle( 'CMS Block Title') -> setIdentifier('fixture_block') ->setContent('< h1 >Fixture Block Title</h1 >< a href=" store url</a><p> Config value
Definition: block.php:9
if( $block->displayPriceExclTax()||$block->displayBothPrices())(__('Excl. Tax')) ?>"> <?php if ($block -> displayPriceWithWeeeDetails()): ?> <span class="cart-tax-total" data-mage-init=' Magento Weee Helper Data Magento Weee Helper Data title amount
Definition: unit.phtml:68
$id
Definition: fieldset.phtml:14
assertResponseFields($actualResponse, $assertionMap)
$value
Definition: gender.phtml:16
taxRateField this edit on("click.mselect-delete", ".mselect-delete", function() { if(!confirm('<?=/*@escapeNotVerified */__( 'Do you really want to delete this tax rate?') ?>')) { return;} var that=$(this), select=that.closest('.mselect-list').prev(), rateValue=that.parent().find( 'input[type="checkbox"]').val();$( 'body').trigger( 'processStart');var ajaxOptions={ type:'POST', data:{ tax_calculation_rate_id:rateValue, form_key:$( 'input[name="form_key"]').val() }, dataType:'json', url:'<?=/*@escapeNotVerified */$block->getTaxRateDeleteUrl() ?>', success:function(result, status) { $( 'body').trigger( 'processStop');if(result.success) { that.parent().remove();select.find( 'option').each(function() { if(this.value===rateValue) { $(this).remove();} });select.trigger( 'change.hiddenSelect');} else { if(result.error_message) alert({ content:result.error_message });else alert({ content:'<?=/*@escapeNotVerified */__( 'An error occurred') ?>' });} }, error:function() { $( 'body').trigger( 'processStop');alert({ content:'<?=/*@escapeNotVerified */__( 'An error occurred') ?>' });} };$.ajax(ajaxOptions);}) .on( 'click.mselectAdd'
Definition: edit.phtml:164
graphQlQuery(string $query, array $variables=[], string $operationName='', array $headers=[])