Skip to content

Commit 109da86

Browse files
committed
#35906 GraphQL Routes query with fragments has issue in the category page #35906
- Changed from non-safe if statement to safe empty if statement
1 parent bcb0fea commit 109da86

File tree

2 files changed

+137
-3
lines changed

2 files changed

+137
-3
lines changed

app/code/Magento/CatalogGraphQl/Model/Category/DepthCalculator.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use GraphQL\Language\AST\FieldNode;
1212
use GraphQL\Language\AST\InlineFragmentNode;
1313
use GraphQL\Language\AST\NodeKind;
14+
use GraphQL\Language\AST\SelectionNode;
1415
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1516

1617
/**
@@ -66,21 +67,21 @@ private function calculateRecursive(ResolveInfo $resolveInfo, Node $node) : int
6667
* Add inline fragment fields into calculating of category depth
6768
*
6869
* @param ResolveInfo $resolveInfo
69-
* @param InlineFragmentNode $inlineFragmentField
70+
* @param SelectionNode $inlineFragmentField
7071
* @param array $depth
7172
* @return int
7273
*/
7374
private function addInlineFragmentDepth(
7475
ResolveInfo $resolveInfo,
75-
InlineFragmentNode $inlineFragmentField,
76+
SelectionNode $inlineFragmentField,
7677
$depth = []
7778
): int {
7879
$selections = $inlineFragmentField->selectionSet->selections;
7980
/** @var FieldNode $field */
8081
foreach ($selections as $field) {
8182
if ($field->kind === NodeKind::INLINE_FRAGMENT) {
8283
$depth[] = $this->addInlineFragmentDepth($resolveInfo, $field, $depth);
83-
} elseif ($field->selectionSet && $field->selectionSet->selections) {
84+
} elseif (!empty($field->selectionSet) && $field->selectionSet->selections) {
8485
$depth[] = $this->calculate($resolveInfo, $field);
8586
}
8687
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
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\CatalogGraphQl\Test\Unit\Model\Resolver\Category;
9+
10+
use GraphQL\Language\AST\FieldNode;
11+
use GraphQL\Language\AST\InlineFragmentNode;
12+
use GraphQL\Language\AST\NodeKind;
13+
use GraphQL\Language\AST\NodeList;
14+
use GraphQL\Language\AST\SelectionSetNode;
15+
use Magento\CatalogGraphQl\Model\Category\DepthCalculator;
16+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class DepthCalculatorTest extends TestCase
21+
{
22+
/**
23+
* @var DepthCalculator
24+
*/
25+
private DepthCalculator $depthCalculator;
26+
27+
/**
28+
* @var ResolveInfo|MockObject
29+
*/
30+
private $resolveInfoMock;
31+
32+
/**
33+
* @var FieldNode|MockObject
34+
*/
35+
private $fieldNodeMock;
36+
37+
/**
38+
* Await for depth of '1' if selectionSet is null
39+
* @return void
40+
*/
41+
public function testCalculateWithNullAsSelectionSet(): void
42+
{
43+
$this->fieldNodeMock->kind = NodeKind::FIELD;
44+
/** @var SelectionSetNode $selectionSetMock */
45+
$selectionSetMock = $this->createMock(SelectionSetNode::class);
46+
$selectionSetMock->selections = $this->getMockSelectionsArrayForNullCase();
47+
$this->fieldNodeMock->selectionSet = $selectionSetMock;
48+
$result = $this->depthCalculator->calculate($this->resolveInfoMock, $this->fieldNodeMock);
49+
$this->assertEquals(1, $result);
50+
}
51+
52+
/**
53+
* Await for depth of '2' if selectionSet is not null
54+
* @return void
55+
*/
56+
public function testCalculateNonNullAsSelectionSet(): void
57+
{
58+
$this->fieldNodeMock->kind = NodeKind::FIELD;
59+
$selectionSetMock = $this->createMock(SelectionSetNode::class);
60+
$selectionSetMock->selections = $this->getMockSelectionsArrayForNonNullCase();
61+
$this->fieldNodeMock->selectionSet = $selectionSetMock;
62+
$result = $this->depthCalculator->calculate($this->resolveInfoMock, $this->fieldNodeMock);
63+
$this->assertEquals(2, $result);
64+
}
65+
66+
/**
67+
* @return NodeList
68+
*/
69+
private function getMockSelectionsArrayForNullCase()
70+
{
71+
/** @var SelectionSetNode $selectionSetMock */
72+
$selectionSetMock = $this->createMock(SelectionSetNode::class);
73+
$selectionSetMock->selections = [$this->getNewFieldNodeMock()];
74+
$inlineFragmentMock = $this->getNewInlineFragmentNodeMock();
75+
$inlineFragmentMock->selectionSet = $selectionSetMock;
76+
return new NodeList([
77+
$this->getNewFieldNodeMock(),
78+
$inlineFragmentMock
79+
]);
80+
}
81+
82+
/**
83+
* @return FieldNode|MockObject
84+
*/
85+
private function getNewFieldNodeMock()
86+
{
87+
return $this->getMockBuilder(FieldNode::class)
88+
->setConstructorArgs(['vars' => []])
89+
->getMock();
90+
}
91+
92+
/**
93+
* @return InlineFragmentNode|MockObject
94+
*/
95+
private function getNewInlineFragmentNodeMock()
96+
{
97+
return $this->getMockBuilder(InlineFragmentNode::class)
98+
->disableOriginalConstructor()
99+
->getMock();
100+
}
101+
102+
/**
103+
* @return NodeList
104+
*/
105+
private function getMockSelectionsArrayForNonNullCase()
106+
{
107+
$newFieldMock = $this->getNewFieldNodeMock();
108+
$newFieldMock->selectionSet = $this->createMock(SelectionSetNode::class);
109+
$newFieldMock->selectionSet->selections = [$this->getNewFieldNodeMock()];
110+
/** @var SelectionSetNode $selectionSetMock */
111+
$selectionSetMock = $this->createMock(SelectionSetNode::class);
112+
$selectionSetMock->selections = [$newFieldMock];
113+
114+
$inlineFragmentMock = $this->getNewInlineFragmentNodeMock();
115+
$inlineFragmentMock->selectionSet = $selectionSetMock;
116+
return new NodeList([
117+
$this->getNewFieldNodeMock(),
118+
$inlineFragmentMock
119+
]);
120+
}
121+
122+
/**
123+
* @inheritDoc
124+
*/
125+
protected function setUp(): void
126+
{
127+
$this->depthCalculator = new DepthCalculator();
128+
$this->resolveInfoMock = $this->createMock(ResolveInfo::class);
129+
$this->fieldNodeMock = $this->getMockBuilder(FieldNode::class)
130+
->disableOriginalConstructor()
131+
->getMock();
132+
}
133+
}

0 commit comments

Comments
 (0)